编译Nuttx
Atmel SAM4S Xplained Pro
简介
Core
- ARM Cortex-M4 with 2 Kbytes of cache running at up to 120 MHz
- Memory Protection Unit (MPU)
- DSP Instruction Set
- Thumb ® -2 instruction set
Memories
- Up to 2048 Kbytes embedded Flash with optional dual-bank and cache memory, ECC, Security Bit and Lock Bits
- Up to 160 Kbytes embedded SRAM
- 16 Kbytes ROM with embedded boot loader routines (UART, USB) and IAP routines
- 8-bit Static Memory Controller (SMC): SRAM, PSRAM, NOR and NAND Flash support
同步
nuttx
与nuttx-apps
两个源代码,它们两个平级目录.1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35~$ git clone https://github.com/apache/incubator-nuttx nuttx
~$ git clone https://github.com/apache/incubator-nuttx-apps.git apps
~$ cd nuttx
# 列出所有支持板子.
~$ tools/configure.sh -L | grep "sam"
~$ tools/configure.sh -l sam4s-xplained-pro:nsh
~$ cp boards/arm/sam34/sam4s-xplained-pro/configs/nsh/defconfig .config
~$ cp boards/arm/sam34/sam4s-xplained-pro/scripts/Make.defs .
# 这里使用一个 第三方的工具链(gcc-arm-none-eabi-6-2017-q2-update) arm-none-eabi- 也可以编译成功.选择 CONFIG_ARMV7M_TOOLCHAIN_GNU_EABIL=y
~$ export PATH=/fullpath/gcc-arm-none-eabi-6-2017-q2-update/bin:$PATH
~$ make CROSSDEV=arm-none-eabi-
# 查看交㕚工具链支持的CPU特性.
~$ arm-none-eabi-g++ -print-multi-lib
.;
thumb;@mthumb
fpu;@mfloat-abi=hard
armv6-m;@mthumb@march=armv6s-m
armv7-m;@mthumb@march=armv7-m
armv7e-m;@mthumb@march=armv7e-m
armv7-ar/thumb;@mthumb@march=armv7
cortex-m7;@mthumb@mcpu=cortex-m7
armv7e-m/softfp;@mthumb@march=armv7e-m@mfloat-abi=softfp@mfpu=fpv4-sp-d16
armv7e-m/fpu;@mthumb@march=armv7e-m@mfloat-abi=hard@mfpu=fpv4-sp-d16
armv7-ar/thumb/softfp;@mthumb@march=armv7@mfloat-abi=softfp@mfpu=vfpv3-d16
armv7-ar/thumb/fpu;@mthumb@march=armv7@mfloat-abi=hard@mfpu=vfpv3-d16
cortex-m7/softfp/fpv5-sp-d16;@mthumb@mcpu=cortex-m7@mfloat-abi=softfp@mfpu=fpv5-sp-d16
cortex-m7/softfp/fpv5-d16;@mthumb@mcpu=cortex-m7@mfloat-abi=softfp@mfpu=fpv5-d16
cortex-m7/fpu/fpv5-sp-d16;@mthumb@mcpu=cortex-m7@mfloat-abi=hard@mfpu=fpv5-sp-d16
cortex-m7/fpu/fpv5-d16;@mthumb@mcpu=cortex-m7@mfloat-abi=hard@mfpu=fpv5-d16下面错误,可以打开源码位置,注释掉它.
1 | arch/arm/src/imxrt/Kconfig:1114: syntax error |
使用BuildRoot构建指交叉工具链
- buildroot nuttx
- 这里是使用
NuttX
提供的修改后的BuildRoot
版本.通过buildroot
编译出一个特殊版本的交叉工具链,再用它去编译出最终的nuttx
系统镜像.buildroot
的源码目录与nuttx,nuttx-apps
也是平级的目录.在实践过程中开启了BR2_GCC_CORTEX_M4F_SP
导致下面的DBUG
里出错的原因.也就是说Atmel SAM4S Xplained Pro
是cortex-m4
内核,但是它不带FPU
,强选FPU
肯定是出错的,
1 | ~$ git clone https://bitbucket.org/nuttx/buildroot.git buildroot |
- 如果成功会生成如下的目录.注意,如果开启了
BR2_ENABLE_MULTILIB=y
与BR2_SOFT_FLOAT=y
生成的目标目录是build_arm_nofpu
,否则生成的目录就是build_arm
.
1 | ~$ tree -L 2 build_arm_hf/ |
- 测试工具链
1 | ~$ export PATH=`pwd`/build_arm_hr/staging_dir/bin:$PATH |
- 如果出现下面的错误,在
make menuconfig
选择一个高版本的gdb
尝试一下.1
2
3
4/fullpath/buildroot/toolchain_build_arm_hf/gdb-7.9.1/gdb/python/python.c: In function ‘_initialize_python’:
/fullpath/buildroot/toolchain_build_arm_hf/gdb-7.9.1/gdb/python/python.c:1690:3: error: too few arguments to function ‘_PyImport_FixupBuiltin’
_PyImport_FixupBuiltin (gdb_module, "_gdb"); - 如果出现
gcc
编译时无法下载mpc,mpfr,gmp
的依赖包时,查看一下toolchain_build_arm_hf/gcc-4.9.4/contrib/download_prerequisites
.修改版本号,或者下载的地址.
gcc-4.7.4的补丁
- 在构建交㕚工具链时如果出现下面的错误
1 | In file included from .../gcc-4.7.4/gcc/cp/except.c:990:0: |
- 这里引用了cfns: fix mismatch in gnu_inline attributes的补丁.直接创建在
BuildRoot
的源码里.
1 | ~$ cat > toolchain/gcc/4.7.4/gnu_inline.patch <<EOF |
GCC-4.7.4的编译错误
1 | make[4]: Entering directory '/fullpath/buildroot/toolchain_build_arm_nofpu/gcc-4.7.4-build/libiberty/testsuite' |
- 编译时出现上面的错误,这好像是这个GCC版本的问题,在
4.9.x
好像没有出这样的错误,同是查看了各级的config.log
与各级的Makefile
也没有找出问题,后来只有进入到编译的目录内toolchain_build_arm/gcc-4.7.4-build
内直接运行make
,无错的话再回到buildroot
内,再运行make
这里就正常完成了.
配置NuttX
系统
1 | ~$ tools/configure.sh -l sam4s-xplained-pro:nsh |
Nuttx
的最终配置如下:
1 | ~$ grep -v '^$\|^#' .config |
- 编译时出现下面错误,这个有可能是配置时没有选择
CONFIG_ARCH_IRQPRIO=y
,然后就去make
后的结果.通过搜索nuttx
源码时发现,getcontrol(void)
是定义在arch/arm/include/armv7-m/irq.h
里的内联函数.最终在arch/arm/src/chip/sam_start.c
前面,添加#include <nuttx/irq.h>
就可以了.
1 | /fullpath/nuttx/staging/libarch.a(sam_start.o): In function `sam_fpuconfig': |
使用OpenOCD调试
编译OpenOCD
1 | ~$ git clone http://repo.or.cz/r/openocd.git |
根据
Nuttx
官方的Debugging Nuttx提示,基于某些特性调试,可能需要修改相应的openocd/src/rtos/nuttx_header.h
内的宏定义如:CONFIG_DISABLE_MQUEUE=y
.运行
OpenOCD
服务,通过PC端的USB连接到Atmel-SAM4S_Xpained-Pro
上写有DEBUG USB
的接口上,注意,该USB接口是板上调试器(EDBG)的组合接口,它包含三个接口功能:DEBUG,Virtual COM Port, Data Gateway Interface(DGI).
1 | # 这里如果定义板级配置也可直接: openocd -f board/atmel_sam4s_xplained_pro.cfg -c init -c "reset halt" |
- 使用GDB桥接到
OpenOCD
服务上去调试.
1 | ~$ arm-nuttx-eabi-gdb nuttx |
也可以把几个参数合在一行命令下提交,如
arm-nuttx-eabi-gdb -ex "target remote :3333" -ex "mon reset halt" nuttx
关于类似
ATSAM4SD32C.cpu -- clearing lockup after double fault
,参考了stackexchange处理.查看目标文件的内容.
1 | ~$ file nuttx |
GDB调试
OpenOCD
服务
1 | # ~$ openocd -f board/atmel_sam4s_xplained_pro.cfg -c init -c 'reset halt' -c '$_TARGETNAME configure -rtos nuttx' |
GDB连接
- 在
nuttx
的目录下运行,为了加载nuttx
文件.
1 | ~ nuttx$ arm-none-eabi-gdb -ex "target remote :3333" -ex "mon reset halt" nuttx |
- 定义一些
gdb hook
函数,只是为了方便一些调试,最好的方式是把这些define
放在~/.gdbinit
内, 但是要注意,你如果在用系统gdb
去调非nuttx
的程序时,
记得要删了~/.gdbinit
.
1 | (gdb) define hookpost-file |
- 连接远程
openocd
的端口
1 | (gdb) target extended-remote :3333 |
- 上线的
file nuttx
是加载文件的symbols
,因为定义了hook-file
,所以会在openocd
内显示,如:
1 | Error: No symbols for NuttX # 有可能会显示,如果每次都显示,是因为没有打开`CONFIG_DEBUG_SYMBOLS` |
- 查看调试线程信息.
1 | (gdb) info threads |
- 查看寄存器的信息
1 | (gdb) info registers |
设置断点
下面设置的断点是在文件的某行上面,为防止调试时程序跑飞,硬件重启后又需要重新设置断点,这里保存断点到
bp.txt
文件上,下次可以使用source bp.txt
加载.
1 | (gdb) b chip/sam_hsmci.c:757 |
- 查看调用栈,有时调试板子,在板子初始硬件时,串口打印还没有就绪时,此时用
backtrace
查看调用栈很有用,比如:晶振不起振.
1 | (gdb) backtrace |
- 单步(s = Step into, n = Step over),单步步入(Step Into)有时会进入很深的调用栈,如果要退回可以使用
finish
指令跳出.
1 | (gdb) step |
- 查看变量
1 | btle_main (argc=<error reading variable: value has been optimized out>, argv=<error reading variable: value has been optimized out>) at nrf24l01_btle.c:372 |
- hexdump 查看地址,数组
1 | (gdb) x /32bx data |
- 查看结构体的内容
1 | (gdb) set print pretty on |
烧写固件
- 烧写
flash0
,地址0x00400000
在链接脚本文件boards/arm/sam34/sam4s-xplained-pro/scripts/sam4s-xplained-pro.ld
里有定义.
1 | ~$ openocd -f board/atmel_sam4s_xplained_pro.cfg -c init -c "reset halt" -c "flash write_image erase nuttx.bin 0x00400000" -c "reset" |
- 连接到它的
UART
接口,进入系统.
1 | ~$ sudo minicom -o -b 115200 -D /dev/ttyACM0 |
NAND 移植
1 | sam_nand_initialize: CS0 |
- 读/写页(page),擦除块(block).在概念上,由大到小来说,就是:
1 | Nand Flash ⇒ Chip ⇒ Plane ⇒ Block ⇒ Page ⇒ oob |
1 | hexdump /dev/mtdblock0 count=128 |
- 格式化
nuttx
代码1
git status | grep "modified:" | awk '{print $2}' | xargs tools/checkpatch.sh -f
- 内存分布
SAMA5D3 Series
是参照Datasheet
第5章Memories
. SAM4S是SAM4S Datasheet Chapter 6 . Product Mapping
Arduino Due
- Arduino Due
- Hacking with the Arduino Due
- SAM3X-Arduino Pin Mapping
- The Arduino Due is a microcontroller board based on the Atmel SAM3X8E ARM Cortex-M3 CPU. It is the first Arduino board based on a 32-bit ARM core microcontroller. It has 54 digital input/output pins (of which 12 can be used as PWM outputs), 12 analog inputs, 4 UARTs (hardware serial ports), a 84 MHz clock, an USB OTG capable connection, 2 DAC (digital to analog), 2 TWI, a power jack, an SPI header, a JTAG header, a reset button and an erase button.
- 根据官方警示:
Arduino Due
的管脚只容3.3v
,高于3.3v
会损坏板子.
BOSSAC烧写
- 这里将使用它官方的烧写工具
BOSSAC
,它一般位于用户目录下.如:~/.arduino15/packages/arduino/tools/bossac/1.7.0-arduino3/bossac
.
检测目标板子信息
1 | ~$ bossac -p ttyACM0 -U false -i |
- 需要设置正确的端口参数,如果再不行,按
reset
再重试,如下:
1 | ~$ stty -F /dev/ttyACM0 speed 1200 cs8 -cstopb -parenb |
烧入nuttx.bin
1 | $ bossac -p ttyACM0 -U false -e -w -v -b nuttx.bin -R |
使用SWD烧写
- 除了使用
BOSSAC
,本来想使用SWD
接口与OpenOCD
来烧写调试.因为Due
板有一个排4针的DEBUG
接口,针脚是:1:RESET,2:SWDIO,3:SWCLK,4:GND
.1
2
3
4
5
6
7
8
9~$ cat > ~/sam3x8e.cfg<<EOF
source [find interface/stlink.cfg]
set CPUTAPID 0x2ba01477
source [find board/atmel_sam3x_ek.cfg]
EOF
~$ openocd -f ~/sam3x8e.cfg -c init -c halt -c "flash write_image erase nuttx.bin 0x80000" -c "at91sam3 gpnvm set 1" -c "exit"
使用板载AT16u2
烧写
在网上发现可以修改
AT16u2
的固件,使它成为CMSIS_DAP
,从而可以支持openocd
的烧写调试.
更新AT16u2的固件
烧写
AVR
芯片需要一个烧写器,如:avr JATG-ICE, AVR-ISP,Atmel-ICE,USBasp
.也可以把一块arduino
板子变成AVR-ISP
.如:Arduino Uno
. 但是这里有一块NUCLEO-L152RE
它有兼容arduino
的接口,可以使用stm32duino把它变成AVR-ISP
烧写器,烧入官方的ArduinoISP
进去.打开
Arduino IDE --> File --> examples(Builtin-examples) --> 11.ArduinoISP --> ArduinoISP
,烧写上传到NUCLEO-L152RE
.
1 | NUCLEO-L152RE Arduino Due (ICSP) |
avrdude
下载avrdude源码,
avrdude
是一个开源的AVR
烧写软件,它最新地板本是avrdude-6.3,通过源码可以查看它所支持的硬件详情.下面是使用
NUCLEO-L152RE
做为一个烧写器,按照上面接线,对Arduino Due
板上的at16u2
的固件进行更新.1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81~$ cd ~/.arduino15/packages/arduino/tools/avrdude/6.3.0-arduino17/
~$ tree
.
├── bin
│ └── avrdude
└── etc
└── avrdude.conf
~$ avrdude -c arduino -P /dev/ttyACM0 -b 19200 -p atmega16u2 -vvv -U flash:w:at16u2_cmsis_dap/at16u2_cmsis_dap.elf.hex:i
avrdude: Version 6.3-20171130
Copyright (c) 2000-2005 Brian Dean, http://www.bdmicro.com/
Copyright (c) 2007-2014 Joerg Wunsch
System wide configuration file is "/etc/avrdude.conf"
User configuration file is "/home/michael/.avrduderc"
User configuration file does not exist or is not a regular file, skipping
Using Port : /dev/ttyACM0
Using Programmer : arduino
Overriding Baud Rate : 19200
AVR Part : ATmega16U2
Chip Erase delay : 9000 us
PAGEL : PD7
BS2 : PC6
RESET disposition : possible i/o
RETRY pulse : SCK
serial program mode : yes
parallel program mode : yes
Timeout : 200
StabDelay : 100
CmdexeDelay : 25
SyncLoops : 32
ByteDelay : 0
PollIndex : 3
PollValue : 0x53
Memory Detail :
Block Poll Page Polled
Memory Type Mode Delay Size Indx Paged Size Size #Pages MinW MaxW ReadBack
----------- ---- ----- ----- ---- ------ ------ ---- ------ ----- ----- ---------
eeprom 65 20 4 0 no 512 4 128 9000 9000 0x00 0x00
Block Poll Page Polled
Memory Type Mode Delay Size Indx Paged Size Size #Pages MinW MaxW ReadBack
----------- ---- ----- ----- ---- ------ ------ ---- ------ ----- ----- ---------
flash 65 6 128 0 yes 16384 128 128 4500 4500 0x00 0x00
Block Poll Page Polled
Memory Type Mode Delay Size Indx Paged Size Size #Pages MinW MaxW ReadBack
----------- ---- ----- ----- ---- ------ ------ ---- ------ ----- ----- ---------
lfuse 0 0 0 0 no 1 0 0 9000 9000 0x00 0x00
Block Poll Page Polled
Memory Type Mode Delay Size Indx Paged Size Size #Pages MinW MaxW ReadBack
----------- ---- ----- ----- ---- ------ ------ ---- ------ ----- ----- ---------
hfuse 0 0 0 0 no 1 0 0 9000 9000 0x00 0x00
Block Poll Page Polled
Memory Type Mode Delay Size Indx Paged Size Size #Pages MinW MaxW ReadBack
----------- ---- ----- ----- ---- ------ ------ ---- ------ ----- ----- ---------
efuse 0 0 0 0 no 1 0 0 9000 9000 0x00 0x00
Block Poll Page Polled
Memory Type Mode Delay Size Indx Paged Size Size #Pages MinW MaxW ReadBack
----------- ---- ----- ----- ---- ------ ------ ---- ------ ----- ----- ---------
lock 0 0 0 0 no 1 0 0 9000 9000 0x00 0x00
Block Poll Page Polled
Memory Type Mode Delay Size Indx Paged Size Size #Pages MinW MaxW ReadBack
----------- ---- ----- ----- ---- ------ ------ ---- ------ ----- ----- ---------
calibration 0 0 0 0 no 1 0 0 0 0 0x00 0x00
Block Poll Page Polled
Memory Type Mode Delay Size Indx Paged Size Size #Pages MinW MaxW ReadBack
----------- ---- ----- ----- ---- ------ ------ ---- ------ ----- ----- ---------
signature 0 0 0 0 no 3 0 0 0 0 0x00 0x00
Programmer Type : Arduino
Description : Arduino
Hardware Version: 2
Firmware Version: 1.18
Topcard : Unknown
Vtarget : 0.0 V
Varef : 0.0 V
Oscillator : Off
SCK period : 0.1 us
跳线
- 因为
Due
板上的GND,RESET
已经连接到AT16u2
上了,这里Due
板内只需两根跳线就够了.所以此时的at16u2
就是一个CMSIS-DAP
的设备了.
1 | ICSP DEBUG(SWD) |
- 使用
OpenOCD
烧写.
1 | ~$ openocd -f interface/cmsis-dap.cfg -f board/atmel_sam3x_ek.cfg -c init -c halt -c "flash write_image erase nuttx.bin 0x80000" -c "at91sam3 gpnvm set 1" -c "exit" |
使用UM232H(FTDI)
做烧写器
- 上面的做法是使用一块
arduino
板做为烧写器,这里是使用FT232H USB to SPI/I2C
的小板来做为烧写器,连接板上的DEBUG(SWD)
.
1 | # FT232HQ minimodule channel 0 (Channel A) |
也可以使用
Due
板上的标准的ARM-JTAG-10pin
去调试,接线的方式如同上面,可以使用JTAG
信号,也可以只接SWD
信号.如果转接到一个20Pin
的板上,就需要对接相应的信号线.使用
OpenOCD
烧写,如果板上原来是arduino
镜像,需要按下reset
后,马上运行下面命令.
1 | ~$ openocd -f interface/ftdi/ft232h-module-swd.cfg -f board/atmel_sam3x_ek.cfg -c init -c halt -c "flash write_image erase nuttx.bin 0x80000" -c "at91sam3 gpnvm set 1" -c "exit" |
OpenOCD连接
其它
- Write code to FLASH don’t change boot mode and don’t reset. This lets
you examine the FLASH contents that you just loaded while the bootloader
is still active.
1 | ~$ bossac.exe --port=COM26 --usb-port=false -e -w -v --boot=0 nuttx.bin |
- Verify the FLASH contents (the bootloader must be running)
1 | ~$ bossac.exe --port=COM26 --usb-port=false -v nuttx.bin |
- Read from FLASH to a file (the bootloader must be running):
1 | ~$ bossac.exe --port=COM26 --usb-port=false --read=4096 nuttx.dump |
- Change to boot from FLASH
1 | ~$ bossac.exe --port=COM26 --usb-port=false --boot=1 |
恢复AT16u2
的固件
下面是把
Arduino Due
板上的AT16u2
恢复它原来的固件功能,这里是使用FT232H
连它的ICSP
而不是用一个Arduino
板来做烧写器.arduino
它所有支持的固件都在它的安装包内,因为Arduino Due
是SAM3X8E
的芯片,这里选择查看~/.arduino15/packages/arduino/hardware/sam/
目录.如下.
1 | ~$ tree ~/.arduino15/packages/arduino/hardware/sam/1.6.12/firmwares |
- 关于如何接线的问题,可以查看
/etc/avrdude.conf
,根据里面的注释指导,结合自已板子接线.
1 |
|
- 烧写命令如下,如有问题可以,添加
-vvv
烧写查看.
1 | ~$ avrdude -C /etc/avrdude.conf -c UM232H -P /dev/ttyUSB0 -b 19200 -p atmega16u2 -U flash:w:Arduino-DUE-usbserial-prod-firmware-2013-02-05.hex:i |
谢谢支持
- 微信二维码: