打印
[牛人杂谈]

系统定时器 SysTick

[复制链接]
2271|17
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
系统定时器 SysTick
ARMCortex-M4
集成了一个
SysTick
,它提供了一种简单的、
24
位写清零(
clear-on-write
)、递减的、计数值减到零后
自动重载(wrap-on-zero)的计数器,该计数器带有灵活的控制机制。SysTick其实就是一个定时器而已,只是它放在了NVIC中,主要的目的是为了给操作系统提供一个硬件上的中断(也称作“滴答中断”)。那么什么是滴答中断呢?这里来简单地解释一下。当操作系统进行运转的时候,也会有“心跳”。它会根据“心跳”的节拍来工作,把整个时间段分成很多小小的时间片,每个任务每次只能运行一个“时间片”的时间长度就得退出给别的任务运行,这样可以确保任何一个任务都不会霸占整个系统不放。或者把每个定时器周期的某个时间范围赐予特定的任务等,还有操作系统提供的各种定时功能,都与这个滴答定时器有关。因此,需要一个定时器来产生周期性的中断,而且最好还让用户程序不能随意访问它的寄存器,以维持操作系统“心跳”的节律。 只要不把它在SysTick控制及状态寄存器中的使能位清除,就永不停息。


沙发
zhuomuniao110| | 2016-7-13 00:03 | 只看该作者


使用特权

评论回复
板凳
zhuomuniao110| | 2016-7-13 00:24 | 只看该作者
好多人不知道关于系统的初始化怎么做,其实很简单,这个SYS的例程都说清楚了,还有怎么搞那个硬件的物理地址就是ID。
/**************************************************************************//**
* [url=home.php?mod=space&uid=288409]@file[/url]     main.c
* [url=home.php?mod=space&uid=895143]@version[/url]  V2.00
* $Revision: 4 $
* $Date: 14/01/28 11:44a $
* [url=home.php?mod=space&uid=247401]@brief[/url]    M051 Series Global Control and Clock Control Driver Sample Code
*
* @note
* Copyright (C) 2011 Nuvoton Technology Corp. All rights reserved.
*
******************************************************************************/
#include <stdio.h>
#include "M051Series.h"

#define PLL_CLOCK       50000000

#define SIGNATURE       0x125ab234
#define FLAG_ADDR       0x20000FFC

/*---------------------------------------------------------------------------------------------------------*/
/*  Brown Out Detector IRQ Handler                                                                         */
/*---------------------------------------------------------------------------------------------------------*/
void BOD_IRQHandler(void)
{
    /* Clear BOD Interrupt Flag */
    SYS_CLEAR_BOD_INT_FLAG();

    printf("Brown Out is Detected\n");
}

/*---------------------------------------------------------------------------------------------------------*/
/*  Simple calculation test function                                                                       */
/*---------------------------------------------------------------------------------------------------------*/
#define PI_NUM  256
int32_t f[PI_NUM + 1];
uint32_t piTbl[19] =
{
    3141,
    5926,
    5358,
    9793,
    2384,
    6264,
    3383,
    2795,
    288,
    4197,
    1693,
    9937,
    5105,
    8209,
    7494,
    4592,
    3078,
    1640,
    6284
};

int32_t piResult[19];

int32_t pi(void)
{
    int32_t i, i32Err;
    int32_t a = 10000, b = 0, c = PI_NUM, d = 0, e = 0, g = 0;

    for(; b - c;)
        f[b++] = a / 5;

    i = 0;
    for(; d = 0, g = c * 2; c -= 14,/*printf("%.4d\n",e+d/a),*/ piResult[i++] = e + d / a, e = d % a)
    {
        if(i == 19)
            break;

        for(b = c; d += f[b] * a, f[b] = d % --g, d /= g--, --b; d *= b);
    }
    i32Err = 0;
    for(i = 0; i < 19; i++)
    {
        if(piTbl[i] != piResult[i])
            i32Err = -1;
    }

    return i32Err;
}

void Delay(uint32_t x)
{
    int32_t i;

    for(i = 0; i < x; i++)
    {
        __NOP();
        __NOP();
    }
}

