3.2 HDMI display and timer interrupt control experiment

This experiment uses the HDMI display and timer counter function of the Plus1 7021 platform to introduce the basic programming method, which involves interrupt use. The Plus1 7021 system provides four general-purpose 16-bit count timers, timer0 to timer3. When the preset value is reached, the corresponding interrupt signal is generated by each timer。

The interrupt numbers assigned by the corresponding system are shown in the table below

 

Interrupt Number

Timer0

151

Timer1

152

Timer2

153

Timer3

154

The corresponding 32-bit registers are described in detail, please refer to the online technical documentation provided as follows:

https://sunplus-tibbo.atlassian.net/wiki/spaces/doc/pages/461144098

Here is a brief introduction to the meaning of related registers, as shown in the following table:

 

Control Register

Counting controller

Counting clock preprocessing controller

Counting value controller

 

 

 

 

 

 

 

Timer0

timer0_ctrl

bit[31:16]Reserved

bit[15:14] :Timer clock selection

0: System clock (default)

1: STC 90KHZ clock

bit13 :Operation method

0:Single operation (default)

1:Repeat the operation

bit12 : Reserved

bit11 :Switch control

0:Turn off the counter

1:Start counter

bit[10:0] :Reserved

timer0_reload

bit[31:16]Reserved

bit[15:0]

16-bit count preset value setting

 

 

timer0_cnt

bit[31:16]Reserved

bit[15:0]

16-bit count value

 

 

 

 

 

 

 

 

timer1

timer1_ctrl

bit[31:16]Reserved

bit[15:14] :Timer clock selection

0: System clock (default)

1: STC 90KHZ clock

bit13 :Operation method

0:Single operation (default)

1:Repeat the operation

bit12 : Reserved

bit11 :Switch control

0:Turn off the counter

1:Start counter

bit[10:0] :Reserved

timer1_reload

bit[31:16]Reserved

bit[15:0]

16-bit count preset value setting

 

 

timer1_cnt

bit[31:16]Reserved

bit[15:0]

16-bit count value

 

 

 

 

 

 

timer2

timer2_ctrl

bit[31:6]Reserved

bit[5:2] :Timer clock selection

0: System clock (default)

1: STC 90KHZ clock

bit1 :Operation method

0:Single operation (default)

1:Repeat the operation

bit1 : Reserved

bit0 :Switch control

0:Turn off the counter

1:Start counter

timer2_reload

bit[31:16]Reserved

bit[15:0]

16-bit count preset value setting

 

timer2_pres_val

bit[31:16]Reserved

bit[15:0]

16-bit count clock preset value setting

 

timer2_cnt

bit[31:16]Reserved

bit[15:0]

16-bit count value

 

 

 

 

 

 

timer3

timer3_ctrl

bit[31:6]Reserved

bit[5:2] :Timer clock selection

0: System clock (default)

1: STC 90KHZ clock

bit1 :Operation method

0:Single operation (default)

1:Repeat the operation

bit1 : Reserved

bit0 :Switch control

0:Turn off the counter

1:Start counter

timer3_reload

bit[31:16]Reserved

bit[15:0]

16-bit count preset value setting

 

timer3_pres_val

bit[31:16]Reserved

bit[15:0]

16-bit count clock preset value setting

 

timer3_cnt

bit[31:16]Reserved

bit[15:0]

16-bit count value

 

The regmap_q628.h under the installation directory \SP7021\workspace\sp7021\ include folder defines these four registers, as marked in red below:

regmap_q628.h

struct stc_regs {

    unsigned int stc_15_0;       // 12.0

    unsigned int stc_31_16;      // 12.1

    unsigned int stc_64;         // 12.2

    unsigned int stc_divisor;    // 12.3

    unsigned int rtc_15_0;       // 12.4

    unsigned int rtc_23_16;      // 12.5

    unsigned int rtc_divisor;    // 12.6

    unsigned int stc_config;     // 12.7

    unsigned int timer0_ctrl;    // 12.8 Timer Register

    unsigned int timer0_cnt;     // 12.9 Timer Register

    unsigned int timer1_ctrl;    // 12.10 Timer Register

    unsigned int timer1_cnt;     // 12.11 Timer Register

    unsigned int timerw_ctrl;    // 12.12

    unsigned int timerw_cnt;     // 12.13

    unsigned int stc_47_32;      // 12.14

    unsigned int stc_63_48;      // 12.15

    unsigned int timer2_ctl;     // 12.16 Timer Register

    unsigned int timer2_pres_val;// 12.17 Timer Register

    unsigned int timer2_reload;  // 12.18 Timer Register

    unsigned int timer2_cnt;     // 12.19 Timer Register

    unsigned int timer3_ctl;     // 12.20 Timer Register

    unsigned int timer3_pres_val;// 12.21 Timer Register

    unsigned int timer3_reload;  // 12.22 Timer Register

    unsigned int timer3_cnt;     // 12.23 Timer Register

    unsigned int stcl_0;         // 12.24

    unsigned int stcl_1;         // 12.25

    unsigned int stcl_2;         // 12.26

    unsigned int atc_0;          // 12.27

    unsigned int atc_1;          // 12.28

    unsigned int atc_2;          // 12.29

    unsigned int timer0_reload;  // 12.30 Timer Register

    unsigned int timer1_reload;  // 12.31 Timer Register

};

#define STC_REG     ((volatile struct stc_regs *)RF_GRP(12, 0))

The HDMI display and timer interrupt control experiment require the following 3 files, as follows:

1) Install directory \SP7021\workspace\sp7021\main.c

2) Install directory \SP7021\workspace\sp7021\testapi\util \timer.c

3) Install directory \SP7021\workspace\sp7021\include\util\timer.h

main.c

