FreeRTOS移植到STM32(寄存器版)静态创建任务

FreeRTOS移植到STM32f103(寄存器版)静态创建任务


前言

基于寄存器的FreeRTOS移植到STM32,没有库函数,本文只是移植过程中代码相关的修改,没有目录结构的创建,参考此文需要先创建好FreeRtos的相关目录。创建目录参考文章:https://blog.csdn.net/qq_61672347/article/details/125529482
关于串口的寄存器配置,请参考我的另一篇文章:STM32寄存器配置USART1串口及USART->BRR值的计算https://blog.csdn.net/qq_47775761/article/details/130231106


1.配置启动文件

  1. Start文件夹下添加启动文件
    在这里插入图片描述
    2.根据自己的芯片,设置宏定义:我的是64kb的rom,故设置中容量产品的宏定义:STM32F10X_MD
    在这里插入图片描述

2. 配置FreeRTOSConfig.h:

  1. 中断服务相关的配置,手写进去即可:

    #define xPortPendSVHandler 	PendSV_Handler
    #define vPortSVCHandler 	SVC_Handler
    
  2. 使用静态内存分配,默认为动态分配:

    #define configSUPPORT_STATIC_ALLOCATION 1
    
  3. 其他的默认即可。

3. 在main.c的最下方写上systick中断服务函数:

///**
//  * @brief  This function handles SysTick Handler.
//  * @param  None
//  * @retval None
//  */
extern void xPortSysTickHandler(void);
//systick中断服务函数
void SysTick_Handler(void)
{	
    #if (INCLUDE_xTaskGetSchedulerState  == 1 )
      if (xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED)
      {
    #endif  /* INCLUDE_xTaskGetSchedulerState */  
        xPortSysTickHandler();
    #if (INCLUDE_xTaskGetSchedulerState  == 1 )
      }
    #endif  /* INCLUDE_xTaskGetSchedulerState */
}

4. FreeRtos默认的系统CPU_CLOCK是72MHz,TICK_RATE为每秒1000个tick(时间片),即1个tick(时间片)是1ms,但是STM32默认的SYSCLK是内核不精准的8MHz内部晶振,这导致了一个时间片长达9毫秒之久,所以我们要配置时钟为外部精准的72MHz系统时钟,代码如下(sysclk.c):

#include "stm32f10x.h"                  // Device header

/*时钟源为外部晶振,9倍频,SYSCLK为72MHz,APB2不分频,APB1二分频*/
void SYSCLK_Init()
{
  /*打开HSE*/
  RCC->CR |= RCC_CR_HSEON;
  /* 等待HSE等待完毕 */
  while ((RCC->CR & RCC_CR_HSERDY) == 0)
  {
  }
  /*时钟源选择为 HSE,进行9倍频 SYSCLK = HSE*9 = 8MHz*9 = 72MHz */
  RCC->CFGR |= RCC_CFGR_PLLMULL9;
  RCC->CFGR |= RCC_CFGR_PLLSRC;

  FLASH->ACR |= FLASH_ACR_LATENCY_2; // FLASH缓冲

  /* 使能PLL倍频器 */
  RCC->CR |= RCC_CR_PLLON;
  /* Wait till PLL is ready */
  while ((RCC->CR & RCC_CR_PLLRDY) == 0) // 等待PLL倍频器就绪
  {
  }
  /* SYSCLK预分频系数为1,即不分频 */
  RCC->CFGR |= RCC_CFGR_HPRE_DIV1;

  /* APB2预分频系数为1,即不分频 =SYSCLK */
  RCC->CFGR |= RCC_CFGR_PPRE2_DIV1;
  //
  //    /* APB1预分频系数为2,即 APB2 = SYSCLK/2 */
  RCC->CFGR |= RCC_CFGR_PPRE1_DIV2;

  /* 复位时钟源选择,并将时钟源选择为PLL */
  RCC->CFGR &= (~(RCC_CFGR_SW));
  RCC->CFGR |= RCC_CFGR_SW_PLL;
  //
  /* 等待时钟源选择完成置位 */
  while ((RCC->CFGR & RCC_CFGR_SWS) != 0x08)
  {
  }
}

