[STM32F4]

STM32F4移植FreeRTOS V10.3.1

[复制链接]
329|16
手机看帖
扫描二维码
随时随地手机跟帖
木木guainv|  楼主 | 2021-7-1 11:46 | 显示全部楼层 |阅读模式
一、环境

Win10、Keil uVision5、STM32CubeMX、STM32F429IGT6

二、准备工作2.1创建基于HAL库的STM32F429基础工程

    创建新项目,MCU型号选择STM32F429IGTx,然后开始项目。

watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3NtYWxsZXJ4dWFu,size_16,color_FFFFFF,t_70.jpg


使用特权

评论回复
木木guainv|  楼主 | 2021-7-1 11:46 | 显示全部楼层

选择使用外部高速时钟,时钟源为外部晶振,然后配置系统时钟,根据晶振频率将系统时钟配置到180MHz。


watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3NtYWxsZXJ4dWFu,size_16,color_FFFFFF,t_70.jpg

watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3NtYWxsZXJ4dWFu,size_16,color_FFFFFF,t_70.jpg


使用特权

评论回复
木木guainv|  楼主 | 2021-7-1 11:46 | 显示全部楼层

配置USART1为异步收发串口模式,设定为115200波特率,8位数据位,1位停止位,无奇偶校验,配置USART1相关外设IO引脚,启用USART1 DMA收发传输,启用USART1中断和其DMA收发关联通道中断并设定优先级。


watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3NtYWxsZXJ4dWFu,size_16,color_FFFFFF,t_70.jpg

watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3NtYWxsZXJ4dWFu,size_16,color_FFFFFF,t_70.jpg

watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3NtYWxsZXJ4dWFu,size_16,color_FFFFFF,t_70.jpg

watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3NtYWxsZXJ4dWFu,size_16,color_FFFFFF,t_70.jpg

watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3NtYWxsZXJ4dWFu,size_16,color_FFFFFF,t_70.jpg


使用特权

评论回复
木木guainv|  楼主 | 2021-7-1 11:47 | 显示全部楼层

在项目管理子页面对项目相关配置项以及代码生成项进行相关配置。


watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3NtYWxsZXJ4dWFu,size_16,color_FFFFFF,t_70.jpg

watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3NtYWxsZXJ4dWFu,size_16,color_FFFFFF,t_70.jpg


使用特权

评论回复
木木guainv|  楼主 | 2021-7-1 11:47 | 显示全部楼层

建议对HAL时基源选择为SysTick以外的时钟源。

watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3NtYWxsZXJ4dWFu,size_16,color_FFFFFF,t_70.jpg


使用特权

评论回复
木木guainv|  楼主 | 2021-7-1 11:47 | 显示全部楼层

以上步骤完成后点击生成代码,代码生成完以后用Keil uVision5打开项目并进行编译,此时编译应该是能正常编译的。

watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3NtYWxsZXJ4dWFu,size_16,color_FFFFFF,t_70.jpg

经过以上步骤,我们创建了不含有FreeRTOS的基础工程(如果想使用CMSIS接口的也可以在配置时直接勾选使用FreeRTOS中间件)。


使用特权

评论回复
木木guainv|  楼主 | 2021-7-1 11:48 | 显示全部楼层
2.2获取FreeRTOS源码
FreeRTOS作为开源RTOS,允许开源商用,可以在其官方网站找到源码获取入口(官方网址为:www.freertos.org)。进入官网后,在首页点击下载FreeRTOS,进入下载页面点击下载。这里我获取的是FreeRTOS V10.3.1的源码。

327260dd3af8b1e26.png


5702060dd3b0133fdc.png

使用特权

评论回复
木木guainv|  楼主 | 2021-7-1 11:48 | 显示全部楼层
三、FreeRTOS移植
       在STM32CubeMX生成的项目目录中添加子目录FreeRTOS。将官方源码中Source目录中的所有内容全部复制到我们创建的FreeRTOS目录下。保留FreeRTOS\portable目录下的Keil、MemMang、RVDS,其他的可以删除(其实Keil也可以删除)。



20200625152656422.png

watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3NtYWxsZXJ4dWFu,size_16,color_FFFFFF,t_70.jpg

watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3NtYWxsZXJ4dWFu,size_16,color_FFFFFF,t_70.jpg

20200625152734137.png


使用特权

评论回复
木木guainv|  楼主 | 2021-7-1 11:49 | 显示全部楼层
在Keil uVision5中创建分组FreeRTOS_CORE、FreeRTOS_PORTABLE。将FreeRTOS目录下的croutine.c、event_groups.c、list.c、queue.c、stream_buffer.c、tasks.c、timers.c全部添加到分组FreeRTOS_CORE。将FreeRTOS\portable\MemMang\heap_4.c和FreeRTOS\portable\RVDS\ARM_CM4F\port.c添加到分组FreeRTOS_PORTABLE。

watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3NtYWxsZXJ4dWFu,size_16,color_FFFFFF,t_70.jpg

watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3NtYWxsZXJ4dWFu,size_16,color_FFFFFF,t_70.jpg


使用特权

评论回复
木木guainv|  楼主 | 2021-7-1 11:49 | 显示全部楼层

然后将FreeRTOS的相关头文件路径添加到项目中。

watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3NtYWxsZXJ4dWFu,size_16,color_FFFFFF,t_70.jpg


使用特权

评论回复
木木guainv|  楼主 | 2021-7-1 11:50 | 显示全部楼层

将官方Demo中的FreeRTOS复制到我们的工程目录FreeRTOS\include中去。

watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3NtYWxsZXJ4dWFu,size_16,color_FFFFFF,t_70.jpg








watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3NtYWxsZXJ4dWFu,size_16,color_FFFFFF,t_70.jpg


使用特权

评论回复
木木guainv|  楼主 | 2021-7-1 11:52 | 显示全部楼层

将FreeRTOSConfig.h中第45行左右的 #ifdef __ICCARM__ 修改为 #ifdef __CC_ARM以便和我们使用的编译器匹配。

watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3NtYWxsZXJ4dWFu,size_16,color_FFFFFF,t_70.jpg

watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3NtYWxsZXJ4dWFu,size_16,color_FFFFFF,t_70.jpg


使用特权

评论回复
木木guainv|  楼主 | 2021-7-1 11:53 | 显示全部楼层
将FreeRTOSConfig.h中目前没有实现的没有使用的钩子函数开启宏关闭(官方Demo中开启了这些宏):configUSE_IDLE_HOOK、configUSE_TICK_HOOK、configCHECK_FOR_STACK_OVERFLOW、configUSE_MALLOC_FAILED_HOOK。


watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3NtYWxsZXJ4dWFu,size_16,color_FFFFFF,t_70.jpg

watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3NtYWxsZXJ4dWFu,size_16,color_FFFFFF,t_70.jpg


使用特权

评论回复
木木guainv|  楼主 | 2021-7-1 11:53 | 显示全部楼层
打开文件stm32f4xx_it.c,找到SVC_Handler、PendSV_Handler、SysTick_Handler的函数定义将其屏蔽,因为这三个函数和FreeRTOS内核息息相关,在FreeRTOS内核源码中有具体实现,屏蔽掉是为了祛除重定义。

watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3NtYWxsZXJ4dWFu,size_16,color_FFFFFF,t_70.jpg

watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3NtYWxsZXJ4dWFu,size_16,color_FFFFFF,t_70.jpg




这时候编译,会正常通过。


使用特权

评论回复
木木guainv|  楼主 | 2021-7-1 11:54 | 显示全部楼层
四、添加基础功能

经过以上步骤实际上已经基本完成了FreeRTOS V10.3.1在STM32F429IGT6的移植,但是为了方便测试,我们还将添加一些基础功能。

4.1串口DMA发送

添加USART1_Tx DMA传输N字节相关代码段:

#define USART1_TX_DMA_BUFFER_MAX_SIZE 1024
uint8_t Usart1_Tx_DMA_Buffer[USART1_TX_DMA_BUFFER_MAX_SIZE+1];
uint16_t Usart1_DMASend_NBytes(uint8_t* buffer, uint16_t size)
{
        uint16_t size_t=0;
        if(!size) return 0;
        size_t = (size > USART1_TX_DMA_BUFFER_MAX_SIZE ? USART1_TX_DMA_BUFFER_MAX_SIZE : size);       
        while(0 != __HAL_DMA_GET_COUNTER(&hdma_usart1_tx)){;}  
  if(buffer!=NULL)
        {
                memcpy(&Usart1_Tx_DMA_Buffer[0], buffer,size_t);
        }
  HAL_UART_Transmit_DMA(&huart1, Usart1_Tx_DMA_Buffer, size_t);               
  return size;
}


使用特权

评论回复
木木guainv|  楼主 | 2021-7-1 11:54 | 显示全部楼层
创建几个简单的FreeRTOS任务:

#define START_TASK_PRIO                1                                                                                                 
#define START_STK_SIZE                 128                                                                                   
TaskHandle_t StartTask_Handler;                                                                                 
void start_task(void *pvParameters);                                                         

#define USART1_SEND_TASK_PRIO                2                                                                         
#define USART1_SEND_STK_SIZE                 256                                                                  
TaskHandle_t USART1_SendTask_Handler;                                                         
void USART1_Send_task(void *pvParameters);                       

#define APP_TASK_PRIO                3                                                                 
#define APP_STK_SIZE                 256                                                                  
TaskHandle_t APP_Task_Handler;                                                         
void APP_task(void *pvParameters);

