258 lines
6.4 KiB
C
258 lines
6.4 KiB
C
#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();
|
||
}
|