5. systick定时器配置成使用外部晶振,并关闭systick定时器(关闭的目的是防止触发systick中断):

SysTick->CTRL |= 0x00000004;	

6. NVIC优先级分组为第四组(全部设置为抢占优先级):

SCB->AIRCR=0x05fa0000|0x300;//NVIC优先级分组为第四组

7. 工程代码:

  1. main.c

    #include "stm32f10x.h"
    #include "FreeRTOS.h"
    #include "task.h"
    
    #include "sysclk.h"
    
    static TaskHandle_t LED_Task_handle = NULL;
    
    /*空闲任务栈*/
    static StackType_t Idle_Task_Stack[configMINIMAL_STACK_SIZE];
    /*空闲任务控制块*/
    static StaticTask_t Idle_Task_TCB;
    
    
    /*Led任务栈*/
    static StackType_t Led_Task_Stack[128];
    /*Led任务控制块*/
    static StaticTask_t Led_Task_TCB;
    
    void vApplicationGetIdleTaskMemory(StaticTask_t **ppxIdleTaskTCBBuffer,
                                       StackType_t **ppxIdleTaskStackBuffer,
                                       uint32_t *pulIdleTaskStackSize)
    {
        *ppxIdleTaskTCBBuffer = &Idle_Task_TCB;
        *ppxIdleTaskStackBuffer = Idle_Task_Stack;
        *pulIdleTaskStackSize = configMINIMAL_STACK_SIZE;
    }
    
    static void LED_Task_Entry(void *p_arg)
    {
        while(1)
        {
           GPIOC->ODR &= ~(1 << 13);//关灯
           vTaskDelay(1000);
    			 GPIOC->ODR |= 1 << 13;//开灯
           vTaskDelay(1000);
        }
    }
    
    void GPIO_Init()
    {
    	RCC->APB2ENR |= (1 << 4); // 使能APB2上的GPIOC
        GPIOC->CRH &= 0xff0fffff; // 配置c13口为推挽输出,由于点亮LED
        GPIOC->CRH |= 0x00300000;
    }
    
    int main(void)
    {
    	/*SYSCLK初始化*/	
    	SYSCLK_Init();
    	/*使用外部晶振,并关闭systick定时器*/
    	SysTick->CTRL |= 0x00000004;
        //NVIC优先级分组为第四组
    	SCB->AIRCR=0x05fa0000|0x300;
    	
    	GPIO_Init();
    	
    	LED_Task_handle=xTaskCreateStatic((TaskFunction_t)LED_Task_Entry,//任务函数入口
    	                                  (const char*)"LED_Task",//任务名称
                       	              (uint32_t) 128, //任务栈大小
                       	              (void *)NULL,//传给任务的参数
                                      (UBaseType_t) 4,//优先级
    	                              (StackType_t *)Led_Task_Stack,//任务栈的起始地址
    	                              (StaticTask_t *)&Led_Task_TCB);//任务控制块
    	if(LED_Task_handle!=NULL)
    		vTaskStartScheduler();														
    	while(1);
    }
    
    ///**
    //  * @brief  This function handles SysTick Handler.
    //  * @param  None
    //  * @retval None
    //  */
    extern void xPortSysTickHandler(void);
    //systick中断服务函数
    void SysTick_Handler(void)
    {	
        #if (INCLUDE_xTaskGetSchedulerState  == 1 )
          if (xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED)
          {
        #endif  /* INCLUDE_xTaskGetSchedulerState */  
            xPortSysTickHandler();
        #if (INCLUDE_xTaskGetSchedulerState  == 1 )
          }
        #endif  /* INCLUDE_xTaskGetSchedulerState */
    }
    
    
    1. sysclk.h
      #ifndef __SYSCLK_H_
      #define __SYSCLK_H_
            void SYSCLK_Init(void);
      #endif
      
    
  2. 其他头文件为FREERTOS文件,直接用即可

总结

实验内容是一个LED每隔1S亮灭一次。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

爱学习的喷火龙

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值