当前位置:网站首页>arm-4-裸板开发

arm-4-裸板开发

2022-08-09 23:01:00 Btobk

程序链接(运行)地址和程序地址

ld文件就是链接文件,链接地址是指程序运行的地址在哪里(运行的时候,放到内存里去运行),程序地址是指程序储存在哪里

在芯片手册中找到gpio,控制地址,设置接口,最核心的就是start.s文件

make – 烧录到sd卡(自带的工具) – evm设置 – 上电
使用minitool
在这里插入图片描述
200000是链接地址

使用sd卡,可以将程序拷贝到0x0000,没有superboot也可以运行
使用minitool,可以将程序拷贝到0x2000,必须要有superboot才可以运行
那么其中到底发生了什么事情呢,为什么他们两个有差异

arm启动顺序

1.看文档在这里插入图片描述
2.看文档,芯片手册-overview

dmz:隔离区

sfrs;特殊寄存器

在这里插入图片描述
这块叫什么呢?
在这里插入图片描述

这块叫boot area 启动区,裸板程序就在这里,因为irom里面有一块固化代码,包含了看门狗等,这也就是为什么裸板不用看门狗,把程序放在这里,他就直接跑起来了

外设总线寻址地址
在这里插入图片描述
控制器–onenand

在这里插入图片描述
所以有boot就烧到20000,没有就烧到0000(起始地址)

看看启动了

gpio和boot启动

rom里面的固有程序会把硬盘中的第一段bootloader程序(16k校验)搬到芯片内部iram,如果运行成功,就搬第二段,全成功了就启动os,再把os转到内存里

在这里插入图片描述

1.启动irom上面的code
2.搬bl1到iram
3.搬bl2到ram
4.bl2启动os kernel
5…os kernel 到dram

裸板程序是在iram上运行的
superboot是在第6步完成,superboot实际上帮忙完成了2,3两步骤

