• 进入OS前的两步之System tick


    OK,继续向操作系统迈进。由简入繁,先实现两个小功能。第一个是system tick,第二个是任务切换(PendSV)。一个是操作系统的心跳,一个是操作系统的并发处理的具体实现

    System tick,在裸机程序里面,这个功能一直是用来做延时功能用的,用STM32做项目,基本都会用到。这里不准备再从头去实现这个功能,而是直接用ST官方的库文件。库文件版本为3.5.0。

    主要用到两个函数,第一个为

    static __INLINE uint32_t SysTick_Config(uint32_t ticks)

    {

    if (ticks > SysTick_LOAD_RELOAD_Msk) return (1); /* Reload value impossible */

    SysTick->LOAD = (ticks & SysTick_LOAD_RELOAD_Msk) - 1; /* set reload register */

    NVIC_SetPriority (SysTick_IRQn, (1<<__NVIC_PRIO_BITS) - 1); /* set Priority for Cortex-M0 System Interrupts */

    SysTick->VAL = 0; /* Load the SysTick Counter Value */

    SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk |

    SysTick_CTRL_TICKINT_Msk |

    SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */

    return (0); /* Function successful */

    }

    下面来解读一下这个函数。

    1,从函数的注释可以了解到,参数ticks就是Systick的重装值。成功返回1,失败返回0。

    * @param ticks number of ticks between two interrupts

    * @return 1 = failed, 0 = successful

    2,第一句if (ticks > SysTick_LOAD_RELOAD_Msk) return (1);这一句的意思是若是重装值大于重装值的上限,那么就返回失败。Reload 是一个24bit的寄存器,所以最大值不能大于2^24。

    3,设定重装值。

    SysTick的结构体原型如下:

    typedef struct

    {

    __IO uint32_t CTRL; /*!< Offset: 0x00 SysTick Control and Status Register */

    __IO uint32_t LOAD; /*!< Offset: 0x04 SysTick Reload Value Register */

    __IO uint32_t VAL; /*!< Offset: 0x08 SysTick Current Value Register */

    __I uint32_t CALIB; /*!< Offset: 0x0C SysTick Calibration Register */

    } SysTick_Type;

    将SysTick_Type的地址指向0xE000E010,那么结构体中的四个成员的偏移地址刚好对应下图的四个表所指寄存器的地址。

    4,设定中断优先级。

    5,将当前计数的值清零。

    6,使能SysTick和中断。

    这个函数在core_cm3.h文件里面。

    另外一个函数在misc.c里面,

    void SysTick_CLKSourceConfig(uint32_t SysTick_CLKSource)

    {

    /* Check the parameters */

    assert_param(IS_SYSTICK_CLK_SOURCE(SysTick_CLKSource));

    if (SysTick_CLKSource == SysTick_CLKSource_HCLK)

    {

    SysTick->CTRL |= SysTick_CLKSource_HCLK;

    }

    else

    {

    SysTick->CTRL &= SysTick_CLKSource_HCLK_Div8;

    }

    }

    用来指定时钟源是HCLK还是HCLK 8分频。在不调用该函数的情况下,默认为时钟源为HCLK。

    有了这两个函数,再加上中断函数SysTick_Handler,我们就可以使用SysTick了,下面用一段LED闪烁的代码来测试一下。

    第一步:建立一个新文件夹。

    第二步:建立工程,添加启动代码,并将如下文件添加至工程。

    项目视图:

    文件夹视图:

    Config中的头文件列表只保留

    #include "misc.h" /* High level functions for NVIC and SysTick (add-on to CMSIS functions) */

    系统时钟选择

    #define SYSCLK_FREQ_72MHz 72000000

    Main文件中测试代码如下:

    #include "stm32f10x_conf.h"

    #define LED0 *((volatile unsigned long *)(0x422101a0)) //PA8 out

    unsigned char flag=0;

    void LEDInit(void)

    {

    RCC->APB2ENR|=1<<2;

    GPIOA->CRH&=0XFFFFFFF0;

    GPIOA->CRH|=0X00000003;

    }

    int main(void)

    {

        SysTick_Config(9000000);

        SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8);//72/8=9MHZ

        LEDInit();

        

        while(1);

    }

    void SysTick_Handler(void)

    {

        flag=~flag;

        LED0=flag;

    }

    第三步:仿真测试。

    测试的波形如下:

    可以看到,刚好1秒闪烁一次。下载到开发板上测试也OK。

    OK,System tick 算是搞定,接下来就是任务切换了。

  • 相关阅读:
    Python中os与sys两模块的区别
    单线程爬取图片
    linux下glances服务器监控工具
    python中的join()函数的用法
    python的exec、eval详解
    mongodb启动不了解决方法
    生产者和消费者(.net实现)
    IOS开发--第一阶段--导行(1)(基本概念)
    12.26 linux基本操作指令
    12.25
  • 原文地址:https://www.cnblogs.com/WeyneChen/p/4872387.html
Copyright © 2020-2023  润新知