历史上的今天
今天是:2024年10月12日(星期六)
2018年10月12日 | Tiny210裸机之按键中断
2018-10-12 来源:eefocus
start.S源码:
.global _start
_start:
ldr sp, =0xD0030000 // 初始化栈,因为后面要调用C函数
bl clock_init // 初始化时钟
bl ddr_init // 初始化内存
bl nand_init // 初始化NAND
ldr r0, =0x36000000 // 要拷贝到DDR中的位置
ldr r1, =0x0 // 从NAND的0地址开始拷贝
ldr r2, =bss_start // BSS段的开始地址
sub r2,r2,r0 // 要拷贝的大小
bl nand_read // 拷贝数据
clean_bss:
ldr r0, =bss_start
ldr r1, =bss_end
mov r3, #0
cmp r0, r1
ldreq pc, =on_ddr
clean_loop:
str r3, [r0], #4
cmp r0, r1
bne clean_loop
ldr pc, =on_ddr
on_ddr:
mrs r0, cpsr
bic r0,r0,#0x1f // 清M4~M0
orr r0,r0,#0x12
msr cpsr,r0 // 进入irq
ldr sp, =0x3e000000 // 初始化普通中断模式的栈,指向内存
bl irq_init
mrs r0, cpsr
bic r0,r0,#0x9f // 开总的中断开关,清M4~M0
orr r0,r0,#0x10
msr cpsr,r0 // 进入user mode
ldr sp, =0x3f000000 // 初始化用户模式的栈,指向内存
ldr pc, =main
halt:
b halt
.global key_IRQ
key_IRQ:
sub lr, lr, #4 // 1.计算返回地址
stmdb sp!, {r0-r12, lr} // 2.保护现场
// 3. 处理异常
bl do_irq
// 4. 恢复现场
ldmia sp!, {r0-r12, pc}^ // ^表示把spsr恢复到cpsr
===================================================================
irq.c源码:
#include "lib.h"
#define GPH2CON (*(volatile unsigned int *)0xE0200C40)
#define GPH2DAT (*(volatile unsigned int *)0xE0200C44)
#define GPH3CON (*(volatile unsigned int *)0xE0200C60)
#define GPH3DAT (*(volatile unsigned int *)0xE0200C64)
#define EXT_INT_2_CON (*(volatile unsigned int *)0xE0200E08)
#define EXT_INT_3_CON (*(volatile unsigned int *)0xE0200E0C)
#define EXT_INT_2_MASK (*(volatile unsigned int *)0xE0200F08)
#define EXT_INT_3_MASK (*(volatile unsigned int *)0xE0200F0C)
#define VIC0INTSELECT (*(volatile unsigned int *)0xF200000C)
#define VIC0INTENABLE (*(volatile unsigned int *)0xF2000010)
#define VIC0VECTADDR16 (*(volatile unsigned int *)0xF2000140)
#define VIC0ADDRESS (*(volatile unsigned int *)0xF2000F00)
#define EXT_INT_2_PEND (*(volatile unsigned int *)0xE0200F48)
#define EXT_INT_3_PEND (*(volatile unsigned int *)0xE0200F4c)
int i = 0;
void do_irq(void)
{
// 清中断
EXT_INT_2_PEND |= 1<<3;
EXT_INT_3_PEND |= 1<<0;
// 清中断向量
VIC0ADDRESS = 0;
if(!(GPH2DAT & (1<<3)))
{
wy_printf("counter(k4) : %d \n",i++);
}
if(!(GPH3DAT & (1<<0)))
{
wy_printf("counter(K5) : %d \n",i--);
}
}
extern void key_IRQ(void);
void irq_init(void)
{
// 设置GPH2_3(K4),GPH3_0(K5)用于中断
GPH2CON |= 0xf<<12;
GPH3CON |= 0xf<<0;
// 设置触发方式为下降沿触发
EXT_INT_2_CON |= 0x2<<12;
EXT_INT_3_CON |= 0x2<<0;
// 使能中断(GPIO里面的)
EXT_INT_2_MASK &= ~(1<<3);
EXT_INT_3_MASK &= ~(1<<0);
// 设置为IRQ中断
VIC0INTSELECT &= ~(1<<16);
// 使能中断(中断控制器里面的)
VIC0INTENABLE |= 1<<16;
// 设置中断向量
VIC0VECTADDR16 = (int)key_IRQ;
}
==================================================================
main.c源码:
#include "command.h"
#include "clock.h"
#include "led.h"
#include "uart.h"
#include "lib.h"
#include "nand.h"
#define CFG_PROMPT "WY_BOOT # " // Monitor Command Prompt
#define CFG_CBSIZE 256 // Console I/O Buffer Size
char *argv[10];
int readline (const char *const prompt)
{
char console_buffer[CFG_CBSIZE]; // console I/O buffer
char *buf = console_buffer;
int argc = 0;
int state = 0;
//puts(prompt);
wy_printf("%s",prompt);
gets(console_buffer);
while (*buf)
{
if (*buf != ' ' && state == 0)
{
argv[argc++] = buf;
state = 1;
}
if (*buf == ' ' && state == 1)
{
*buf = '\0';
state = 0;
}
buf++;
}
return argc;
}
void message(void)
{
wy_printf("\nThis bootloader support some command to test peripheral:\n");
wy_printf("Such as: LCD, IIS, BUZZER \n");
wy_printf("Try 'help' to learn them \n\n");
}
int main(void)
{
char buf[6];
int argc = 0;
int i = 0;
led_init(); // 设置对应管脚为输出
uart_init(); // 初始化UART0
nand_read_id(buf);
wy_printf("\n**********************************************************\n");
wy_printf(" wy_bootloader\n");
wy_printf(" vars: %d \n",2012);
wy_printf(" nand id:");
putchar_hex(buf[0]);
putchar_hex(buf[1]);
putchar_hex(buf[2]);
putchar_hex(buf[3]);
putchar_hex(buf[4]);
wy_printf("\n**********************************************************\n");
while (1)
{
argc = readline (CFG_PROMPT);
if(argc == 0 && i ==0)
{
message();
i=1;
}
run_command(argc, argv);
}
return 0;
}
==================================================================
Makefile文件:
uart.bin:start.s main.c uart.c clock.c led.c lib.c command.c nand.c mem_setup.S irq.c
arm-linux-gcc -nostdlib -c start.s -o start.o
arm-linux-gcc -nostdlib -c main.c -o main.o
arm-linux-gcc -nostdlib -c uart.c -o uart.o
arm-linux-gcc -nostdlib -c lib.c -o lib.o
arm-linux-gcc -nostdlib -c clock.c -o clock.o
arm-linux-gcc -nostdlib -c led.c -o led.o
arm-linux-gcc -nostdlib -c command.c -o command.o
arm-linux-gcc -nostdlib -c nand.c -o nand.o
arm-linux-gcc -nostdlib -c irq.c -o irq.o
arm-linux-gcc -nostdlib -c mem_setup.S -o mem_setup.o
arm-linux-ld -T bootloader.lds start.o main.o uart.o lib.o clock.o led.o command.o nand.o mem_setup.o irq.o -o uart_elf
arm-linux-objcopy -O binary -S uart_elf uart.bin
clean:
rm -rf *.o *.bin uart_elf *.dis
===================================================================
bootloader.lds链接文件:
SECTIONS {
. = 0x36000010;
.text : {
* (.text)
}
. = ALIGN(4);
.rodata : {
* (.rodata)
}
. = ALIGN(4);
.data : {
* (.data)
}
. = ALIGN(4);
bss_start = .;
.bss : { *(.bss) *(COMMON) }
bss_end = .;
}
史海拾趣
|
核心器件: MAX1714 最近推出的各种集成式降压 DC/DC变换器均已采取对外接低侧MOSFET同步整流器的电压降采样的方法,无需高侧电流检测电阻器。这种拓扑节省了检测电阻器的成本和印制电路板的空间,也适当提高了电路效率。但是,MOS ...… 查看全部问答> |
|
本文有模拟电路、数字电路、单片机电路、ARM硬件、ARM编程等基础知识,里面还有电阻、电容、半导体二级管三极管等元器件的介绍,还有电源电路、电路设计、通信系统等。欢迎想学电子基础知识的人下载。… 查看全部问答> |
|
我最近在学华恒ARM9,用的是三星S3C2410当做到中断这个问题的时候,遇到了问题,还请各位大虾帮忙 问题如下: 1、不管我把中断置一还是置零都没看到区别,和芯片资料有出入,为什么会这样 2、我把中断待决寄存器和源待决寄存器的值读出来,发现 ...… 查看全部问答> |
|
液晶屏初始化时花屏了!(LCD12864带字库的)LCD12864 带字库的。在我对液晶屏初始化时,设置到“进入设定点”这一步,用api函数SSIDataPut(SSI_BASE, data) 发送命令字0x06,就花屏了!这是为什么? … 查看全部问答> |




