Уткнулся в непонятную проблему. Если включить прерывания для UART, то перестаёт работать прерывание SysTick_Handler.
Инициализация тактирования системы:
Спойлер
Код: Выделить всё
// Range 1 Boost
SET_BIT(PWR->CR5, PWR_CR5_R1MODE);
// HSE
SET_BIT(RCC->CR, RCC_CR_HSEON);
while (READ_BIT(RCC->CR, RCC_CR_HSERDY) == 0U) asm("");
// disable PLL
CLEAR_BIT(RCC->CR, RCC_CR_PLLON);
// config PLL
MODIFY_REG(
RCC->PLLCFGR,
(RCC_PLLCFGR_PLLSRC | RCC_PLLCFGR_PLLM | RCC_PLLCFGR_PLLN | RCC_PLLCFGR_PLLQ | RCC_PLLCFGR_PLLR | RCC_PLLCFGR_PLLPDIV),
(
RCC_PLLCFGR_PLLSRC_HSE | // PLL source
((( 1 ) - 1U) << RCC_PLLCFGR_PLLM_Pos) | // PLLM = 1 .. 16
(( 36 ) << RCC_PLLCFGR_PLLN_Pos) | // PLLN
(((( 6 ) >> 1U) - 1U) << RCC_PLLCFGR_PLLQ_Pos) | // PLLQ = 2, 4, 6, 8
(((( 2 ) >> 1U) - 1U) << RCC_PLLCFGR_PLLR_Pos) | // PLLR = 2, 4, 6, 8
(( 2 ) << RCC_PLLCFGR_PLLPDIV_Pos) // PLLP = 2 .. 31
)
);
// enable PLL
SET_BIT(RCC->CR, RCC_CR_PLLON);
// Enable PLL System Clock output: PLLCLK selection from main PLL
SET_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLREN);
/* Wait till PLL is ready */
while (READ_BIT(RCC->CR, RCC_CR_PLLRDY) == 0U) asm("");
//volatile uint32_t
// pcr5 = PWR->CR5,
// cr = RCC->CR,
// pll = RCC->PLLCFGR;
/* Increasing the number of wait states because of higher CPU frequency */
if (READ_BIT(FLASH->ACR, FLASH_ACR_LATENCY) < FLASH_ACR_LATENCY_4WS)
/* Program the new number of wait states to the LATENCY bits in the FLASH_ACR register */
MODIFY_REG(FLASH->ACR, FLASH_ACR_LATENCY, FLASH_ACR_LATENCY_4WS);
//volatile uint32_t pllf = RCC_GetSysClockFreqFromPLLSource();
/* Intermediate step with HCLK prescaler 2 necessary before to go over 80Mhz */
MODIFY_REG(RCC->CFGR, RCC_CFGR_HPRE, RCC_CFGR_HPRE_DIV2);
// SYSCLKSource
MODIFY_REG(RCC->CFGR, RCC_CFGR_SW, RCC_CFGR_SW_PLL);
while (READ_BIT(RCC->CFGR, RCC_CFGR_SWS) != (RCC_CFGR_SW_PLL << RCC_CFGR_SWS_Pos)) asm("");
/* Set the highest APB divider in order to ensure that we do not go through
a non-spec phase whatever we decrease or increase HCLK. */
MODIFY_REG(RCC->CFGR, RCC_CFGR_PPRE1, RCC_CFGR_PPRE1_DIV16);
MODIFY_REG(RCC->CFGR, RCC_CFGR_PPRE2, RCC_CFGR_PPRE2_DIV16);
/* Set the new HCLK clock divider */
MODIFY_REG(RCC->CFGR, RCC_CFGR_HPRE, RCC_CFGR_HPRE_DIV1);
/*-------------------------- PCLK1 Configuration ---------------------------*/
MODIFY_REG(RCC->CFGR, RCC_CFGR_PPRE1, RCC_CFGR_PPRE1_DIV1);
/*-------------------------- PCLK2 Configuration ---------------------------*/
MODIFY_REG(RCC->CFGR, RCC_CFGR_PPRE2, RCC_CFGR_PPRE2_DIV1);
//volatile uint32_t SystemCoreClock =
// HAL_RCC_GetSysClockFreq() >> (AHBPrescTable[READ_BIT(RCC->CFGR, RCC_CFGR_HPRE) >> RCC_CFGR_HPRE_Pos] & 0x1FU);
// в аргументе передаётся делитель (количество тиков для срабатывания прерывания)
SysTick_Config(SYSCLOCK_FREQ / 1000U); // частота в Гц / 1000 = интервал 1мс
Код: Выделить всё
#define SYSCLOCK_FREQ 144000000ULСпойлер
Код: Выделить всё
#define UARTNUM 3
/* Configure the UART clock source */
#define __uartccip(uartn) RCC_CCIPR_USART ## uartn ## SEL
#define UART_CCIP(uartn) __uartccip(uartn)
MODIFY_REG(RCC->CCIPR, UART_CCIP(UARTNUM), 0 /* RCC_USART3CLKSOURCE_PCLK1 */);
/* Peripheral clock enable */
#define __uarten(uartn) RCC_APB1ENR1_USART ## uartn ## EN
#define UART_EN(uartn) __uarten(uartn)
SET_BIT(RCC->APB1ENR1, UART_EN(UARTNUM));
// GPIOB
/*
*USART3 GPIO Configuration
PB10 ------> USART3_TX
PB11 ------> USART3_RX
*/
SET_BIT(RCC->AHB2ENR, RCC_AHB2ENR_GPIOBEN);
GPIO_SPEED (PINGRP, PINRX, LOW);
GPIO_TYPE (PINGRP, PINRX, PUSHPULL);
GPIO_PUPD (PINGRP, PINRX, NOPULL);
GPIO_MODE (PINGRP, PINRX, ALTERNATE);
GPIO_AF (PINGRP, PINRX, 0x07);
GPIO_SPEED (PINGRP, PINTX, LOW);
GPIO_TYPE (PINGRP, PINTX, PUSHPULL);
GPIO_PUPD (PINGRP, PINTX, NOPULL);
GPIO_MODE (PINGRP, PINTX, ALTERNATE);
GPIO_AF (PINGRP, PINTX, 0x07);
/* TX, RX enable */
UART->CR1 = USART_CR1_TE | USART_CR1_RE | USART_CR1_TXEIE | USART_CR1_RXNEIE;
UART->CR2 = 0;
UART->CR3 = 0;
/* UART_PRESCALER_DIV1 */
UART->PRESC = 0;
/* в нашем случае PLLclk = SysClk */
uint64_t clk = SYSCLOCK_FREQ;
uint32_t baud = 115200;
UART->BRR = (clk + (baud >> 1)) / baud;
/* UART enable */
SET_BIT(UART->CR1, USART_CR1_UE);
#define __uartirq(uartn) USART ## uartn ## _IRQn
#define UART_IRQ(uartn) __uartirq(uartn)
NVIC_SetPriority(UART_IRQ(UARTNUM), 0);
NVIC_EnableIRQ(UART_IRQ(UARTNUM));
Спойлер
Код: Выделить всё
static uint8_t _tx[64], *_tc = NULL;
static size_t _tsz = 0;
static void _tx_send() {
if (_tsz <= 0)
return;
UART->TDR = *_tc;
_tc++;
_tsz--;
}
#define __uartit(uartn, itn) USART ## uartn ## _IRQHandler
#define UART_IT(uartn, itn) __uartit(uartn, itn)
void UART_IT(UARTNUM,0)(void) {
if (UART->ISR & (USART_ISR_TXE | USART_ISR_TXE_TXFNF))
_tx_send();
if (UART->ISR & (USART_ISR_RXNE | USART_ISR_RXNE_RXFNE)) {
volatile auto r = UART->RDR;
volatile uint8_t n = 1;
}
if (UART->ISR & USART_ISR_IDLE)
UART->ICR = USART_ICR_IDLECF;
if (UART->ISR & USART_ISR_TC)
UART->ICR = USART_ICR_TCCF;
}
Спойлер
Код: Выделить всё
static volatile uint32_t _tick = 0;
void SysTick_Handler(void) {
_tick ++;
static uint16_t _tick_1s = 0;
_tick_1s++;
if (_tick_1s >= 1000) {
_tick_1s = 0;
}
}Код: Выделить всё
NVIC_EnableIRQ(UART_....)При срабатывании прерывания UART регистр ISR вот такой: 0x600080, вместо 8 бывает d и c если делать обработчик проще (оставлять только обработку tx).
Вообще, я это обнаружил случайно, хотел из SysTick для отладки отправлять раз в секунду hello в этот uart, но хотелось бы всё-таки разобраться, что делаю не так.


