博主写完bootloader后,APP程序这边不管怎么样freeRTOS都不运行,最基本的LED闪烁任务创建都有问题,
bootloader主函数如下:
#include "main.h"
#include "user_header.h"
typedef void ( *pFunction )( void );
pFunction Jump_To_Application; //函数指针
uint32_t JumpAddress = 0;
void delay_1( void )
{
uint16_t nTime = 0x0000;
for( nTime = 0; nTime < 0x0FFF; nTime++ ) {
}
}
void BKP_RtcInit( void )
{
/* enable PMU clock */
rcu_periph_clock_enable( RCU_PMU );
rcu_periph_clock_enable( RCU_RTC );
/* enable the access of the RTC registers */
pmu_backup_write_enable();//使能对BKP寄存器的访问
}
int main( void )
{
//systick_config();
static uint16_t timeOutCnt = 0;
BSP_Init();
BKP_RtcInit();
printf( "APP\n" );
//BKP_DATA6 = 0x0000;
if( ( BKP_DATA6&BKP_BOOT )== BKP_BOOT ) { //APP跳转过来
printf( "APP Enter Boot Succeed" );
//响应APP接收
transmit_message.tx_data[0] = 0x60;
transmit_message.tx_data[1] = 0x55;
transmit_message.tx_data[2] = 0x22;
transmit_message.tx_data[3] = 0xff;
transmit_message.tx_data[4] = 0xff;
transmit_message.tx_data[5] = 0xff;
transmit_message.tx_data[6] = 0xff;
CAN_ProtocolSendData( CF,7 );
usartProtocol_str.functionCode = 0x11;
usartProtocol_str.Data[0] = 0x22;
usartProtocol_str.Data[1] = 0xff;
usartProtocol_str.Data[2] = 0xff;
usartProtocol_str.Data[3] = 0xff;
usartProtocol_str.Data[4] = 0xff;
UART_ProtocolSendData( usartProtocol_str.functionCode,usartProtocol_str.Data,5 );
}
while( 1 ) {
if( ( BKP_DATA6&BKP_BOOT ) == BKP_APP ) {
if( ( BKP_DATA6&BKP_REAL_APP )!= BKP_REAL_APP ) { //APP运行区域数据是否有效
if( ( ( *( __IO uint32_t * )AppRealAddress ) & 0x2FFE0000 ) == 0x20000000 ) { //ApplicationAddress为新程序的起始地址,检查栈顶地址是否合法,即栈顶地址是否为0x2000xxxx(内置SRAM)
printf( "JMP TO APP" );
can_interrupt_disable( CAN0, CAN_INTEN_RFNEIE1 ); //FIFO1
can_interrupt_disable( CAN0, CAN_INTEN_RFNEIE0 ); //FIFO0
NVIC_ClearPendingIRQ( SysTick_IRQn );
usart_disable( USART0 );
usart_disable( USART2 );
/*配置跳转到用户程序复位中断入口*/
JumpAddress = *( __IO uint32_t * )( AppRealAddress + 4 ); //用户代码区第二个字存储为新程序起始地址(新程序复位向量指针)
/*将地址指针强制转换成函数指针*/
Jump_To_Application = ( pFunction ) JumpAddress;
/*设置栈*/
__set_MSP( *( __IO uint32_t * ) AppRealAddress ); //初始化APP堆栈指针(用户代码区的第一个字用于存放栈顶地址)
/*跳转*/
Jump_To_Application(); //设置PC指针为新程序复位中断函数的地址
} else {
BKP_DATA6 = BKP_DATA6 | BKP_BOOT; //文件错误则处于boot,直到升级成功
}
} else {
//让系统处于BOOT区域
//此时如果备份APP有效可以把备份APP数据拷贝到运行APP区域...
BKP_DATA6 = BKP_DATA6 | BKP_BOOT;
}
} else { //等待升级
printf( "Wait for upgrade\n" );
//串口升级
if( Uart_Fram_Record_Struct.InfBit.FramLength1!=0 ) {
UART_Firmware_Update( Uart_Fram_Record_Struct.Data_uart1_RX_BUF );
Uart_Fram_Record_Struct.InfBit.FramLength1 = 0;
timeOutCnt = 0;
}
//CAN升级
if( CanUserDataType.canId != 0x00000000 ) {
CAN_Firmware_Update( &CanUserDataType ); //CAN数据处理进程
CanUserDataType.canId = 0x00000000;
timeOutCnt = 0;
}
timeOutCnt++;
if( timeOutCnt >= 50000 ) { //超时
timeOutCnt = 0;
printf( "UpData Time Out" );
if( BKP_DATA6 & BKP_REAL_APP ) { //APP运行区无效
} else {
BKP_DATA6 = 0x0000; //APP运行区无效
}
} else {
delay_1();
}
}
}
}
APP主函数如下:
#include "user_header.h"
TaskHandle_t Task1_Handler;
void task1(void *pvParameters) {
while(1) {
vTaskDelay(200);
gpio_bit_set(GPIOA, GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7);
vTaskDelay(200);
gpio_bit_reset(GPIOA, GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7);
}
}
void GPIO_config() {
/* enable the LED1 GPIO clock */
rcu_periph_clock_enable(RCU_GPIOA);
/* configure LED1 GPIO port */
gpio_init(GPIOA, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ,GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7);
/* reset LED1 GPIO pin */
gpio_bit_reset(GPIOA,GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7);
}
void BKP_RtcInit( void )
{
/* enable PMU clock */
rcu_periph_clock_enable( RCU_PMU );
rcu_periph_clock_enable( RCU_RTC );
/* enable the access of the RTC registers */
pmu_backup_write_enable();//使能对BKP寄存器的访问
}
int main(void)
{
//systick_config(); //系统滴答
nvic_vector_table_set(NVIC_VECTTAB_FLASH, 0x4000); //设置向量表基地址(重映射向量表) :基地址+偏移量
/*设置中断优先级*/
nvic_priority_group_set(NVIC_PRIGROUP_PRE3_SUB1); //3位抢占 1位响应
GPIO_config(); //LED的GPIO初始化
BKP_RtcInit(); //使能BKP
USART2_Init(); //串口2初始化
#if CAN0_OPEN==1
can_gpio_config(); //CAN初始化
can_config();
/* initialize transmit message */
can_struct_para_init(CAN_TX_MESSAGE_STRUCT, &g_transmit_message);//结构体初始化
g_transmit_message.tx_sfid = 0x00; //标准格式帧标识符
g_transmit_message.tx_efid = 0x18FEEEBB; //扩展格式帧标识符
g_transmit_message.tx_ft = CAN_FT_DATA; //帧类型:数据帧/远程帧
g_transmit_message.tx_ff = CAN_FF_EXTENDED; //帧格式:标准帧/扩展帧
g_transmit_message.tx_dlen = 8; //数据长度
g_transmit_message.fd_flag = 0; //FD帧标志位
g_transmit_message.fd_brs = 1; //位速率转换开关
g_transmit_message.fd_esi = 0; //错误状态指示
/* initialize receive message */
can_struct_para_init(CAN_RX_MESSAGE_STRUCT, &g_receive_message);//接收结构体初始
#endif
taskENTER_CRITICAL(); /* 进入临界区 */
xTaskCreate((TaskFunction_t)task1,
(const char* )"task1",
50,
NULL,
5,
(TaskHandle_t* )&Task1_Handler);
taskEXIT_CRITICAL(); /* 退出临界区 */
vTaskStartScheduler();
while(1) {}
}
经过反复排查,FreeRTOSConfig.h文件中设定的任务优先级后,
#define configMAX_PRIORITIES ( 5 ) //任务优先级
APP创建任务优先级给得过高,任务创建优先级调整后,RTOS运行依旧不正常。
taskENTER_CRITICAL(); /* 进入临界区 */
xTaskCreate((TaskFunction_t)task1,
(const char* )"task1",
50,
NULL,
3,
(TaskHandle_t* )&Task1_Handler);
taskEXIT_CRITICAL(); /* 退出临界区 */
vTaskStartScheduler();
经过仔细排查,发现FreeRTOS可以干预的最高优先级,文件默认给的5(单片机数字越低,优先级越高),优先级很低。
#define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY 5
重新调整FreeRTOS可以干预的优先级,改为如下
#define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY 1
调整后,程序运行正常,说明就是任务优先级+FreeRTOS系统最高干预优先级引起。