Vega development board RISC-V kernel implementation microsecond precision delay

Foreword

VEGA Vega received a development board has for some time, did not play for a long time, and want to drive a OLED screen, but we must first realize IIC protocol, implemented IIC protocol, the most basic is the need for a precise time delay function, so study a little how to write an accurate delay function. Known, ARM Cortex-M core has a 24-bit SysTick system tick timer, it is a simple cycle timer for providing time base, mostly by the operating system. RV32M1 core of RISC-V also has a SysTick timer, but it does not belong to the core, but the use of an external general-purpose timers, that LPIT0 (low power periodic interval timer) Timer channel 0 to achieve, we can learn from system_RV32M1_ri5cy.c file, get some information:


/* Use LIPT0 channel 0 for systick. */
#define SYSTICK_LPIT LPIT0
#define SYSTICK_LPIT_CH 0
#define SYSTICK_LPIT_IRQn LPIT0_IRQn

/* Leverage LPIT0 to provide Systick */
void SystemSetupSystick(uint32_t tickRateHz, uint32_t intPriority)
{
    /* Init pit module */
    CLOCK_EnableClock(kCLOCK_Lpit0);

    /* Reset the timer channels and registers except the MCR register */
    SYSTICK_LPIT->MCR |= LPIT_MCR_SW_RST_MASK;
    SYSTICK_LPIT->MCR &= ~LPIT_MCR_SW_RST_MASK;

    /* Setup timer operation in debug and doze modes and enable the module */
    SYSTICK_LPIT->MCR = LPIT_MCR_DBG_EN_MASK | LPIT_MCR_DOZE_EN_MASK | LPIT_MCR_M_CEN_MASK;

    /* Set timer period for channel 0 */
    SYSTICK_LPIT->CHANNEL[SYSTICK_LPIT_CH].TVAL = (CLOCK_GetIpFreq(kCLOCK_Lpit0) / tickRateHz) - 1;

    /* Enable timer interrupts for channel 0 */
    SYSTICK_LPIT->MIER |= (1U << SYSTICK_LPIT_CH);

    /* Set interrupt priority. */
    EVENT_SetIRQPriority(SYSTICK_LPIT_IRQn, intPriority);

    /* Enable interrupt at the EVENT unit */
    EnableIRQ(SYSTICK_LPIT_IRQn);

    /* Start channel 0 */
    SYSTICK_LPIT->SETTEN |= (LPIT_SETTEN_SET_T_EN_0_MASK << SYSTICK_LPIT_CH);
}

void SystemClearSystickFlag(void)
{
    /* Channel 0. */
    SYSTICK_LPIT->MSR = (1U << SYSTICK_LPIT_CH);
}

system_RV32M1_ri5cy.h file SysTick interrupt service function:


#define SysTick_Handler LPIT0_IRQHandler

About LPIT0

LPIT0 Each channel contains one 32-bit counter, the count value of the countdown after the loading, when the countdown reaches zero, an interrupt flag is set, cleared by writing 1 to the Interrupt flag bit. In order to minimize the time consumed by execution of the function, delay of the delay function employed directly to registers manner. By reading RV32M1 Reference Manual [Chapter 50 Low Power Interrupt Timer (LPIT ) ] section, and achieve fsl_lpit.h library functions, we can understand the function of the following registers:

Register Name Full name Read / Write meaning
TVAL Timer Value Register Read / Write Set the timer initial value
CVAL Current Timer Value Read-only Get the current count value
sets Set Timer Enable Register Read and write Timer enable control
CLRTEN Clear Timer Enable Register just write Clears the count value
MCR Module Control Register Read and write Timer Clock Enable
MSR Module Status Register Read and write Overflow interrupt flag, write 1 to clear the interrupt

By introducing the above reference manual related registers, we have two ways to get whether the timer overflow:

  • Get is 0, i.e. the value of the current count value register CVAL
  • Get whether the register overflow state, i.e. the value of the MSR register.

These registers are 32 bits, the specific meaning of each one, can be found RV32M1 Reference Manual

delay.c file


#include "delay.h"

