orangepi3 lts裸机点灯

8 篇文章 0 订阅
4 篇文章 0 订阅

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.pdf17页开始的方法将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上玩裸机的也是基本没看到过。

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值