调试MCU经常需要用串口。
裸机前后台系统,基本就是基于定时器中断。
init.s 启动代码
Mode_USR EQU 0x10
Mode_FIQ EQU 0x11
Mode_IRQ EQU 0x12
Mode_SVC EQU 0x13
Mode_ABT EQU 0x17
Mode_UND EQU 0x1B
Mode_SYS EQU 0x1F
UND_Stack_Size EQU 0x00000400
SVC_Stack_Size EQU 0x00001000
ABT_Stack_Size EQU 0x00000400
FIQ_Stack_Size EQU 0x00000400
IRQ_Stack_Size EQU 0x00001000
USR_Stack_Size EQU 0x00001000
Heap_Size EQU 0x00010000
I_Bit EQU 0x80 ; when I bit is set, IRQ is disabled
F_Bit EQU 0x40 ; when F bit is set, FIQ is disabled
Stack_Top EQU 0x52000000
IMPORT main
PRESERVE8
AREA |VIC|,CODE,READONLY
ENTRY
start
mrc p15,0,r0,c1,c0,0
orr r0,r0,#(1<<24)
mcr p15,0,r0,c1,c0,0
LDR R0, =Stack_Top
MSR CPSR_c, #Mode_UND:OR:I_Bit:OR:F_Bit
MOV SP, R0
SUB R0, R0, #UND_Stack_Size
MSR CPSR_c, #Mode_ABT:OR:I_Bit:OR:F_Bit
MOV SP, R0
SUB R0, R0, #ABT_Stack_Size
MSR CPSR_c, #Mode_FIQ:OR:I_Bit:OR:F_Bit
MOV SP, R0
SUB R0, R0, #FIQ_Stack_Size
MSR CPSR_c, #Mode_IRQ:OR:I_Bit:OR:F_Bit
MOV SP, R0
SUB R0, R0, #IRQ_Stack_Size
MSR CPSR_c, #Mode_SVC:OR:I_Bit:OR:F_Bit
MOV SP, R0
SUB SL, SP, #USR_Stack_Size
MSR CPSR_c, #Mode_USR
MOV SP, R0
SUB SL, SP, #USR_Stack_Size
;使能IQR中断
MRS R0,CPSR
BIC R0,R0,#0x80
MSR CPSR_c,R0
bl main
END
6410_include.h 一些重定义类型 与宏定义。
#ifndef __DEF_H__
#define __DEF_H__
#define FIN 12000000 //晶振频率
// 读/写寄存器数据
#define Outp32(addr, data) (*(volatile u32 *)(addr) = (data))
#define Outp16(addr, data) (*(volatile u16 *)(addr) = (data))
#define Outp8(addr, data) (*(volatile u8 *)(addr) = (data))
#define Inp32(addr) (*(volatile u32 *)(addr))
#define Inp16(addr) (*(volatile u16 *)(addr))
#define Inp8(addr) (*(volatile u8 *)(addr))
typedef unsigned long u32;
typedef unsigned short u16;
typedef unsigned char u8;
typedef signed long s32;
typedef signed short s16;
typedef signed char s8;
#endif
uart.h 串口驱动头文件
#include '6410_include.h'
#ifndef __UART_H__
#define __UART_H__
#define ULCON0 (0x7F005000)
#define UCON0 (0x7F005004)
#define UFCON0 (0x7F005008)
#define UMCON0 (0x7F00500C)
#define UBRDIV0 (0x7F005028)
#define GPACON (0X7F008000)
#define GPAPUD (0X7F008008)
#define UTRSTAT0 (*(volatile unsigned *)(0x7F005010))
#define UTXH0 (*(volatile unsigned *)(0x7F005020))
#define UART_clock 66500000
#endif
void Uart0_Init(u32 baud);
void Uart_Putc(char ch);
void Uart_Puts(char *str);
void Uart_Printf(char *fmt,...);
uart.c 串口驱动
#include '6410_include.h'
#include
#include 'uart.h'
//端口初始化;
static void Uart0_Port_Init(void)
{
u32 uConValue;
uConValue = Inp32(GPACON);
uConValue = (uConValue & ~0xff) | 0x22; //配置为UART0功能;
Outp32(GPACON,uConValue);
uConValue = Inp32(GPAPUD);
uConValue &= ~0xf; //低4位配置为0000,上下拉电阻除能;
Outp32(GPAPUD,uConValue);
}
//uart初始化;
void Uart0_Init(u32 baud)
{
u32 pclk;
u32 uConValue;
u32 uTemp;
pclk = UART_clock;
Uart0_Port_Init();
uConValue = Inp32(ULCON0);
uConValue = (uConValue & ~0x3F) | 0x3;//配置为8位数据,1位停止位,0位校验位;
Outp32(ULCON0,uConValue);
uConValue = Inp32(UCON0);
uConValue= (uConValue & ~0x405| 0x405); //配置为中断或轮询模式,使用pclk作为波特率;
Outp32(UCON0,uConValue);
uConValue = Inp32(UFCON0);
uConValue = 0x0;//配置为非FIFO模式;
Outp32(UFCON0,uConValue);
uConValue = Inp32(UMCON0);
uConValue = 0x0;//配置为非中断,非流控模式;
Outp32(UMCON0,uConValue);
uTemp = (int)(pclk/16/baud)- 1;
Outp32(UBRDIV0,uTemp);//配置波特率;
Delay(10000);
}
//单字符输出;
void Uart_Putc(char ch)
{
if(ch == 'n')
{
while(!(UTRSTAT0 & 0x2));
UTXH0 = 'r';
}
while(!(UTRSTAT0 & 0x2));
UTXH0 = ch;
}
//字符串输出
void Uart_Puts(char *str)
{
while(*str)
{
Uart_Putc(*str++);
}
}
//格式化输出;
void Uart_Printf(char *fmt,...)
{
char str[256];
va_list ap;
va_start(ap,fmt); //va_start() 与 va_end() 需要对称
vsprintf(str,fmt,ap);
Uart_Puts(str);
va_end(ap);
}
timer0.h 定时器0头文件
#include '6410_include.h'
#ifndef __TIMER_H__
#define __TIMER_H__
#define TINT_CSTAT (*(volatile unsigned*)(0x7F006044))
#define TCFG0 (*(volatile unsigned*)(0x7F006000))
#define TCFG1 (*(volatile unsigned*)(0x7F006004))
#define TCON (*(volatile unsigned*)(0x7F006008))
#define TCNTB0 (*(volatile unsigned*)(0x7F00600C))
#define TCMPB0 (*(volatile unsigned*)(0x7F006010))
#define TCNTO0 (*(volatile unsigned*)(0x7F006014))
#define TCNTB1 (*(volatile unsigned*)(0x7F006018))
#define TCMPB1 (*(volatile unsigned*)(0x7F00601c))
#define TCNTO1 (*(volatile unsigned*)(0x7F006020))
#define TCNTB2 (*(volatile unsigned*)(0x7F006024))
#define TCNTO2 (*(volatile unsigned*)(0x7F00602c))
#define TCNTB3 (*(volatile unsigned*)(0x7F006030))
#define TCNTO3 (*(volatile unsigned*)(0x7F006038))
#define TCNTB4 (*(volatile unsigned*)(0x7F00603c))
#define TCNTO4 (*(volatile unsigned*)(0x7F006040))
#define VIC0ADDRESS (*(volatile unsigned *)(0x71200f00))
#define VIC0INTENABLE (*(volatile unsigned *)(0x71200010))
#define VIC0VECTADDR0 0x71200100
#define NUM_TIMER0 23
#endif //__TIMER_H__
void __irq Isr_TIMER0(void);
void Timer0_Init(u32 Time0_Value);
timer0.c 定时器驱动代码
#include 'timer0.h'
#include 'uart.h'
#include 'LED.h'
u8 led_sw = 1;
//中断服务函数
void __irq Isr_Timer(void)
{
led_sw = !led_sw;
LED1(led_sw);