uint32_t g_au32PllSetting[] =
{
    CLK_PLLCON_PLL_SRC_HXT | CLK_PLLCON_NR(3) | CLK_PLLCON_NF(25) | CLK_PLLCON_NO_4,  /* PLL = 25MHz */
    CLK_PLLCON_PLL_SRC_HXT | CLK_PLLCON_NR(3) | CLK_PLLCON_NF(29) | CLK_PLLCON_NO_4,  /* PLL = 29MHz */
    CLK_PLLCON_PLL_SRC_HXT | CLK_PLLCON_NR(3) | CLK_PLLCON_NF(33) | CLK_PLLCON_NO_4,  /* PLL = 33MHz */
    CLK_PLLCON_PLL_SRC_HXT | CLK_PLLCON_NR(3) | CLK_PLLCON_NF(37) | CLK_PLLCON_NO_4,  /* PLL = 37MHz */
    CLK_PLLCON_PLL_SRC_HXT | CLK_PLLCON_NR(3) | CLK_PLLCON_NF(41) | CLK_PLLCON_NO_4,  /* PLL = 41MHz */
    CLK_PLLCON_PLL_SRC_HXT | CLK_PLLCON_NR(3) | CLK_PLLCON_NF(45) | CLK_PLLCON_NO_4,  /* PLL = 45MHz */
    CLK_PLLCON_PLL_SRC_HXT | CLK_PLLCON_NR(3) | CLK_PLLCON_NF(49) | CLK_PLLCON_NO_4   /* PLL = 49MHz */
};

void SYS_PLL_Test(void)
{
    int32_t  i;

    /*---------------------------------------------------------------------------------------------------------*/
    /* PLL clock configuration test                                                                             */
    /*---------------------------------------------------------------------------------------------------------*/

    printf("\n-------------------------[ Test PLL ]-----------------------------\n");

    for(i = 0; i < sizeof(g_au32PllSetting) / sizeof(g_au32PllSetting[0]) ; i++)
    {
        /* Switch HCLK clock source to HXT and HCLK source divide 1 */
        CLK_SetHCLK(CLK_CLKSEL0_HCLK_S_HXT, CLK_CLKDIV_HCLK(1));

        /* Set PLL to power down mode and PLL_STB bit in CLKSTATUS register will be cleared by hardware. */
        CLK_DisablePLL();

        /* Set PLL frequency */
        CLK->PLLCON = g_au32PllSetting[i];

        /* Waiting for PLL clock ready */
        CLK_WaitClockReady(CLK_CLKSTATUS_PLL_STB_Msk);

        /* Switch HCLK clock source to PLL */
        CLK_SetHCLK(CLK_CLKSEL0_HCLK_S_PLL, CLK_CLKDIV_HCLK(1));

        printf("  Change system clock to %d Hz ...................... ", SystemCoreClock);

        /* Output selected clock to CKO, CKO Clock = HCLK / 2^(1 + 1) */
        CLK_EnableCKO(CLK_CLKSEL2_FRQDIV_S_HCLK, 1, 0);

        /* The delay loop is used to check if the CPU speed is increasing */
        Delay(0x400000);

        if(pi())
        {
            printf("[FAIL]\n");
        }
        else
        {
            printf("[OK]\n");
        }

        /* Disable CKO clock */
        CLK_DisableCKO();
    }
}

void SYS_Init(void)
{

    /*---------------------------------------------------------------------------------------------------------*/
    /* Init System Clock                                                                                       */
    /*---------------------------------------------------------------------------------------------------------*/

    /* Enable Internal RC 22.1184MHz clock */
    CLK_EnableXtalRC(CLK_PWRCON_OSC22M_EN_Msk);

    /* Waiting for Internal RC clock ready */
    CLK_WaitClockReady(CLK_CLKSTATUS_OSC22M_STB_Msk);

    /* Switch HCLK clock source to Internal RC and HCLK source divide 1 */
    CLK_SetHCLK(CLK_CLKSEL0_HCLK_S_HIRC, CLK_CLKDIV_HCLK(1));

    /* Enable external XTAL 12MHz clock */
    CLK_EnableXtalRC(CLK_PWRCON_XTL12M_EN_Msk);

    /* Waiting for external XTAL clock ready */
    CLK_WaitClockReady(CLK_CLKSTATUS_XTL12M_STB_Msk);

    /* Set core clock as PLL_CLOCK from PLL */
    CLK_SetCoreClock(PLL_CLOCK);

    /* Enable UART module clock */
    CLK_EnableModuleClock(UART0_MODULE);

    /* Select UART module clock source */
    CLK_SetModuleClock(UART0_MODULE, CLK_CLKSEL1_UART_S_HXT, CLK_CLKDIV_UART(1));

    /*---------------------------------------------------------------------------------------------------------*/
    /* Init I/O Multi-function                                                                                 */
    /*---------------------------------------------------------------------------------------------------------*/

    /* Set P3 multi-function pins for UART0 RXD , TXD and CKO */
    SYS->P3_MFP &= ~(SYS_MFP_P30_Msk | SYS_MFP_P31_Msk  | SYS_MFP_P36_Msk);
    SYS->P3_MFP |= (SYS_MFP_P30_RXD0 | SYS_MFP_P31_TXD0 | SYS_MFP_P36_CKO);

}

