【电子DIY】DIY行车记录仪为游戏机之主控软件开发(3)适配freertos

代码见:https://github.com/qinyunti/py32f403-nes.git

一.前言

为了后面方便复杂点的业务开发,我们来适配FreeRTOS。 下面分享整个过程。

二.添加代码

下载代码

git clone https://github.com/FreeRTOS/FreeRTOS-Kernel.git

提取FreeRTOS-Kernel内核文件

保留FreeRTOS-Kernel下以下c文件

212312x3i36c09llm3cvl0

保留FreeRTOS-Kernel\include文件夹,并添加到头文件包含路径。

复制portable\MemMang下的heap_4.c,如果使用其他的堆实现则复制对应的文件。

复制FreeRTOS-Kernel\portable\GCC\ARM_CM4F下的所有文件

复制examples/template_configuration/FreeRTOSConfig.h

添加后文件如下,设置include和FreeRTOSConfig.h所在路径到头文件包含路径

212312ecnytjzi2tg4khfv

工程添加文件如下

212312afx0sg0flpgx3gp0

三.配置

工程配置

212313kmr4b99j4t84inn8

FreeRTOSConfig.h中

#define configTICK_TYPE_WIDTH_IN_BITS              TICK_TYPE_WIDTH_64_BITS

改为

#define configTICK_TYPE_WIDTH_IN_BITS              TICK_TYPE_WIDTH_32_BITS

设置堆大小

#define configTOTAL_HEAP_SIZE                        4096

改为

#define configTOTAL_HEAP_SIZE                        (4096*10)

设置中断优先级宏

/* configKERNEL_INTERRUPT_PRIORITY sets the priority of the tick and context

* switch performing interrupts.  Not supported by all FreeRTOS ports.  See

* https://www.freertos.org/RTOS-Cortex-M3-M4.html for information specific to

* ARM Cortex-M devices. */

#define configKERNEL_INTERRUPT_PRIORITY          0

/* configMAX_SYSCALL_INTERRUPT_PRIORITY sets the interrupt priority above which

* FreeRTOS API calls must not be made.  Interrupts above this priority are

* never disabled, so never delayed by RTOS activity.  The default value is set

* to the highest interrupt priority (0).  Not supported by all FreeRTOS ports.

* See https://www.freertos.org/RTOS-Cortex-M3-M4.html for information specific

* to ARM Cortex-M devices. */

#define configMAX_SYSCALL_INTERRUPT_PRIORITY     0

/* Another name for configMAX_SYSCALL_INTERRUPT_PRIORITY - the name used depends

* on the FreeRTOS port. */

#define configMAX_API_CALL_INTERRUPT_PRIORITY    0

改为

#include "py32f403xD.h"

/* configKERNEL_INTERRUPT_PRIORITY sets the priority of the tick and context

* switch performing interrupts.  Not supported by all FreeRTOS ports.  See

* https://www.freertos.org/RTOS-Cortex-M3-M4.html for information specific to

* ARM Cortex-M devices. */

#define configKERNEL_INTERRUPT_PRIORITY          (7<<(8-__NVIC_PRIO_BITS))

/* configMAX_SYSCALL_INTERRUPT_PRIORITY sets the interrupt priority above which

* FreeRTOS API calls must not be made.  Interrupts above this priority are

* never disabled, so never delayed by RTOS activity.  The default value is set

* to the highest interrupt priority (0).  Not supported by all FreeRTOS ports.

* See https://www.freertos.org/RTOS-Cortex-M3-M4.html for information specific

* to ARM Cortex-M devices. */

#define configMAX_SYSCALL_INTERRUPT_PRIORITY     (5<<(8-__NVIC_PRIO_BITS))

/* Another name for configMAX_SYSCALL_INTERRUPT_PRIORITY - the name used depends

* on the FreeRTOS port. */

#define configMAX_API_CALL_INTERRUPT_PRIORITY    (5<<(8-__NVIC_PRIO_BITS))

#define configCHECK_FOR_STACK_OVERFLOW        2

改为

#define configCHECK_FOR_STACK_OVERFLOW        0

使用3位优先级即__NVIC_PRIO_BITS为3,即优先级寄存器8位高3位有效。

这里设置系统调用最高中断优先级为5,如果中断中要调用系统API则中断优先级不能高于5.

滴答等内核中断优先级设置为最低优先级7.

(对于NVIC数字越大优先级越低)

#define configCPU_CLOCK_HZ    ( ( unsigned long ) 20000000 )

根据实际的systick频率修改,我这里是

#define configCPU_CLOCK_HZ    ( ( unsigned long ) 144000000 )

#define configTICK_RATE_HZ                         100改为

#define configTICK_RATE_HZ                         1000

Systick 1ms中断一次,调度一次。

由于OS使用Systick,且HAL层也使用Systick,我们在系统初始化之前不使用HAL。

使用LL。

工程中定义宏

USE_FULL_LL_DRIVER

212313xnxe22qe8qqj8rle

修改py32f403_hal.c中

函数

HAL_StatusTypeDef HAL_Init(void)

注释掉,先不初始化systick等到os中启动时初始化。

  //HAL_InitTick(TICK_INT_PRIORITY);

编译报错

1602 | __STATIC_INLINE uint32_t LL_ADC_DMA_GetRegAddr(ADC_TypeDef *ADCx, uint32_t Register)

先不编译

.\PY32F403_HAL_Driver\Src\py32f403_ll_adc.c

py32f403_it.c中,系统滴答中回调os的滴答处理和HAL的处理。

extern void xPortSysTickHandler( void );

/**

  * @brief  This function handles SysTick Handler.

  * @param  None

  * @retval None

  */

void SysTick_Handler(void)

{

        xPortSysTickHandler();

  HAL_IncTick();

}

修改

startup_py32f403xx.s中

替换所有SVC_Handler 为vPortSVCHandler  

替换所有PendSV_Handler 为xPortPendSVHandle

及对应OS需要的调度中断处理。

四.测试

#include "FreeRTOS.h"

#include "task.h"

uint8_t rx_buffer[64];

static void shell_task(void * arg)

{

        (void)arg;


        uart_init(0, 115200);

        uart_init(1, 115200);        

        uart_send(1,(uint8_t*)"Hello World\r\n",strlen("Hello World\r\n"));

        while(1){

                uint32_t len = uart_read(1, rx_buffer, sizeof(rx_buffer));

                if(len > 0){

                        uart_send(1,rx_buffer,len);

                }

        }

}

int main(void)

{

        HAL_Init();

        clk_init();

        clk_out();


        TaskHandle_t xHandle;

        xTaskCreate( shell_task, "shell", 1024, NULL, 1, &xHandle );


        vTaskStartScheduler();

}

可以看到串口收发正常

五.总结

由于官方都有对应平台的移植,所以适配只需要添加对应的文件即可。需要注意下编译器版本,这里使用ARM编译器版本6,GNU兼容配置,所以选用GCC的Port。 另外注意中断相关的优先级配置,堆大小配置等一些关键配置。