概述
armv8-a裸机
板子信息
用的orangepi3 lts开发板,资料是真不多。只能自己撸手册,能用的工具也是有限。主芯片SOC用的Allwinner H6, A53的内核,armv8-a64位指令集。
步骤
- 装编译器
- 看原理图
- 看数据手册
- 找可用项目移植
- 装linux
- 传输程序到开发板mmc硬盘或SD卡
- 用u-boot跑裸机程序
装编译器
不同版本指令集需要使用不同版本编译器,这也是嵌入式开发最烦的地方,除了这
个还有不同公司,不同选项编译器。足够让人头大。最开始我使用arm-none-eabi
工具链编译出来,放板子上语法错误。后面发现需要用aarch64-linux-gnu工具链。在电脑上的Ubuntu或者Window的Ubuntu的子系统中安装编译器。
sudo apt install gcc-aarch64-linux-gnu
查看数据手册
看到板子上有两个led,分别是PWR-LED和STATUS-LED,分别对应PL4和PL7引脚。高
电平时LED点亮,低电平熄灭。
查看数据手册
查看数据手册主要是为了确定GPIO相关寄存器地址,Allwinner_H6_V200_User_Manual_V1.1.pdf
用户手册的379页给出了GPIO的相关寄存器地址和配置信息。对于PL相关的在434页。对于点灯主要就用到以下3个:
- GPIOL configure registers(0x07022000) 配置寄存器
- GPIOL pull registers(0x0702201C) 上拉,下拉
- GPIOL date registers(0x07022010) 输入,输出数据
我根据手册写了一个头文件,定义了各GPIO寄存器
#ifndef _H6_GPIO_H
#define _H6_GPIO_H
#define register(address) (*(volatile unsigned int *)address)
#define GPIO_BASE 0x0300B000
#define GPIOS_BASE 0x07022000
#define GPIOC_CFG0 (GPIO_BASE + 2 * 0x0024 + 0x00)
#define GPIOC_CFG1 (GPIO_BASE + 2 * 0x0024 + 0x04)
#define GPIOC_CFG2 (GPIO_BASE + 2 * 0x0024 + 0x08)
#define GPIOC_CFG3 (GPIO_BASE + 2 * 0x0024 + 0x0C)
#define GPIOC_DAT
(GPIO_BASE + 2 * 0x0024 + 0x10)
#define GPIOC_DRV0
(GPIO_BASE + 2 * 0x0024 + 0x14)
#define GPIOC_DRV1
(GPIO_BASE + 2 * 0x0024 + 0x18)
#define GPIOC_PUL0
(GPIO_BASE + 2 * 0x0024 + 0x1c)
#define GPIOC_PUL1
(GPIO_BASE + 2 * 0x0024 + 0x20)
#define GPIOC_INT_CFG0 (GPIO_BASE + 0x200+2*0x20+0x00)
#define GPIOC_INT_CFG1 (GPIO_BASE + 0x200+2*0x20+0x04)
#define GPIOC_INT_CFG2 (GPIO_BASE + 0x200+2*0x20+0x08)
#define GPIOC_INT_CFG3 (GPIO_BASE + 0x200+2*0x20+0x0c)
#define GPIOC_INT_CTL (GPIO_BASE + 0x200+2*0x20+0x10)
#define GPIOC_INT_STA (GPIO_BASE + 0x200+2*0x20+0x14)
#define GPIOC_INT_DEB (GPIO_BASE + 0x200+2*0x20+0x18)
#define GPIOD_CFG0 (GPIO_BASE + 3 * 0x0024 + 0x00)
#define GPIOD_CFG1 (GPIO_BASE + 3 * 0x0024 + 0x04)
#define GPIOD_CFG2 (GPIO_BASE + 3 * 0x0024 + 0x08)
#define GPIOD_CFG3 (GPIO_BASE + 3 * 0x0024 + 0x0C)
#define GPIOD_DAT
(GPIO_BASE + 3 * 0x0024 + 0x10)
#define GPIOD_DRV0
(GPIO_BASE + 3 * 0x0024 + 0x14)
#define GPIOD_DRV1
(GPIO_BASE + 3 * 0x0024 + 0x18)
#define GPIOD_PUL0
(GPIO_BASE + 3 * 0x0024 + 0x1c)
#define GPIOD_PUL1
(GPIO_BASE + 3 * 0x0024 + 0x20)
#define GPIOD_INT_CFG0 (GPIO_BASE + 0x200+3*0x20+0x00)
#define GPIOD_INT_CFG1 (GPIO_BASE + 0x200+3*0x20+0x04)
#define GPIOD_INT_CFG2 (GPIO_BASE + 0x200+3*0x20+0x08)
#define GPIOD_INT_CFG3 (GPIO_BASE + 0x200+3*0x20+0x0c)
#define GPIOD_INT_CTL (GPIO_BASE + 0x200+3*0x20+0x10)
#define GPIOD_INT_STA (GPIO_BASE + 0x200+3*0x20+0x14)
#define GPIOD_INT_DEB (GPIO_BASE + 0x200+3*0x20+0x18)
#define GPIOF_CFG0 (GPIO_BASE + 5 * 0x0024 + 0x00)
#define GPIOF_CFG1 (GPIO_BASE + 5 * 0x0024 + 0x04)
#define GPIOF_CFG2 (GPIO_BASE + 5 * 0x0024 + 0x08)
#define GPIOF_CFG3 (GPIO_BASE + 5 * 0x0024 + 0x0C)
#define GPIOF_DAT
(GPIO_BASE + 5 * 0x0024 + 0x10)
#define GPIOF_DRV0
(GPIO_BASE + 5 * 0x0024 + 0x14)
#define GPIOF_DRV1
(GPIO_BASE + 5 * 0x0024 + 0x18)
#define GPIOF_PUL0
(GPIO_BASE + 5 * 0x0024 + 0x1c)
#define GPIOF_PUL1
(GPIO_BASE + 5 * 0x0024 + 0x20)
#define GPIOF_INT_CFG0 (GPIO_BASE + 0x200+5*0x20+0x00)
#define GPIOF_INT_CFG1 (GPIO_BASE + 0x200+5*0x20+0x04)
#define GPIOF_INT_CFG2 (GPIO_BASE + 0x200+5*0x20+0x08)
#define GPIOF_INT_CFG3 (GPIO_BASE + 0x200+5*0x20+0x0c)
#define GPIOF_INT_CTL (GPIO_BASE + 0x200+5*0x20+0x10)
#define GPIOF_INT_STA (GPIO_BASE + 0x200+5*0x20+0x14)
#define GPIOF_INT_DEB (GPIO_BASE + 0x200+5*0x20+0x18)
#define GPIOG_CFG0 (GPIO_BASE + 6 * 0x0024 + 0x00)
#define GPIOG_CFG1 (GPIO_BASE + 6 * 0x0024 + 0x04)
#define GPIOG_CFG2 (GPIO_BASE + 6 * 0x0024 + 0x08)
#define GPIOG_CFG3 (GPIO_BASE + 6 * 0x0024 + 0x0C)
#define GPIOG_DAT
(GPIO_BASE + 6 * 0x0024 + 0x10)
#define GPIOG_DRV0
(GPIO_BASE + 6 * 0x0024 + 0x14)
#define GPIOG_DRV1
(GPIO_BASE + 6 * 0x0024 + 0x18)
#define GPIOG_PUL0
(GPIO_BASE + 6 * 0x0024 + 0x1c)
#define GPIOG_PUL1
(GPIO_BASE + 6 * 0x0024 + 0x20)
#define GPIOG_INT_CFG0 (GPIO_BASE + 0x200+6*0x20+0x00)
#define GPIOG_INT_CFG1 (GPIO_BASE + 0x200+6*0x20+0x04)
#define GPIOG_INT_CFG2 (GPIO_BASE + 0x200+6*0x20+0x08)
#define GPIOG_INT_CFG3 (GPIO_BASE + 0x200+6*0x20+0x0c)
#define GPIOG_INT_CTL (GPIO_BASE + 0x200+6*0x20+0x10)
#define GPIOG_INT_STA (GPIO_BASE + 0x200+6*0x20+0x14)
#define GPIOG_INT_DEB (GPIO_BASE + 0x200+6*0x20+0x18)
#define GPIOH_CFG0 (GPIO_BASE + 7 * 0x0024 + 0x00)
#define GPIOH_CFG1 (GPIO_BASE + 7 * 0x0024 + 0x04)
#define GPIOH_CFG2 (GPIO_BASE + 7 * 0x0024 + 0x08)
#define GPIOH_CFG3 (GPIO_BASE + 7 * 0x0024 + 0x0C)
#define GPIOH_DAT
(GPIO_BASE + 7 * 0x0024 + 0x10)
#define GPIOH_DRV0
(GPIO_BASE + 7 * 0x0024 + 0x14)
#define GPIOH_DRV1
(GPIO_BASE + 7 * 0x0024 + 0x18)
#define GPIOH_PUL0
(GPIO_BASE + 7 * 0x0024 + 0x1c)
#define GPIOH_PUL1
(GPIO_BASE + 7 * 0x0024 + 0x20)
#define GPIOH_INT_CFG0 (GPIO_BASE + 0x200+7*0x20+0x00)
#define GPIOH_INT_CFG1 (GPIO_BASE + 0x200+7*0x20+0x04)
#define GPIOH_INT_CFG2 (GPIO_BASE + 0x200+7*0x20+0x08)
#define GPIOH_INT_CFG3 (GPIO_BASE + 0x200+7*0x20+0x0c)
#define GPIOH_INT_CTL (GPIO_BASE + 0x200+7*0x20+0x10)
#define GPIOH_INT_STA (GPIO_BASE + 0x200+7*0x20+0x14)
#define GPIOH_INT_DEB (GPIO_BASE + 0x200+7*0x20+0x18)
#define GPIOL_CFG0 (GPIOS_BASE + 0 * 0x0024 + 0x00)
#define GPIOL_CFG1 (GPIOS_BASE + 0 * 0x0024 + 0x04)
#define GPIOL_CFG2 (GPIOS_BASE + 0 * 0x0024 + 0x08)
#define GPIOL_CFG3 (GPIOS_BASE + 0 * 0x0024 + 0x0C)
#define GPIOL_DAT
(GPIOS_BASE + 0 * 0x0024 + 0x10)
#define GPIOL_DRV0
(GPIOS_BASE + 0 * 0x0024 + 0x14)
#define GPIOL_DRV1
(GPIOS_BASE + 0 * 0x0024 + 0x18)
#define GPIOL_PUL0
(GPIOS_BASE + 0 * 0x0024 + 0x1c)
#define GPIOL_PUL1
(GPIOS_BASE + 0 * 0x0024 + 0x20)
#define GPIOL_INT_CFG0 (GPIOS_BASE + 0x200+0*0x20+0x00)
#define GPIOL_INT_CFG1 (GPIOS_BASE + 0x200+0*0x20+0x04)
#define GPIOL_INT_CFG2 (GPIOS_BASE + 0x200+0*0x20+0x08)
#define GPIOL_INT_CFG3 (GPIOS_BASE + 0x200+0*0x20+0x0c)
#define GPIOL_INT_CTL (GPIOS_BASE + 0x200+0*0x20+0x10)
#define GPIOL_INT_STA (GPIOS_BASE + 0x200+0*0x20+0x14)
#define GPIOL_INT_DEB (GPIOS_BASE + 0x200+0*0x20+0x18)
#define GPIOM_CFG0 (GPIOS_BASE + 1 * 0x0024 + 1x00)
#define GPIOM_CFG1 (GPIOS_BASE + 1 * 0x0024 + 1x04)
#define GPIOM_CFG2 (GPIOS_BASE + 1 * 0x0024 + 1x08)
#define GPIOM_CFG3 (GPIOS_BASE + 1 * 0x0024 + 1x0C)
#define GPIOM_DAT
(GPIOS_BASE + 1 * 0x0024 + 1x10)
#define GPIOM_DRV0
(GPIOS_BASE + 1 * 0x0024 + 1x14)
#define GPIOM_DRV1
(GPIOS_BASE + 1 * 0x0024 + 1x18)
#define GPIOM_PUL0
(GPIOS_BASE + 1 * 0x0024 + 1x1c)
#define GPIOM_PUL1
(GPIOS_BASE + 1 * 0x0024 + 1x20)
#define GPIOM_INT_CFG0 (GPIOS_BASE + 1x200+1*0x20+0x00)
#define GPIOM_INT_CFG1 (GPIOS_BASE + 1x200+1*0x20+0x04)
#define GPIOM_INT_CFG2 (GPIOS_BASE + 1x200+1*0x20+0x08)
#define GPIOM_INT_CFG3 (GPIOS_BASE + 1x200+1*0x20+0x0c)
#define GPIOM_INT_CTL (GPIOS_BASE + 1x200+1*0x20+0x10)
#define GPIOM_INT_STA (GPIOS_BASE + 1x200+1*0x20+0x14)
#define GPIOM_INT_DEB (GPIOS_BASE + 1x200+1*0x20+0x18)
// Mode Type
// 此处根据使用习惯对值进行取反操作,因为原始默认值为0x77777777
#define MODE_INPUT
0xf
#define MODE_OUTPUT 0xe
// Muli Driving
#define MULI_DRV_0
0x0
#define MULI_DRV_1
0x1
#define MULI_DRV_2
0x2
#define MULI_DRV_3
0x3
//Pull Down or Pull Up
#define PULL_DIS
0x0
#define PULL_DOWN 0x1
#define PULL_UP
0x2
#endif
找可用项目移植
也是花了好长一段时间才找到这个简单项目,好更改的项目,可以在此项目上自己添加
功能。
git clone https://gitee.com/dawendiguo/arm64-baremetal-demo.git
将aarch和script目录复制到目前目录,更改baremetal.ld和Makefile
# baremetal.ld
# 就改了下启动开始地址,改成了0x40008000,不改应该也可以
ENTRY(_Reset)
SECTIONS
{
. = 0x40008000;
.startup . : { head.o(.text) }
.text : { *(.text) }
.data : { *(.data) }
.bss : { *(.bss COMMON) }
. = ALIGN(8);
. = . + 0x1000; /* 4kB of stack memory */
stack_top = .;
}
Makefile
# head.s和baremetal.ld位置改了,usart相关代码删除了
ifeq ($(strip $(V)),)
E = @echo
Q = @
else
E = @#
Q =
endif
export E Q
CROSS_PREFIX=aarch64-linux-gnu-
CFLAGS += -I include
all: work.bin
main.o: main.c gpio.h
$(E) "
CC
" $@
$(Q) $(CROSS_PREFIX)gcc $(CFLAGS) -c $< -o $@
$(Q) $(CROSS_PREFIX)as -c $< -o $@
work.elf: main.o head.o
$(E) "
LINK
" $@
$(Q) $(CROSS_PREFIX)ld -Tbaremetal.ld $^ -o $@
work.bin: work.elf
$(E) "
OBJCOPY " $@
$(Q) $(CROSS_PREFIX)objcopy -O binary $< $@
clean:
$(E) "
CLEAN
"
$(Q) rm -f
work.* *.o
最后再撸一个主函数main.c
/*
* Allwinner H6 芯片控制GPIOD15,GPIO16信号反转
*/
#include "gpio.h"
void delay(int sec);
int main(){
// 设置gpiol4,gpiol7为输出模式
register(GPIOL_CFG0) &= ~(MODE_OUTPUT << (4 * 4));
register(GPIOL_CFG0) &= ~(MODE_OUTPUT << (4 * 7));
// 都设置为上拉
register(GPIOL_PUL0) |= PULL_UP << (2 * 4);
register(GPIOL_PUL0) |= PULL_UP << (2 * 7);
while(1){
/*// 开GPIOL4,关GPIOL7*/
register(GPIOL_DAT) |= (1 << 4);
register(GPIOL_DAT) &= ~(1 << 7);
delay(10000);
/*// 关GPIOL4,开GPIOL7*/
register(GPIOL_DAT) |= (1 << 7);
register(GPIOL_DAT) &= ~(1 << 4);
delay(10000);
}
}
void delay(int sec){
for(int i = 0; i < sec; i++){
for(int j = 0; j < 10000; j++)
;
}
}
装linux
按OrangePi_3_LTS_H6_用户手册_v2.0.pdf
17页开始的方法将ubuntu烧写到emmc。顺便配置了一个sshd服务程序。
传输程序到开发板mmc硬盘或SD卡
其实最方便的是u-boot支持网络可以直接使用tftp传递程序文件,但不知道是什么原因我的u-boot没有网络,linux网络还没问题就是u-boot没网。只能用SD卡或直接传输到内部emmc。
# ssh 传输
scp user@host:path/filename
/
# SD卡保存,SD卡使用ext4或fat格式
mv main.bin SD卡根目录
u-boot启动
这里需要一个电脑USB转串口的工具,淘宝买一个20元以内。将GND,RX,TX3个引脚>插入开发板的J3调试口。
# 电脑上安装picocom
sudo apt install picocom
# 开启uart,没有权限用root用户
picocom -b 115200 /dev/ttyUSB0
# 开发板上电,如果没有显示开机u-boot信息交换RX,TX引脚,GND一定要插
# 上电开机进去u-boot到快进系统时会提示按空格进u-boot命令行,不行就多试几
次
(u-boot命令行)[],这里有简单u-boot命令行使用介绍,我们这里只用到几个命令>。
# 选择内部mmc或者SD卡
mmc list
# 根据自己实际选择硬盘,我的0是SD卡,1是内部mmc硬盘
mmc dev 0 或者 1
# 可以使用fatls或者ext4ls查看一下文件内容,有多个分区可以使用mmc 1:1 这种格式,1:1表示第1号硬盘第一个分区
ext4ls mmc 1:1
# 载入程序到内存,40008000是前面写程序时baremetal.ld中指定的起始地址
ext4load mmc 1:1 40008000 work.bin
# 运行程序
go 40008000
# 如果程序运行成功,应该就可以看到板子上的电源指示灯和状态指示灯,一红一黄交替闪烁了,
# 如果程序运行后开发板重启,有可能就是程序或者编译器有问题了。
至此算是完成了裸机跑soc芯片GPIO的程序了,接下来就可以进一步玩一下mmu和
Timer了,还有一个复杂的中断GIC。
总结起来相比树莓派,i.MX的板子,全志的资料真的是太有限了。很多项目也是
直接借鉴树莓派,要想自己玩还是比较困难。wiring库也是走的树莓派的老路,就
连实现方法也如出一辙,都是直接使用/dev/mem简单粗暴。不过万事开头难,既然
裸机都通了,linux驱动开发也就不远了。
郁闷的是目前国内的linux教程多是基于2.6版本,目前内核都5.19了变化也是相当
大。就我目前了解。2.6还在玩file_operations结构体,现在gpio都进化到又有其
他中间件了。原来操作arm寄存器直接自己写地址位置,现在又进化成dtb文件了。
真是改变无处不在,相比于目前国内落后的学习资料,不知道又要掉多少坑。
arm教程版本也是滞后的,有的还在讲arm4,arm5指令集。最新的armv9-a都已经出来了。感觉armv8-a的都难找到几个。CSDN上真正在orangepi3 lts上玩裸机的也是基本没看到过。
最后
以上就是过时麦片为你收集整理的orangepi3 lts裸机点灯armv8-a裸机的全部内容,希望文章能够帮你解决orangepi3 lts裸机点灯armv8-a裸机所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复