arm-4-裸板开发

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

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

0xe地址,我们看一下,他的程序储存在哪里
在这里插入图片描述
储存在这里,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;  //把引脚变成输出,最后一位变成1
		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))//按键的电平如果为0001:1&1 = 1则
				buzzer_off();
			else//按键的电平如果为0000:0&1 = 0则
				buzzer_on();
		}
		return 0;
	 }
void buzzer_on(void)
{
	GPD0DAT |= 1<<0 ; //1<<0的意思是1左移0位   *1<<2 = 100
	//|=就是或者,只要有一位是1,就是1,这里的意思是,把最后一位变成1,为什么不直接是0x01呢,因为这样子就可以指定哪一位是1
}

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

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

修改makefile

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

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Btobk

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值