• 移植freertos到stm32 f103 的基本流程和总结


    为什么要在stm32 f103上面移植freertos

      stm32 f103 以他的全面的文档,亲民的价格,强大的功能。成为无数微设备的方案首选。在市场上有极大的使用量。市场占有率也是非常的高。freertos作为一个开源的微型操作系统,凭借着它的资源占用小,功能强大,文档齐全,成为各大芯片公司都支持的操作系统,也是程序员操作系统学习的不二首选。所以,把这两者结合起来,除了能给我们的产品提供强大的支撑之外,还积累的很多基础技术。笔者花了不少心思才把这个移植好,在这里做个记录。希望能给你一些启发。

    基本介绍

      我这里使用的是freertos的版本是9.0。移动植入之前,先看一下freertos的文件目录:

    ├── croutine.c
    ├── event_groups.c
    ├── include
    │   ├── FreeRTOS.h
    │   ├── StackMacros.h
    │   ├── croutine.h
    │   ├── deprecated_definitions.h
    │   ├── event_groups.h
    │   ├── list.h
    │   ├── mpu_prototypes.h
    │   ├── mpu_wrappers.h
    │   ├── portable.h
    │   ├── projdefs.h
    │   ├── queue.h
    │   ├── semphr.h
    │   ├── stdint.readme
    │   ├── task.h
    │   └── timers.h
    ├── list.c
    ├── portable
    │   ├── GCC
    │   │   └── ARM_CM3
    │   │       ├── port.c
    │   │       └── portmacro.h
    │   ├── MemMang
    │   │   ├── heap_1.c
    │   │   ├── heap_2.c
    │   │   ├── heap_2.lst
    │   │   ├── heap_2.o
    │   │   ├── heap_3.c
    │   │   ├── heap_4.c
    │   │   └── heap_5.c
    │   └── readme.txt
    ├── queue.c
    ├── readme.txt
    ├── tasks.c
    └── timers.c
    

    大致一看,这个操作系统是非常简洁的。从文件名字就可以看出:
    queue.c 这个文件是队列,负责线程之间的通信和数据传输的。
    task.c 就是线程及任务模块,线程相关的都在这个文件里面。
    list.c 就是一个链表,用来实现可变数据的存放和操作。
    根目录下的和具体的芯片没关系,和芯片的接口及相关的元素主要在两个函数里面。
    一个是portable文件下的port.c 这个里面要注意下,在stm32 f103中,这里最重要的就是这里的中断处理函数的匹配了。在无操作系统的stm32 f103中,systick, SVC 和 PendSV 这三个中断的处理函数 这三个函数一般在start.s文件或中断向量表中vector.c 中。基本额写法如下所示:

    void SVC_Handler (void) attribute((weak));
    
    void PendSV_Handler (void) attribute((weak));
    
    void SysTick_Handler (void) attribute((weak));
    

    在freertos中,需要替换成port.c 里面的另外三个中断处理函数:

    voidxPortPendSVHandler( void ) attribute (( naked ));
    
    voidxPortSysTickHandler( void );
    
    voidvPortSVCHandler( void ) attribute (( naked ));
    

    另外一个就是heap,heap主要是系统的内存管理单元。heap_1.c, heap_2.c and heap_3.c属于三个基本的样例子,用户也可以根据自己的实际情况做修改。这里的的heap虽然很多,但是每个系统只会使用一个,具体使用哪一个要看你的芯片平台的属性,stm32 f103 使用的是heap_2.c

    移植流程

      第一步就是把代码拷贝到目标文件中,编译通过。这里属于一些基本功夫,详细的步骤我就不多说了,谨记中断处理函数的处理,这里非常容易出问题。再者就是FreeRTOSconfig.h文件中的heap_size大小,不能太大,太大了这个芯片的资源不够的。建议一般不要10k左右就行了吧。

      第二步就是FreeRTOSConfig.h文件的配置选择,这里面的是非常关键的,最容易出错。下面是我的这个文件的配置:

    #define configUSE_PREEMPTION            1
    #define configUSE_IDLE_HOOK         0
    #define configUSE_TICK_HOOK         0
    #define configCPU_CLOCK_HZ          ( ( unsigned long ) 72000000 )
    #define configSYSTICK_CLOCK_HZ ( configCPU_CLOCK_HZ / 8 )  /* fix for vTaskDelay() */
    #define configTICK_RATE_HZ          ( ( TickType_t ) 1000 )
    #define configMAX_PRIORITIES            ( 5 )
    #define configMINIMAL_STACK_SIZE        ( ( unsigned short ) 128 )
    #define configTOTAL_HEAP_SIZE           ( ( size_t ) ( 17 * 1024 ) )
    #define configMAX_TASK_NAME_LEN         ( 16 )
    #define configUSE_TRACE_FACILITY        0
    #define configUSE_16_BIT_TICKS          0
    #define configIDLE_SHOULD_YIELD         1
    #define configUSE_MUTEXES           1
    
    /* Co-routine definitions. */
    #define configUSE_CO_ROUTINES           0
    #define configMAX_CO_ROUTINE_PRIORITIES     2
    
    /* Set the following definitions to 1 to include the API function, or zero
    to exclude the API function. */
    
    #define INCLUDE_vTaskPrioritySet        1
    #define INCLUDE_uxTaskPriorityGet       1
    #define INCLUDE_vTaskDelete         1
    #define INCLUDE_vTaskCleanUpResources       0
    #define INCLUDE_vTaskSuspend            0
    #define INCLUDE_vTaskDelayUntil         1
    #define INCLUDE_vTaskDelay          1
    
    

    这里要注意几点: configCPU_CLOCK_HZ 就是CPU的的时钟,系统的时钟和CPU的时钟是不同的,这里做一个8分频:#define configSYSTICK_CLOCK_HZ ( configCPU_CLOCK_HZ / 8 )
    还有就是后面的heap大小和stack大小,要根据实际的产品情况进行调整的。这个调整好了,可以让你的小芯片发挥出极大的威力。

      第三点,应用部分:
    这里手先看一下主函数:

    int main()
    {
        RCC_Configuration();
        GPIO_Configuration();
        usart1_init();
    
         printf("start main sdf 
    
    ");
         usart1_puts(" 512k flash, 64k ram ..........
    
    ");
    
         xTaskCreate(tadventure,"game",configMINIMAL_STACK_SIZE,NULL,configMAX_PRIORITIES-1,NULL);
         xTaskCreate(flasher,"flash",configMINIMAL_STACK_SIZE,NULL,configMAX_PRIORITIES-1,NULL);
         xTaskCreate(vT_usart, (const char*) "USART Task", configMINIMAL_STACK_SIZE, NULL, 1, NULL);
    
        vTaskStartScheduler();
    
        while (1);
    
        return 0;
    }
    
    

    三个task的处理函数:

    static void flasher(void *arg __attribute__((unused))) {
    
        for (;;) {
            GPIO_ResetBits(GPIOA, GPIO_Pin_1);
            vTaskDelay(pdMS_TO_TICKS(400));
            GPIO_SetBits(GPIOA, GPIO_Pin_1);
            vTaskDelay(pdMS_TO_TICKS(400));
        }
    }
    
    static void tadventure(void *arg __attribute__((unused))) {
    {
        for (;;) {
            GPIO_ResetBits(GPIOA, GPIO_Pin_0);
            vTaskDelay(pdMS_TO_TICKS(1000));
            GPIO_SetBits(GPIOA, GPIO_Pin_0);
            vTaskDelay(pdMS_TO_TICKS(1000));
        }
    }
    
    static void vT_usart(void *p)
    {
        // Block for 500ms.
        const portTickType xDelay = 500 / portTICK_RATE_MS;
    
        for(;;) {
            usart1_puts("FreeRTOS V9.0.0 demo on STM32F103c8t6
    ");
            usart1_puts(" 64k flash, 20k ram ..........
    ");
            vTaskDelay(xDelay);
        }
    }
    
    

    这里的结果如下所示:

    串口日志

    问题备忘

      最大的问题就是一个是FreertosConfig.h文件设置错误导致的系统timer不对。
    另外就是中断的服务处理函数了,一定要换成自己的。

  • 相关阅读:
    mysql数据库(1)
    通过全局异常处理机制实现接口参数校验返回指定返回类型
    http接口安全校验
    java 锁机制介绍
    通过反射获取类的所有属性值拼接成字符串工具类
    Mybatis中出现java.sql.SQLException: 无效的列类型: 1111
    判断两个Long相等
    jwt工具类
    mybatis #{}和${}的区别是什么
    报错解决NoSuchMethod。。。
  • 原文地址:https://www.cnblogs.com/dylancao/p/12331927.html
Copyright © 2020-2023  润新知