在这里插入图片描述
在这里插入图片描述
因为有一个16k的偏移,所以才会是D002001![在这里插入图片描述](https://img-blog.csdnimg.cn/40a8b542841d4acebbaeff6d9c223f1e.png在这里插入图片描述

GPIO

怎么操作GPIO呢,那我们的led灯来举例:
打开芯片手册和电路图,在电路图里面搜索led,在芯片手册里面搜索

在这里插入图片描述

在芯片手册中可以找到组
在这里插入图片描述
在芯片手册中找到位置
在这里插入图片描述
寄存器有8个,每个4位,也就是总共要有21位
灯亮的地址是0001
四个灯要亮就是0000 0000 0000 0000 0001 0001 0001 0001
转换成16进制就是0x0000 1111

我们看一下,他的程序储存在哪里
在这里插入图片描述
储存在这里,sfrs特殊寄存器里

我们知道了启动位置之后,就可以开始实验:
实验目标:
1.使用汇编来进行裸板程序点亮led
2.用c完成实验一
3.通过key来控制led的点亮
4.优化程序,makefile,控制看门狗和cache缓存

1.使用汇编来进行裸板程序点亮led

需要做:
1.把0xE0200280设置成0x00001111的开灯模式
2.把0xE0200284设置成0x00, 所有位设置成0,低电平

mov r0,0xE0200280 这样是不行的,因为mov是只能操纵寄存器内部的,不能涉及到外部的存储器

ldr可以用于内部和外部寄存器的交换

ldr和mov的区别:	https://blog.csdn.net/heybeaman/article/details/79236462
				https://www.cnblogs.com/zhiminyu/p/15629073.html

ldr r0,#0xE0200280 这个意思是吧#0xE0200280里面的值读取到r0
所以也不行
改成:
ldr r0 ,= 0xE0200280 //这个意思就是把0xE0200280赋值到r0

mov r1 ,#0x00001111

str r1,[r0] //把r1的值存到r0的地址里面去

完整代码:
ldr r0 ,= 0xE0200284
mov r1 , 0x000011111
str r1,[r0]

在这里插入图片描述

编译make文件—生成bin文件—基于汇编文件
编译,链接参见链接文件,去头(binary是二进制的意思)
在这里插入图片描述

烧录bin文件,连接开发板,打开minitool和开发板
在这里插入图片描述

2.使用c语言

凡是和寄存器相关的地址,都要用到volatile,防止被修改优化

1.#define JPGCON ( * (volatile unsigned long * )0xE0200280)
(volatile unsigned long * )0xE0200280 指向地址
* (volatile unsigned long * )0xE0200280 指向地址的值

2.#define JPGDAT ( * (volatile unsigned long * )0xE0200284)

 #define JPGCON ( * (volatile unsigned long * )0xE0200280)
 #define JPGDAT ( * (volatile unsigned long * )0xE0200284)
 int main ()
	{
    
		JPGCON = 0x00001111;
		JPGDAT = 0x00;
		return 0;
	 }

修改汇编代码
源代码:

.text
		.global _start
		_start:
		
			LDR R0 ,= 0xE0200280
			MOV R1 , 0x00001111
			STR R1,[R0]

			LDR R0 ,= 0xE0200284
			MOV R1 , 0x00
			STR R1,[R0]
	`loop: 
			B loop

修改后的代码

.text
		.global _start
		_start:
			BL main
			B loop
			/* LDR R0 ,= 0xE0200280 MOV R1 , 0x00001111 STR R1,[R0] LDR R0 ,= 0xE0200284 MOV R1 , 0x00 STR R1,[R0] `loop: B loop /* 

在makefile中加入c的东西:

在这里插入图片描述
make,烧录

3.制作一个蜂鸣器的程序

在这里插入图片描述

汇编代码

.text
.global _start
_start:
	BL main

_loop:
	B _loop

电路图找到蜂鸣器–

在这里插入图片描述
在这里插入图片描述

通过引脚在芯片手册找到io口
在这里插入图片描述

在芯片手册,找到控制寄存器以及数字寄存器地址值
在这里插入图片描述
完善下思路
在这里插入图片描述
开始编写main。c

#define GPD0CON ( * (volatile unsigned long * )0xE020_00A0)
#define GPD0DAT ( * (volatile unsigned long * )0xE020_00A4)
int main ()
	{
    
		GPD0CON |= 1<<0;  //把引脚变成输出
		while(1) //死循环,一直响
		{
    
			buzzer_on();	//控制电平高
			delay(0x5000);	//延迟
			buzzer_off();	//控制低电平
			delay(0x5000);	//延迟
		}
		return 0;
	 }
void buzzer_on(void)
{
    
	GPD0DAT |= 1<<0 ; //1<<0的意思是1左移0位 *1<<2 = 100
	//|=就是或者,只要有一位是1,就是1,这里的意思是,把最后一位变成1,为什么不直接是1呢,因为这样子就可以指定哪一位是1
}

void buzzer_off(void)
{
    
	GPD0DAT &= ~(1<<0) ;~取反,1就是0
}

void delay(unsigned long count)
{
    
	volatitle unsigned long i = count;
	while (i--);
}

``

makefile
在这里插入图片描述

然后再烧写运行

使用button控制
找到button的引脚,再找到值,在找到地址
在这里插入图片描述
在这里插入图片描述

在芯片手册里面找到
在这里插入图片描述

#define GPD0CON ( * (volatile unsigned long * )0xE020_00A0)
#define GPD0DAT ( * (volatile unsigned long * )0xE020_00A4)
#define GPH0CON ( * (volatile unsigned long * )0xE020_0C40)
#define GPH0DAT ( * (volatile unsigned long * )0xE020_0C44)
int main ()
	{
    
		GPD0CON |= 1<<0;  //把引脚变成输出
		GPH0CON &= ~(1<<0)
		while(1) //死循环,一直响
		{
    
			if(GPH0DAT &1<<0))
				buzzer_off();
			else
				buzzer_on();
		}
		return 0;
	 }
void buzzer_on(void)
{
    
	GPD0DAT |= 1<<0 ; //1<<0的意思是1左移0位 *1<<2 = 100
	//|=就是或者,只要有一位是1,就是1,这里的意思是,把最后一位变成1,为什么不直接是1呢,因为这样子就可以指定哪一位是1
}

void buzzer_off(void)
{
    
	GPD0DAT &= ~(1<<0) ;~取反,1就是0
}

void delay(unsigned long count)
{
    
	volatitle unsigned long i = count;
	while (i--);
}

修改makefile

特别注意的事情是,因为死循环太占用资源而且不方便,所以通常不采用这种轮询的方式,而是采用中断的方式

原网站

版权声明
本文为[Btobk]所创,转载请带上原文链接,感谢
https://blog.csdn.net/weixin_42427637/article/details/126124864