JZ2440 bare board development practice # 7 interrupts and exceptions (1)

Preliminaries

Before entering interrupts and exceptions exercises topic, you need to read through the S3C2440 ARM chip or reference manual to find out the status and exception mechanism of ARM.

First need to know is the presence ARM mode and the Thumb mode ARM, wherein Thumb mode instruction length of 16bits, in order to save program memory space exists, the ARM mode instruction 32bits, schematically we usually use, now because of the memory capacity are more large, able to meet the storage needs, the use of ARM mode mostly from ARM mode to Thumb mode requires the use of a program jump instruction BX, when the target address operand BX lowest bit is 1, CPU will turn Thumb mode, as follows, of course, but also with the compiler join Thumb parameters -mthumb.

	adr r0, thumb_func
	add r0, r0, #1  /* bit0=1时, bx就会切换CPU State到thumb state */
	bx r0
	
.code 16	
thumb_func:	
	bl main

ARM and Thumb mode just above and associated instruction length, there is a set of ARM mode of operation, corresponding to the abnormality, but also limit access to resources.

The figure above top to bottom are user mode, fast interrupt mode, interrupt mode, management mode, termination mode, the system mode and undefined mode in which a non-privileged user mode mode, limiting access to some resources and can not directly modify the relevant register achieve conversion mode. Termination mode termination instruction prefetch is divided into read data and terminates, enters the abnormal mode (e.g., not read) operation in both. Undefined instruction read means does not comply with the ARM instruction set, ARM does not know, the process proceeds to the mode. FIQ and IRQ interrupt, need to be clear, the interrupt exception belongs, FIQ interrupt processing for data transfer, with respect to the elapsed time is less IRQ, FIQ part of the reason that where there are more special purpose registers, can not register for more save the scene. Below, the triangle of the flag is the special mode register.

Personally think that the presence of abnormal patterns greatest significance is the ability to perform certain actions to restore the system, it is necessary to jump to the appropriate handler after entering the exception. ARM here to do work in this area, ARM set an exception vector table when an exception occurs, the PC will point to the address corresponding to abnormal abnormalities in the vector table, and we need to do is to establish the exception in the corresponding address vector table.

ARM made when entering the above abnormal patterns do not just jump exception to the scale, before doing anything else describe ARM, you need to first understand CPSR and SPSR registers. CPSR, Current Program Status Register, the current program status register, SPSR, Saved Program Status Registers, saved program status register. SPSR It is simply an archive of CPSR point, when the need to use or modify the CPSR, if the subsequent need to use CPSR original value, the value will be saved CPSR to SPSR, this step should be done automatically ARM's. And CPSR use is more and more, 0-4bit mode bit is set to a value corresponding to a respective mode proceeds, the second table may look. No. 5 is the ARM and Thumb mode status bits mentioned above, it must be noted that the manual can not be manually set to remind this one, otherwise it will enter an unknown state. 6 and bit 7 of the interrupt enable bit is set in response to an interrupt is prohibited. 8-27 bits are reserved and should be set to 0, it is estimated that ARM wants to expand the functions of the follow-up to use. 28-31-bit operation was the result of the status bits, the more common is not explained.

 

 We can now talk about doing things under the ARM when switching anomaly:

1. The return value (PC +4 or PC + 8) R14 to save (LR) register (note: this corresponds LR has a dedicated register mode)

2. Save the CPSR to the SPSR (SPSR is also mapped in the exclusive mode)

3. Change the CPSR mode bits (0-4) mode value corresponding mode

4. The address of the exception PC points corresponding exception vector table

So far, the program enters an exception handler. In an exception handler, we need to do the program are:

1. Because R13 (SP) register for each unique mode register, thus in the corresponding mode, we need to set the stack handler because we intend to use the C language.

2. Before entering the real handler, you need to save the site, that is non-exclusive registers need to save the stack to ensure that after the end of the exception handler returns, the original program can be normal.

