#include "includes.h" #define DEBUG_PORT USART6 // 系统TickCount volatile u32 Systick_TickCount = 0; // 启动原因代码 volatile uint32_t SYS_RSTSTS = 0; // 实现stdout的硬件输出 int stdout_putchar(int ch) { if(ch == '\n') { while(!(DEBUG_PORT->SR & LL_USART_SR_TXE)); DEBUG_PORT->DR = '\r'; } while(!(DEBUG_PORT->SR & LL_USART_SR_TXE)); DEBUG_PORT->DR = (uint8_t) ch; return ch; } u32 GetDelayTick(u32 ms) { return GetTickCount() + ms; } // 考虑了u32溢出翻转的情况 u8 IsTickOut(u32 OutTick) { u32 tick = GetTickCount(); if(tick > OutTick) { if(tick - OutTick > 0x80000000UL) return 0; return 1; } if(OutTick - tick > 0x80000000UL) return 1; return 0; } // 这个函数必须在初始化完成,中断开启以后才有效 void delay_ms(u32 ms) { u32 tick = GetDelayTick(ms); do { } while(!IsTickOut(tick)); } void delay_us(uint16_t us) { uint32_t j; while(us--) { j = SystemCoreClock / 1000000; while(j--); } } /* ************************************************************************* Bootloader和App跳转设计要点 1. Bootloader的程序在前面,大小为8K(0x08000000~0x08001FFF) App的程序在后面,从0x08002000开始,大小为0x3E000 2. Bootloader的内存在前面,大小为2K(0x20000000~0x200007FF) //App的内存在后面,从0x20000800开始,大小为0xF800 3. 从Bootloader跳转到App: 1)关闭全局中断响应(__disable_irq) 2)禁止中断允许(将各中断的允许位清零) 3)清除中断标志(将各中断的标志位清零) 4) 设置堆栈(MSP)为App的堆栈值 5)跳转到App的程序入口 4. 从App跳转到Bootloader: 直接系统复位,运行Bootloader 5. Bootloader工程的特殊处理 1)在Target页,按照上述要求设置IROM1和IRAM1 2)在Linker页,勾选“Use Memory Layout from Target Dialog” 6. App工程的特殊处理 1)在Target页,按照上述要求设置IROM1和IRAM1 2)在Linker页,勾选“Use Memory Layout from Target Dialog” 3) 在system_stm32l4xx.c中修改以下代码: a. 将宏定义VECT_TAB_OFFSET改为0x2000 b. 在SystemInit()函数最后,重新打开全局中断响应(__enable_irq) 7. 从App的任务中跳转到Bootloader,按第3条的方法试验不成功。 具体原因未明,可能是因为要关掉的中断太多,没有一一试验; 也可能是因为FreeRTOS将CPU的特权模式接管了,导致PSP、MSP设置无效等。 ************************************************************************* */ typedef void (*pIapFun_TypeDef)(void); //定义一个函数类型的参数. // 实现从Bootloader跳转到App void JumpToEntry(uint32_t addr) { printf("\r\nJump to 0x%08X\r\n", addr); __disable_irq(); SysTick->CTRL &= ~(SysTick_CTRL_ENABLE_Msk | SysTick_CTRL_TICKINT_Msk); __set_MSP(*(volatile uint32_t *) addr); ((pIapFun_TypeDef) (*(volatile uint32_t *) (addr + 4)))(); // 不应该到这里来 while(1) printf("."); } // 实现从App跳转到Bootloader void JumpToLoader() { printf("\r\nJump to 0x%08X\r\n", (uint32_t) FLASH_BASE); // 直接复位,跳转到Bootloader HAL_NVIC_SystemReset(); // 不应该到这里来 while(1) printf("."); } // 实现串口发送 USART_Handle huart1 = {USART1, 0, 0, 1, NULL, NULL, NULL, 0, NULL, NULL}; USART_Handle huart2 = {USART2, 0, 0, 1, NULL, NULL, NULL, 0, NULL, NULL}; USART_Handle huart3 = {USART3, 0, 0, 1, NULL, NULL, NULL, 0, NULL, NULL}; USART_Handle huart4 = {UART4, 0, 0, 1, NULL, NULL, NULL, 0, NULL, NULL}; USART_Handle huart6 = {USART6, 0, 0, 1, NULL, NULL, NULL, 0, NULL, NULL}; USART_Handle huart8 = {UART8, 0, 0, 1, NULL, NULL, NULL, 0, NULL, NULL}; USART_Handle huart10 = {UART10, 0, 0, 1, NULL, NULL, NULL, 0, NULL, NULL}; // 实现串口发送 void UART_Transmit(USART_Handle *huart, uint8_t *buf, uint16_t len) { while(len--) { while(!(huart->Instance->SR & LL_USART_SR_TXE)); huart->Instance->DR = *buf++; } while(!(huart->Instance->SR & LL_USART_SR_TC)); } // 实现以中断方式串口发送 void UART_TxISR_8BIT(USART_Handle *huart) { /* Check that a Tx process is ongoing */ if(!huart->BusyTx) return; if (huart->TxXferCount == 0U) { /* Disable the UART Transmit Data Register Empty Interrupt */ CLEAR_BIT(huart->Instance->CR1, USART_CR1_TXEIE); /* Enable the UART Transmit Complete Interrupt */ SET_BIT(huart->Instance->CR1, USART_CR1_TCIE); } else { huart->Instance->DR = (uint8_t)(*huart->pTxBuffPtr & (uint8_t)0xFF); huart->pTxBuffPtr++; huart->TxXferCount--; } } uint8_t UART_Transmit_IT(USART_Handle *huart, uint8_t *pData, uint16_t Size) { /* Check that a Tx process is not already ongoing */ if(huart->BusyTx) return 0; huart->pTxBuffPtr = pData; huart->TxXferCount = Size; huart->TxISR = UART_TxISR_8BIT; huart->BusyTx = 1; /* Enable the Transmit Data Register Empty interrupt */ SET_BIT(huart->Instance->CR1, USART_CR1_TXEIE); return 1; } // 应用程序的串口中断处理 void APP_USART_IRQHandler(USART_Handle *huart) { uint32_t isrflags = huart->Instance->SR; uint32_t cr1its = huart->Instance->CR1; uint32_t errorflags = (isrflags & ((uint32_t)(USART_SR_PE | USART_SR_FE | USART_SR_NE | USART_SR_ORE))); // 清除错误状态 LL_USART_ClearFlag_PE(huart->Instance); LL_USART_ClearFlag_FE(huart->Instance); LL_USART_ClearFlag_NE(huart->Instance); LL_USART_ClearFlag_ORE(huart->Instance); /* If no error occurs */ if (errorflags == 0U) { /* UART in mode Receiver ---------------------------------------------------*/ if (((isrflags & USART_SR_RXNE) != 0U) && ((cr1its & USART_CR1_RXNEIE) != 0U)) { if(huart->RxISR) huart->RxISR(huart); else huart->Instance->DR; } /* UART in mode Transmit ---------------------------------------------------*/ if (((isrflags & USART_SR_TXE) != 0U) && ((cr1its & USART_CR1_TXEIE) != 0U)) { if(huart->TxISR) huart->TxISR(huart); else { // 不应该到这里 CLEAR_BIT(huart->Instance->CR1, USART_CR1_TXEIE); huart->BusyTx = 0; } } /* UART in mode Transmitter (transmission end) -----------------------------*/ if (((isrflags & USART_SR_TC) != 0U) && ((cr1its & USART_CR1_TCIE) != 0U)) { /* Disable the UART Transmit Complete Interrupt */ CLEAR_BIT(huart->Instance->CR1, USART_CR1_TCIE); // 清除发送忙标志 huart->BusyTx = 0; } } } // 读取启动原因代码 void Fetch_ResetFlags() { if(LL_RCC_IsActiveFlag_PORRST()) SYS_RSTSTS |= 0x01; if(LL_RCC_IsActiveFlag_PINRST()) SYS_RSTSTS |= 0x02; if(LL_RCC_IsActiveFlag_IWDGRST()) SYS_RSTSTS |= 0x04; if(LL_RCC_IsActiveFlag_LPWRRST()) SYS_RSTSTS |= 0x08; if(LL_RCC_IsActiveFlag_BORRST()) SYS_RSTSTS |= 0x10; if(LL_RCC_IsActiveFlag_SFTRST()) { SYS_RSTSTS |= 0x20; SYS_RSTSTS &= ~0x13; } // 清除启动标志 __HAL_RCC_CLEAR_RESET_FLAGS(); }