static uint8_t  fac_us=0;                           //us延时倍乘数
static uint16_t fac_ms=0;                           //ms延时倍乘数,在ucos下,代表每个节拍的ms数

void Delay_Init(void)
{
    CLOCK_SetIpSrc(kCLOCK_Lpit0, kCLOCK_IpSrcFircAsync);    //设置定时器时钟48MHz
    LOG("LPIT0: %ld \r\n", CLOCK_GetIpFreq(kCLOCK_Lpit0));  //输出LPIT0时钟

    CLOCK_EnableClock(kCLOCK_Lpit0);    //使能时钟
    LPIT_Reset(LPIT0);                  //复位定时器
    LPIT0->MCR = LPIT_MCR_M_CEN_MASK;   //使能定时器

    fac_us = CLOCK_GetIpFreq(kCLOCK_Lpit0)/1000000;
    fac_ms = fac_us*1000;
}
//基于SysTick即LPIT0实现的延时微秒函数
void Delay_us(uint32_t Nus)
{
    LPIT0->CHANNEL[kLPIT_Chnl_0].TVAL =  48 * Nus - 1;                  //加载时间
    LPIT0->SETTEN |= (LPIT_SETTEN_SET_T_EN_0_MASK << kLPIT_Chnl_0);     //启动定时器
    while(LPIT0->CHANNEL[kLPIT_Chnl_0].CVAL);                           //等待计数值到0
//  while((LPIT0->MSR & 0x0001) != 0x01);                               //等待溢出
//  LPIT0->MSR |= (1U << kLPIT_Chnl_0);                                 //写1,清除中断
    LPIT0->CLRTEN |= (LPIT_CLRTEN_CLR_T_EN_0_MASK << kLPIT_Chnl_0);     //清除计数器
}

//基于SysTick即LPIT0实现的延时毫秒函数
void Delay_ms(uint32_t Nms)
{
    LPIT0->CHANNEL[kLPIT_Chnl_0].TVAL = Nms * fac_ms  - 1;          //加载时间
    LPIT0->SETTEN |= (LPIT_SETTEN_SET_T_EN_0_MASK << kLPIT_Chnl_0); //启动定时器
    while(LPIT0->CHANNEL[kLPIT_Chnl_0].CVAL);                       //等待计数到0
//  while((LPIT0->MSR & 0x0001) != 0x0001);                         //等待产生中断
//  LPIT0->MSR |= (1U << kLPIT_Chnl_0);                             //向中断标志位写1,清除中断
    LPIT0->CLRTEN |= (LPIT_CLRTEN_CLR_T_EN_0_MASK << kLPIT_Chnl_0); //清除计数器
}

delay.h file


#ifndef __DELAY_H__
#define __DELAY_H__

#include "fsl_lpit.h"
#include "fsl_lpit.h"
#include "fsl_debug_console.h"
#include "sys.h"

void Delay_Init(void);      //SysTick定时器,即LPIT0,时钟可设置
void Delay_ms(uint32_t Nms);
void Delay_us(uint32_t Nus);

#endif

The actual verification


...

#include "delay.h"
...

int main(void)
{
    ...
    Delay_Init();
    ...
    while(1)
    {
        GPIOA->PTOR = 1 << 24;  //寄存器方式操作,减小误差
        Delay_ms(100);  //延时微秒函数验证
//      Delay_us(5);    //延时微秒函数验证              
    }
}

Actual oscilloscope test and found Delay_us microsecond delay function, there are about 2us error no matter how long the delay, I do not know why this is, but to achieve IIC protocol driver OLED screen is not affected.

IIC interface OLED drive

  • Community Home of the LOGO picture

  • The actual OLED display:

to sum up

Since accurate delay function achieved, then the sensors of various protocols, display module, driver communication module can be easily achieved, and want to share Benpian posts to give the community some friends help, I hope you will post to each other exchange of learning.

Reference material

History Featured


Welcome attention to my personal blog :www.wangchaochao.top

Or micro-channel scan code of the public concerned about my number

Guess you like

Origin www.cnblogs.com/whik/p/11105346.html