drv_systick.c 2.2 KB
Newer Older
W
Wayne Lin 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86
/**************************************************************************//**
*
* @copyright (C) 2020 Nuvoton Technology Corp. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date            Author           Notes
* 2020-11-11      Wayne            First version
*
******************************************************************************/

#include "rtthread.h"
#include "NuMicro.h"
#include "drv_sys.h"

#define USE_TIMER   5

/* Concatenate */
#define _CONCAT2_(x, y)       x##y
#define CONCAT2(x, y)         _CONCAT2_(x, y)

/* Concatenate the macros of timer instance for driver usage. */
#define SYSTICK               CONCAT2(TIMER, USE_TIMER)
#define SYSTICK_IRQ           CONCAT2(IRQ_TIMER, USE_TIMER)

static void nu_systick_isr(int vector, void *param)
{
    rt_tick_increase();
    ETIMER_ClearIntFlag(USE_TIMER);
}

void rt_hw_systick_init(void)
{
    nu_sys_ipclk_enable(TIMER5CKEN);

    nu_sys_ip_reset(TIMER5RST);

    // Set timer frequency
    ETIMER_Open(USE_TIMER, ETIMER_PERIODIC_MODE, RT_TICK_PER_SECOND);

    // Enable timer interrupt
    ETIMER_EnableInt(USE_TIMER);

    rt_hw_interrupt_install(SYSTICK_IRQ, nu_systick_isr, RT_NULL, "systick");
    rt_hw_interrupt_set_priority(SYSTICK_IRQ, IRQ_LEVEL_1);
    rt_hw_interrupt_umask(SYSTICK_IRQ);

    ETIMER_Start(USE_TIMER);
} /* rt_hw_systick_init */

void nu_systick_udelay(uint32_t delay_us)
{
    rt_uint32_t ticks;
    rt_uint32_t told, tnow, tcnt = 0;
    rt_uint32_t cmp = ETIMER_GetCompareData(USE_TIMER);

    ticks = delay_us * cmp / (1000000 / RT_TICK_PER_SECOND);
    told = ETIMER_GetCounter(USE_TIMER);
    while (1)
    {
        /* Timer counter is increment. */
        tnow = ETIMER_GetCounter(USE_TIMER);
        if (tnow != told)
        {
            /* 0 -- old === now -------- cmp */
            if (tnow > told)
            {
                tcnt += tnow - told;
            }
            else
            {
                /* 0 == now --- old ======== cmp */
                tcnt += cmp - told + tnow;
            }
            told = tnow;

            /* Timeout */
            if (tcnt >= ticks)
            {
                break;
            }
        }
    }

} /* nu_systick_udelay */