int main(void)

{

    printf("Build @%s, %s\n", __DATE__, __TIME__);

    hw_init();

    sys_init();

disp_hdmi_init();

    timer_test_init();/*interrupt test api */

    sp_interrupt_setup(); /* interrupt manager module init */

    while(1);

}

Step1: First, system and hardware initialization: hw_init (); sys_init ();

Step2: HDMI display initialization setting disp_hdmi_init (), as follows:

void disp_hdmi_init()

{

    sp_disp_init();

    sp_enable_log_to_osd();

    sp_osd_draw_string("Display and Timer test...",240,50,20,113);

}

The function of sp_enable_log_to_osd () realizes sending serial debugging information printf () to HDMI display interface;

The function of sp_osd_draw_string () realizes the display of ASCII characters at the specified coordinate position of the HDMI display screen

Step3: Then call the count timer initialization function timer_test_init () defined in timer.c;

Step4: Finally call the system interrupt management function sp_interrupt_setup ();

Of the above four functions, only timer_test_init () is written by the user according to the application requirements, and the others are provided by the system.

The function body of timer_test_init () is implemented in timer.c, which is responsible for the initialization of counting timer timer3, including the selection of counting clock, setting of timer value, timer interrupt configuration and corresponding interrupt processing function operation.

 timer.c

#include "common_all.h"

#include "cache.h"

#include "sp_interrupt.h"

#define TIMER3_TICKS        (90 - 1)        /* 1s */

#define TIMER3_CONFIG_STC   (1 << 2)    /* src: stc */

#define TIMER3_RELOAD       (1 << 1)    /* timer3 auto reload */

#define TIMER3_RUN          (1 << 0)    /* timer3 run */

#define TIMER3_STOP         (0 << 0)    /* timer3 stop */

#define TIMER3_INT  (154)

static unsigned int g_repeat_cnt = 0;

void timer3_interrupt_control_mask(int enable)

static void timer3_isr_cfg()

void timer3_callback(void)

void timer_test_init()

timer.c provides 4 method functions and macro definitions for implementing timer control experiments, which are explained as follows:

 void timer3_interrupt_control_mask(int enable)

{

    if (enable != 0) {

        /* enable timer3 interrupt */

        hal_interrupt_unmask(TIMER3_INT);

    } else {

        hal_interrupt_mask(TIMER3_INT);

    }

}

Used to control the opening and closing of the count timer 3 interrupt; when the enable is 0, the interrupt is turned off, and when it is 1, the interrupt is turned on

static void timer3_isr_cfg() 

{

    printf("[CFG] Timer3\n");

    STC_REG->timer3_ctl = TIMER3_CONFIG_STC | TIMER3_RELOAD;

    STC_REG->timer3_pres_val = 999;

    STC_REG->timer3_reload = TIMER3_TICKS;

    STC_REG->timer3_cnt = TIMER3_TICKS;

    hal_interrupt_configure(TIMER3_INT, 0, 1);

    timer3_interrupt_control_mask(1);

    STC_REG->timer3_ctl |= TIMER3_RUN;

}

Realize that the count timer generates an interrupt every 1 second. The related configuration work is as follows:

1)    STC_REG->timer3_ctl = TIMER3_CONFIG_STC | TIMER3_RELOAD;

Select clock as STC 90KHZ clock; operation mode is repeated operation

2)    STC_REG->timer3_pres_val = 999;

   Counting clock preprocessing is set to 999, which means that timer3 only counts once every 1000 STC 90KHZ clocks are received;

3)    STC_REG->timer3_reload = TIMER3_TICKS;

The pre-count value is set to 89, which means that timer3 starts counting again after 90 times

4)    STC_REG->timer3_cnt = TIMER3_TICKS;

The initial count value is set to 89, because the counter is UP to DOWN, that is, from the initial value count to 0 to complete 1 operation;

5)    hal_interrupt_configure(TIMER3_INT, 0, 1);

This is the interrupt setting function provided by the system. There are 3 parameters to be set, as follows:

     void hal_interrupt_configure(int vector, int level, int up)

     int vector :Interrupt number, assigned by the system, each timer has its own dedicated interrupt number:

The interrupt number of time0 is 151

The interrupt number of time1 is 152

The interrupt number of time2 is 153

The interrupt number of time3 is 154

     int level :Interrupt signal trigger mode

0:Edge trigger

1:Level trigger

     int  up    :Interrupt signal polarity

0:Negative polarity (negative edge or negative level)

1:Positive polarity (positive edge or positive level)

6)    timer3_interrupt_control_mask(1);

Turn on count timer 3 interrupt

7)    STC_REG->timer3_ctl |= TIMER3_RUN;

   Start counting timer 3, counting starts

void timer3_callback(void)

{

    printf("@Timer3[%d]\n", ++g_repeat_cnt);

}

It is the corresponding interrupt processing function operation, which displays the number of interrupts in the Terminal window of the IDE environment, and also sends them to the HDMI terminal for display.

 

void timer_test_init()

{

    static interrupt_operation timer3_opt;

    memcpy(timer3_opt.dev_name, "Timer3", strlen("Timer3"));

    timer3_opt.vector = TIMER3_INT;

    timer3_opt.device_config = timer3_isr_cfg;

    timer3_opt.interrupt_handler = timer3_callback;

    interrupt_register(&timer3_opt);

}

It is an interrupt initialization operation to complete the registration of the interrupt function, including the call of the three functions defined above

 

timer.h

#ifndef __TIMER_H__

#define __TIMER_H__

void timer_test_init();

#endif // __TIMER_H__

When a function in timer.c is called by a function in another file, it needs to be declared in timer.h

After compile in the Plus1 IDE environment, download to the platform to run, and see the following information in the terminal window