3. Before the end of the program flow returns to normal, you need to save on-site recovery, and the recovery value in SPSR to the CPSR, while previously saved PC points LR return address. If it is interrupted, also you need to clear the corresponding interrupt bit, to prevent re-triggering.

Note that, between the different modes of the return address that is different, look-up table needs to be handled accordingly.

Further, in addition to user mode, other modes can directly modify the CPSR mode bits to change the current mode.

abnormal

With the above prior knowledge after, the operation has become very simple. Required steps are:

1. Establish exception vector table

Set up the stack and restore the site to save the scene before and after the 2 exception handler

3. exception handler

Due to the need to see the phenomenon, and then in the original program, the code can be added quite enough throws an exception.

Whereby the output Undefined exception code is as follows:

Start.S
---------------------------------
.text
.global _start

_start:
	B RESET	                        //异常向量表,参考芯片手册
	LDR pc,UNDEFIE                  //LDR取汇编的标号即取该地址内容,若为伪指令=,则为直接取地址
	LDR pc,SW_INTERRUPT             
	B ABORT_PREFETCH
	B ABORT_DATA
	B halt				            //reserve
	B IRQ_HANDLE
	B FIQ_HANDLE

UNDEFIE:                            //将目标地址放置在此处,防止编译器将地址放置在4k以外及其他
	.word DO_UND	                //因为硬件原因不能取到内容的地方
	
SW_INTERRUPT:
	.word DO_SWI
	

ABORT_PREFETCH:                    //此处未做实现,因此全部调到halt
ABORT_DATA:	
IRQ_HANDLE:
FIQ_HANDLE:
	B halt

DO_UND:
	//1.设置栈
	LDR SP,=0x34000000
	//2.保存现场
	STMDB SP!,{R0-R12,LR}

	//处理函数
	MRS R0,CPSR
	LDR R1,=UND_TEST_STRING
    BL ExecptionHandle
	
	//3.恢复现场,跳转回原来的位置
	LDMIA SP!,{R0-R12,PC}^              //^ 表示将SPSR恢复到CPSR中
	
DO_SWI:
	//1.设置栈
	LDR SP,=0x33e00000
	//2.保存现场
	STMDB SP!,{R0-R12,LR}
	
	//处理函数
	MRS R0,CPSR
	LDR R1,=SWI_TEST_STRING
    BL ExecptionHandle
	
	//3.恢复现场,跳转回原来的位置
	LDMIA SP!,{R0-R12,PC}^  //^ 表示将SPSR恢复到CPSR中

UND_TEST_STRING:
	.string "enter undefin mode!\n"    //汇编中定义带'\0'的字符串为.string
	
SWI_TEST_STRING:
	.string "enter swi mode!\n"

.align 4                                //4字节对齐。防止string的不对齐而取地址自动对齐造成的异常执行
RESET:
	MOV R0,#0
	LDR R1,[R0]
	
	STR R0,[R0]
	LDR R2,[R0]
	
	CMP R2,R0
	LDR SP,=0x40000000+4096
	MOVEQ SP,#4096
	STREQ R1,[R0]
	
	BL HardwareInitAll
	BL UartInit
	
TEST_UND:
	bl testPrint                    //调试时发现这里必须存在一个语句下面的未定义指令才会生效,
	.word 0xdeadc0de                //原因未知,已排除未对齐原因
	//bl testPrint
TEST_SWI:
	MRS R0,CPSR
	BIC R0,R0,#0x0F                //切换到usr模式
	MSR CPSR,R0
	SWI 0x123
	
	LDR pc,=main
halt:
    B halt
execption.h
----------------------------
#ifndef __EXCEPTION_H
#define __EXCEPTION_H

#include <stdint.h>

void UndExecptionHandle(uint32_t CPSR,char* string);

#endif
execption.c
------------------------

#include "execption.h"
#include "uart.h"

void ExecptionHandle(uint32_t CPSR,char* string)
{
	printHex(CPSR);
	puts(string);
}
uart.h
-----------------------------
#ifndef __UART_H
#define __UART_H

#include <stdint.h>

void UartInit(void);

void putc(uint8_t character);
uint8_t getc(void);