void UART0_Init(void)
{
    /*---------------------------------------------------------------------------------------------------------*/
    /* Init UART                                                                                               */
    /*---------------------------------------------------------------------------------------------------------*/
    /* Reset IP */
    SYS_ResetModule(UART0_RST);

    /* Configure UART0 and set UART0 Baudrate */
    UART_Open(UART0, 115200);
}

/*---------------------------------------------------------------------------------------------------------*/
/*  Main Function                                                                                          */
/*---------------------------------------------------------------------------------------------------------*/
int32_t main(void)
{
    uint32_t u32data;

    /* If define INIT_SYSCLK_AT_BOOTING in system_M051Series.h, HCLK will be set to 50MHz in SystemInit(void). */
    /* In end of main function, program issued CPU reset and write-protection will be disabled. */
    if(SYS_IsRegLocked() == 0)
        SYS_LockReg();

    /* Unlock protected registers */
    SYS_UnlockReg();

    /* Init System, IP clock and multi-function I/O */
    SYS_Init();

    /* Lock protected registers */
    SYS_LockReg();

    /* Init UART0 for printf */
    UART0_Init();

    printf("\n\nCPU [url=home.php?mod=space&uid=72445]@[/url] %dHz\n", SystemCoreClock);

    /*
        This sample code will show some function about system manager controller and clock controller:
        1. Read PDID
        2. Get and clear reset source
        3. Setting about BOD
        4. Change system clock depended on different PLL settings
        5. Output system clock from CKO pin, and the output frequency = system clock / 4
    */

    printf("+---------------------------------------+\n");
    printf("|    M05xx System Driver Sample Code    |\n");
    printf("+---------------------------------------+\n");

    if(M32(FLAG_ADDR) == SIGNATURE)
    {
        printf("  CPU Reset success!\n");
        M32(FLAG_ADDR) = 0;
        printf("  Press any key to continue ...\n");
        getchar();
    }

    /*---------------------------------------------------------------------------------------------------------*/
    /* Misc system function test                                                                               */
    /*---------------------------------------------------------------------------------------------------------*/

    /* Read Part Device ID */
    printf("Product ID 0x%x\n", SYS_ReadPDID());

    /* Get reset source from last operation */
    u32data = SYS_GetResetSrc();
    printf("Reset Source 0x%x\n", u32data);

    /* Clear reset source */
    SYS_ClearResetSrc(u32data);

    /* Unlock protected registers for Brown-Out Detector settings */
    SYS_UnlockReg();

    /* Check if the write-protected registers are unlocked before BOD setting and CPU Reset */
    if(SYS_IsRegLocked() == 0)
    {
        printf("Protected Address is Unlocked\n");
    }

    /* Enable Brown-Out Detector, and set Brown-Out Detector voltage 2.7V */
    SYS_EnableBOD(SYS_BODCR_BOD_INTERRUPT_EN, SYS_BODCR_BOD_VL_2_7V);

    /* Enable BOD IRQ */
    NVIC_EnableIRQ(BOD_IRQn);

    /* Enable Low Voltage Reset function */
    SYS_ENABLE_LVR();

    /* Run PLL Test */
    SYS_PLL_Test();

    /* Write a signature work to SRAM to check if it is reset by software */
    M32(FLAG_ADDR) = SIGNATURE;
    printf("\n\n  >>> Reset CPU <<<\n");

    /* Waiting for message send out */
    UART_WAIT_TX_EMPTY(UART0);

    /* Switch HCLK clock source to Internal RC 22.1184MHz clock and HCLK source divide 1 */
    CLK_SetHCLK(CLK_CLKSEL0_HCLK_S_HIRC, CLK_CLKDIV_HCLK(1));

    /* Set PLL to Power down mode and HW will also clear PLL_STB bit in CLKSTATUS register */
    CLK_DisablePLL();

    /* Reset CPU */
    SYS_ResetCPU();
}


使用特权

评论回复
地板
zhuotuzi| | 2016-7-13 07:18 | 只看该作者
SysTick其实就是一个定时器而已,只是它放在了NVIC中,主要的目的是为了给操作系统提供一个硬件上的中断(也称作“滴答中断”)。

使用特权

评论回复
5
捉虫天师| | 2016-7-13 11:56 | 只看该作者
时钟系统,要结合那个时钟的逻辑结构图,学习很快。

使用特权

评论回复
6
neeringstu| | 2016-7-13 12:54 | 只看该作者
是不是ucos ii的时钟也是用的systick?

使用特权

评论回复
7
捉虫天师| | 2016-7-13 16:34 | 只看该作者
neeringstu 发表于 2016-7-13 12:54
是不是ucos ii的时钟也是用的systick?

应该是的,我觉得这个上面说是系统时钟,那就是了

使用特权