#define SENSOR_TASK_PRIO                4                                                         
#define SENSOR_STK_SIZE                 256                                                                  
TaskHandle_t Sensor_Task_Handler;                                                         
void Sensor_task(void *pvParameters);

#define USART1_TX_Q_NUM    5                   
QueueHandle_t Queue_Usart1_tx;          

#define MAX_FRAME_COMM_BUFFER_SIZE USART1_TX_DMA_BUFFER_MAX_SIZE
typedef struct
{
    uint8_t* start_addr;                         
    uint16_t len;                                              
}Usart1_Tx_Buffer_Typedef;

int main(void)
{
        BaseType_t TaskCreateStatus;       
  HAL_Init();
  SystemClock_Config();
  MX_GPIO_Init();
  MX_DMA_Init();
  MX_USART1_UART_Init();
       
  TaskCreateStatus= xTaskCreate((TaskFunction_t )start_task,
                (const char*    )"start_task",                 
                (uint16_t       )START_STK_SIZE,        
                (void*          )NULL,  
                (UBaseType_t    )START_TASK_PRIO,  
                (TaskHandle_t*  )&StartTask_Handler);
        if(pdPASS == TaskCreateStatus)
        {
                //printf(" start_task create success\r\n");
        }
    vTaskStartScheduler();         

  while (1)
  {
  }
}

void start_task(void *pvParameters)
{
        BaseType_t TaskCreateStatus;          
        taskENTER_CRITICAL();           
  Queue_Usart1_tx=xQueueCreate(USART1_TX_Q_NUM,sizeof(Usart1_Tx_Buffer_Typedef));   
  TaskCreateStatus= xTaskCreate((TaskFunction_t )USART1_Send_task,            
                (const char*    )"USART1_Send_task",          
                (uint16_t       )USART1_SEND_STK_SIZE,
                (void*          )NULL,                               
                (UBaseType_t    )USART1_SEND_TASK_PRIO,       
                (TaskHandle_t*  )&USART1_SendTask_Handler);  
        if(pdPASS == TaskCreateStatus)
        {
                //printf(" LED0Task create success\r\n");
        }
  TaskCreateStatus= xTaskCreate((TaskFunction_t )APP_task,            
                (const char*    )"APP_task",          
                (uint16_t       )APP_STK_SIZE,
                (void*          )NULL,                               
                (UBaseType_t    )APP_TASK_PRIO,       
                (TaskHandle_t*  )&APP_Task_Handler);  
        if(pdPASS == TaskCreateStatus)
        {
                //printf(" LED0Task create success\r\n");
        }
  TaskCreateStatus= xTaskCreate((TaskFunction_t )Sensor_task,            
                (const char*    )"Sensor_task",          
                (uint16_t       )SENSOR_STK_SIZE,
                (void*          )NULL,                               
                (UBaseType_t    )SENSOR_TASK_PRIO,       
                (TaskHandle_t*  )&Sensor_Task_Handler);  
        if(pdPASS == TaskCreateStatus)
        {
                //printf(" LED0Task create success\r\n");
        }                                       
        vTaskDelete(StartTask_Handler);
  taskEXIT_CRITICAL();            
}

void USART1_SendData(uint8_t *pData,uint16_t len)
{       
    Usart1_Tx_Buffer_Typedef         Tx_Buff;
       
    Tx_Buff.start_addr         = pData;
    Tx_Buff.len                                 = len;
    xQueueSendToBack(Queue_Usart1_tx,(void *)&Tx_Buff,portMAX_DELAY);  
}
               
void USART1_Send_task(void *pvParameters)
{
                Usart1_Tx_Buffer_Typedef Tx_Type;
                BaseType_t res = pdTRUE;
    while(1)
    {
        res = xQueueReceive(Queue_Usart1_tx,&Tx_Type,portMAX_DELAY);  
                                if(res == pdTRUE) Usart1_DMASend_NBytes(Tx_Type.start_addr,Tx_Type.len);//通过DMA发送       
                          vTaskDelay(10);   
    }
}

void APP_task(void *pvParameters)
{
        uint8_t testOut[128];
        uint32_t index=0;
        while(1)
        {
                sprintf((char*)testOut,"APP_task %u \r\n",index++);
                USART1_SendData(testOut,strlen((const char*)testOut));
                vTaskDelay(100);                           
        }
}

void Sensor_task(void *pvParameters)
{
        uint8_t testOut2[128];
        uint32_t index=0;
        while(1)
        {
                sprintf((char*)testOut2,"Sensor_task %u \r\n",index++);
                USART1_SendData(testOut2,strlen((const char*)testOut2));
                vTaskDelay(100);                        
        }
}


使用特权

评论回复
木木guainv|  楼主 | 2021-7-1 11:54 | 显示全部楼层
4.2下载验证

将工程进行编译、下载验证,符合预期。

watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3NtYWxsZXJ4dWFu,size_16,color_FFFFFF,t_70.jpg


使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

134

主题

3820

帖子

5

粉丝