void printHex(uint32_t value);
void puts(char* string);
void testPrint();
#endif


#include "uart.h"


#include "s3c2440.h"


void UartInit(void)
{
	//GPIO init
	GPHCON &= ~((3<<6) | (3<<4));
	GPHCON |= (2<<6) | (2<<4);

	//UART init
	ULCON0 = 3;  //8n1
	UCON0 = (1<<2) | (1<<0);
	UBRDIV0 = (int32_t)( 50000000/ (115200 * 16) ) -1;
}


static uint8_t IsReadyToSend(void)
{
	return UTRSTAT0 & (1<<1);
}


static uint8_t IsReadyToReceive(void)
{
	return UTRSTAT0 & (1<<0);
}

void putc(uint8_t character)
{
	if(character==(uint8_t)('\n'))
	{
		while(!IsReadyToSend());
		UTXH0 = (uint8_t)'\r';
	}
	while(!IsReadyToSend());
	UTXH0 = character;
}

uint8_t getc(void)
{
	while(!IsReadyToReceive());
	return URXH0;
}

void printHex(uint32_t value)
{
	int i=0;	
	char output[8]={0};

	for(i = 0;i<8;i++)
	{
		output[i] = value & 0xf;
		value >>= 4;
	}

	puts("0x");
	for(i = 7; i>=0; i--)
	{
		if(output[i]>=0 && output[i]<=9)
			output[i] += '0';
		else
			output[i] = output[i] - 10 + 'A';
		putc(output[i]);
	}
	putc('\n');
}

void puts(char* string)
{
	while(*string)
	{
		putc(*string++);
	}
}

void testPrint()
{
	puts("111\n");
}

#include <stdint.h>

#include "s3c2440.h"
#include "led.h"
#include "uart.h"

int main()
{
	//HardwareInitAll();
	//UartInit();

	puts("main function!\n");
	while(1);
	return 0;
}

CPSR phenomenon is in turn defined print mode, the main function strings and string undefined string, CPSR software interrupts, software interrupts.

There is a play of soft interrupt SWI active trigger, you can take a number of operations, so that our handler can determine what actions need to be performed in accordance with the number of the operation. Here the idea is to get addresses of SWI by LR, the value of the extracted address, the operand reference manual extraction section according to ARM instructions to complete the operation.

You can see the number of operating SWI is 0-23bit. An instruction is 4Bytes, the address can be obtained directly by calling SWI LR-4.

Start.S

.text
.global _start

_start:
	B RESET	
	LDR pc,UNDEFIE
	LDR pc,SW_INTERRUPT

...//省略重复代码
	
DO_SWI:
	//1.设置栈
	LDR SP,=0x33e00000
	//2.保存现场
	STMDB SP!,{R0-R12,LR}
	
	//处理函数
	MRS R0,CPSR
	LDR R1,=SWI_TEST_STRING
	SUB R2,LR,#4                            //减去4,得到SWI地址
    BL SWIHandler
	
	//3.恢复现场,跳转回原来的位置
	LDMIA SP!,{R0-R12,PC}^  //^ 表示将SPSR恢复到CPSR中

UND_TEST_STRING:
	.string "enter undefin mode!\n"
	
SWI_TEST_STRING:
	.string "enter swi mode!\n"

...

TEST_SWI:
	MRS R0,CPSR
	BIC R0,R0,#0x0F
	MSR CPSR,R0
	SWI 0x123
	
	LDR pc,=main
halt:
    B halt
execption.c
-----------------------
#include "execption.h"
#include "uart.h"

void ExecptionHandle(uint32_t CPSR,char* string)
{
	printHex(CPSR);
	puts(string);
}


void SWIHandler(uint32_t CPSR,char* string,uint32_t* opera_address)
{
	ExecptionHandle(CPSR,string);
	printHex((*opera_address) & 0xFFFFFF);
}

Print output is 0x123.

 
Published 19 original articles · won praise 7 · views 6919

Guess you like

Origin blog.csdn.net/G_METHOD/article/details/104547407