评论回复
8
yiyigirl2014| | 2016-7-14 07:07 | 只看该作者
Systick就是一个定时器而已,只是它放在了NVIC中,主要的目的是为了给操作系统提供一个硬件上的中断(号称滴答中断)。滴答中断?这里来简单地解释一下。操作系统进行运转的时候,也会有“心跳”。它会根据“心跳”的节拍来工作,把整个时间段分成很多小小的时间片,每个任务每次只能运行一个“时间片”的时间长度就得退出给别的任务运行,这样可以确保任何一个任务都不会霸占整个系统不放。或者把每个定时器周期的某个时间范围赐予特定的任务等,还有操作系统提供的各种定时功能,都与这个滴答定时器有关。因此,需要一个定时器来产生周期性的中断,而且最好还让用户程序不能随意访问它的寄存器,以维持操作系统“心跳”的节律。 只要不把它在SysTick控制及状态寄存器中的使能位清除,就永不停息。

使用特权

评论回复
9
heisexingqisi| | 2016-7-14 07:20 | 只看该作者
void SYS_PLL_Test(void)
{
    int32_t  i;

    /*---------------------------------------------------------------------------------------------------------*/
    /* PLL clock configuration test                                                                             */
    /*---------------------------------------------------------------------------------------------------------*/

    printf("\n-------------------------[ Test PLL ]-----------------------------\n");

    for(i = 0; i < sizeof(g_au32PllSetting) / sizeof(g_au32PllSetting[0]) ; i++)
    {
        /* Switch HCLK clock source to HXT and HCLK source divide 1 */
        CLK_SetHCLK(CLK_CLKSEL0_HCLK_S_HXT, CLK_CLKDIV_HCLK(1));

        /* Set PLL to power down mode and PLL_STB bit in CLKSTATUS register will be cleared by hardware. */
        CLK_DisablePLL();

        /* Set PLL frequency */
        CLK->PLLCON = g_au32PllSetting[i];

        /* Waiting for PLL clock ready */
        CLK_WaitClockReady(CLK_CLKSTATUS_PLL_STB_Msk);

        /* Switch HCLK clock source to PLL */
        CLK_SetHCLK(CLK_CLKSEL0_HCLK_S_PLL, CLK_CLKDIV_HCLK(1));

        printf("  Change system clock to %d Hz ...................... ", SystemCoreClock);

        /* Output selected clock to CKO, CKO Clock = HCLK / 2^(1 + 1) */
        CLK_EnableCKO(CLK_CLKSEL2_FRQDIV_S_HCLK, 1, 0);

        /* The delay loop is used to check if the CPU speed is increasing */
        Delay(0x400000);

        if(pi())
        {
            printf("[FAIL]\n");
        }
        else
        {
            printf("[OK]\n");
        }

        /* Disable CKO clock */
        CLK_DisableCKO();
    }
}

使用特权

评论回复
10
天灵灵地灵灵| | 2016-7-14 23:47 | 只看该作者
只要不把它在SysTick控制及状态寄存器中的使能位清除,就永不停息。

使用特权

评论回复
11
huangcunxiake| | 2016-7-17 23:02 | 只看该作者
只要不把它在SysTick控制及状态寄存器中的使能位清除,就永不停息。

使用特权

评论回复
12
dentsgot| | 2016-7-20 14:53 | 只看该作者
不知道这个时钟的优先级是不是高呢?

使用特权

评论回复
13
天灵灵地灵灵| | 2016-7-20 22:19 | 只看该作者
需要一个定时器来产生周期性的中断,而且最好还让用户程序不能随意访问它的寄存器,以维持操作系统“心跳”的节律

使用特权

评论回复
14
gejigeji521|  楼主 | 2016-7-24 18:22 | 只看该作者
这个定时器可以为系统的时钟提供脉动。

使用特权

评论回复
15
玛尼玛尼哄| | 2016-7-24 22:22 | 只看该作者
最好还让用户程序不能随意访问它的寄存器,以维持操作系统“心跳”的节律

使用特权

评论回复
16
598330983| | 2016-7-25 22:01 | 只看该作者
当操作系统进行运转的时候,也会有“心跳”。它会根据“心跳”的节拍来工作,把整个时间段分成很多小小的时间片,每个任务每次只能运行一个“时间片”的时间长度就得退出给别的任务运行,这样可以确保任何一个任务都不会霸占整个系统不放

使用特权

评论回复
17
zhuomuniao110| | 2016-7-26 23:26 | 只看该作者
每个任务每次只能运行一个“时间片”的时间长度就得退出给别的任务运行,这样可以确保任何一个任务都不会霸占整个系统不放。

使用特权

评论回复
18
heisexingqisi| | 2016-7-27 07:18 | 只看该作者
只要不把它在SysTick控制及状态寄存器中的使能位清除,就永不停息。

使用特权

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

本版积分规则

180

主题

2268

帖子

8

粉丝