TQ210 bare metal programming (4) - keystroke (interrupt method)

Publisher:CrystalClearLatest update time:2020-12-23 Source: eefocusKeywords:TQ210 Reading articles on mobile phones Scan QR code
Read articles on your mobile phone anytime, anywhere

The S5PV210 has four vector interrupt controllers (VICs), each containing 32 interrupt sources.


When an interrupt source generates an interrupt, the CPU will automatically assign the value of the VICxVECTADDRy (x=0,1,2,3,y=0-31) register to VICxADDRESS (x=0,1,2,3), so we can assign the address of our interrupt handling function to the VICxVECTADDRy register.


For example, we have a function

void key_handle()
{    
……
}

We assign the value of the key_handle function to VIC0VECTADDR0 (external interrupt 0)

VIC0VECTADDR0 =key_handle;


When external interrupt 0 triggers an interrupt, the CPU will automatically assign the value of VIC0VECTADDR0 to VIC0ADDRESS and jump to this address to execute, that is, execute the function key_handle.


code show as below:

.global _start /* Declare a global label */  

.global key_isr  

_start:  

    /* Set up the stack to call the C function */  

    ldr sp, =0x40000000       

  

    /* Enable general interrupt */  

    mrs r0, cpsr  

    bic r0, r0, #0x00000080 /* Clear bit 7, IRQ interrupt disable bit, write 0 to enable IRQ */  

    msr cpsr, r0  

  

    bl main /* Jump to C function to execute */  

  

halt:  

    b stop  

  

key_isr:  

    /* Calculate the return address: The value of PC is equal to the current execution address + 8. When the CPU is about to execute an instruction (not yet executed), it is interrupted. 

    ** This is the address of the instruction to be executed = PC-4 */  

    sub lr, lr, #4  

    stmfd sp!, {r0-r12, lr} /* protect the context */  

    bl key_handle  

    /* Restore the scene */  

    ldmfd sp!, {r0-r12, pc}^ /* ^ means restore spsr to cpsr */ 


key.c

#define GPC0CON             *((volatile unsigned int *)0xE0200060)  

#define GPC0DAT             *((volatile unsigned int *)0xE0200064)  

  

#define GPH0CON             *((volatile unsigned int *)0xE0200C00)  

#define GPH0DAT             *((volatile unsigned int *)0xE0200C04)  

  

#define EXT_INT_0_CON       *((volatile unsigned int *)0xE0200E00)  

#define EXT_INT_0_MASK      *((volatile unsigned int *)0xE0200F00)  

  

#define VIC0INTSELECT       *((volatile unsigned int *)0xF200000C)  

#define VIC0INTENABLE       *((volatile unsigned int *)0xF2000010)  

  

#define VIC0VECTADDR0       *((volatile unsigned int *)0xF2000100)  

#define VIC0VECTADDR1       *((volatile unsigned int *)0xF2000104)  

  

#define VIC0ADDRESS         *((volatile unsigned int *)0xF2000F00)  

  

#define EXT_INT_0_PEND      *((volatile unsigned int *)0xE0200F40)  

  

extern void key_isr(void);  

  

void key_handle()  

{     

    volatile unsigned char key_code = EXT_INT_0_PEND & 0x3;  

      

    VIC0ADDRESS = 0; /* Clear interrupt vector register */  

    EXT_INT_0_PEND |= 3; /* Clear interrupt pending register*/  

      

    if (key_code == 1)      /* key1 */  

        GPC0DAT ^= 1 << 3;    /* toggle LED1 */  

    else if (key_code == 2) /* key2 */  

        GPC0DAT ^= 1 << 4;    /* toggle LED2 */  

}  

  

int main()  

{  

    GPC0CON &= ~(0xFF << 12);  

    GPC0CON |= 0x11 << 12; /* Configure GPC0_3 and GPC0_4 as output: LED1 and LED2 */  

    GPH0CON |= 0xFF << 0; /* Configure GPH0_0 and GPH0_1 as external interrupts: key1 and key2 */  

      

    EXT_INT_0_CON &= ~(0xFF << 0);  

    EXT_INT_0_CON |= 2 | (2 << 4); /* Configure EXT_INT[0] and EXT_INT[1] as falling edge trigger*/  

    EXT_INT_0_MASK &= ~3; /* Unmask external interrupts EXT_INT[0] and EXT_INT[1] */  

      

    VIC0INTSELECT &= ~3; /* Select external interrupt EXT_INT[0] and external interrupt EXT_INT[1] as IRQ type interrupt*/  

      

    VIC0INTENABLE |= 3; /* Enable external interrupts EXT_INT[0] and EXT_INT[1] */  

      

    VIC0VECTADDR0 = (int)key_isr; /* When EXT_INT[0] triggers an interrupt, that is, when the user presses key1, 

                                             The CPU will automatically assign the value of VIC0VECTADDR0 to VIC0ADDRESS and jump to this address to execute */  

    VIC0VECTADDR1 = (int)key_isr;  

      

    while (1);  

      

    return 0;  


Makefile

key.bin: start.o key.o  

    arm-linux-ld -Ttext 0x20000000 -o key.elf $^  

    arm-linux-objcopy -O binary key.elf $@  

    arm-linux-objdump -D key.elf > key.dis  

      

key.o : key.c  

    arm-linux-gcc -c $< -o $@  

start.o : start.S  

    arm-linux-gcc -c $< -o $@  

      

clean:  

    rm *.o *.elf *.bin *.dis 


Download the program to memory and run it


Press key1, LED1 lights up, press key1 again, LED1 turns off

Press key2, LED2 lights up, press key2 again, LED2 turns off

Keywords:TQ210 Reference address:TQ210 bare metal programming (4) - keystroke (interrupt method)

Previous article:Embedded Learning Notes 2: Introduction to the 210 Power-on Startup Process
Next article:TQ210 bare metal programming (2) - LED running light

Latest Microcontroller Articles
Change More Related Popular Components

EEWorld
subscription
account

EEWorld
service
account

Automotive
development
circle

About Us Customer Service Contact Information Datasheet Sitemap LatestNews


Room 1530, 15th Floor, Building B, No.18 Zhongguancun Street, Haidian District, Beijing, Postal Code: 100190 China Telephone: 008610 8235 0740

Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号