- 参考链接
开发板简介
- The STM32 Nucleo-144 F767ZI boards offer combinations of performance and power that provide an affordable and flexible
way for users to build prototypes and try out new concepts. For compatible boards, the SMPS significantly reduces power
consumption in Run mode. - The Arduino-compatible ST Zio connector expands functionality of the Nucleo open development platform, with a wide choice
of specialized Arduino* Uno V3 shields. - The STM32 Nucleo-144 board does not require any separate probe as it integrates the ST-LINK/V2-1 debugger/programmer.
- The STM32 Nucleo-144 board comes with the STM32 comprehensive free software libraries and examples available with the
STM32Cube MCU Package.
- Key Features
- STM32 microcontroller in LQFP144 package
- Ethernet compliant with IEEE-802.3-2002 (depending on STM32 support)
- USB OTG or full-speed device (depending on STM32 support)
- 3 user LEDs
- 2 user and reset push-buttons
- 32.768 kHz crystal oscillator
- Board connectors:
- USB with Micro-AB
- SWD
- Ethernet RJ45 (depending on STM32 support)
- ST Zio connector including Arduino* Uno V3
- ST morpho
- Flexible power-supply options: ST-LINK USB VBUS or external sources.
- On-board ST-LINK/V2-1 debugger/programmer with USB re-enumeration
- capability: mass storage, virtual COM port and debug port.
- Comprehensive free software libraries and examples available with the STM32Cube MCU package.
- 根据文档
The Cortex ® -M7 with FPU core is binary compatible with the Cortex ® -M4 core.
说明 ,Cortex-M7内核比M4性更
高,且二进制兼容.
Zephyr
系统简介
Zephyr
内核是一个内存占用极低的内核,它主要设计用于资源受限系统:从简单的嵌入式环境传感器、LED 可穿戴设备,到复杂的智能手表、IoT 无线网关.Zephyr
在被设计时就支持多架构,包括ARM Cortex-M
,Intel x86
,ARC
,NIOS II
和RISC V
.使用Zephyr
的一大优点是操作系统(OS)和软件开发工具包(SDK)可支持数百个开发板.
安装Zephyr环境
初始化工程
1 | ~$ pip3 install west |
- 更新后的目录结构如下:
1 | ~ zephyrproject$ tree -L 2 |
- 安装大量的Python依赖库
1
~ zephyrproject$ pip install -r ./zephyr/scripts/requirements.txt
安装工具链
- 最新的发行版下载最新版
1 | ~$ wget https://github.com/zephyrproject-rtos/sdk-ng/releases/download/v0.11.4/zephyr-sdk-0.11.4-setup.run |
- 解压安装完成后,会有一个
~/.zephyrrc
的环境变量文件.下面安装udev
文件.1
2~$ sudo cp ~/zephyr-sdk-0.11.4/sysroots/x86_64-pokysdk-linux/usr/share/openocd/contrib/60-openocd.rules /etc/udev/rules.d/
~$ sudo udevadm control --reload
板级示例程序
1 | ~$ west build -p auto -b nucleo_f767zi samples/hello_world |
- 连接到目标板子的USB,使用下面命令烧写入示例.
1 | ~$ west flash |
- 通过USB连接的
/dev/ttyACM0
会看到如下输出.
1 | ~$ sudo minicom -o -b 115200 -D /dev/ttyACM0 |
板级调试
1 | ~$ west debug |
- 如上面错误,是因为这里是使用
pyenv
安装的python-3.8.2
,不在系统内的搜索路径里,而且默认还是静态(static)编译的,所以会出显上面的错误.下面来重装它,并且使用LD_LIBRARY_PATH
指定路径.
1 | ~$ CONFIGURE_OPTS=--enable-shared pyenv install 3.8.2 |
- 再次运行调试.
1 | ~$ LD_LIBRARY_PATH=/home/michael/.pyenv/versions/3.8.2/lib west debug |
测试非标准板子(STM32F030 DEMO BOARD)
- STM32F030 DEMO BOARD
- 我手里的这块
stm32f030_demo
是没有STLINK-V2
调试器的,但是它有引出GND,VCC,DIO,CLK
这样一组接口,刚才好手上有一个JLink-OB
也是这样的接口,下面就用它来烧写与调试.
1 | ~$ west build -b stm32f030_demo samples/basic/blinky |
配置
openocd
连接参数.1
2
3
4
5~$ cat > jlink-ob-stm32f0.cfg<<EOF
source [find interface/jlink.cfg]
transport select swd
source [find target/stm32f0x.cfg]
EOF使用
openocd
烧写.1
2~$ cd build/zephyr
~$ openocd -f ~/jlink-ob-stm32f0.cfg -c init -c "reset halt" -c "stm32f0x mass_erase 0" -c "flash write_bank 0 zephyr.bin 0" -c "reset run"
Nuttx
系统简介
NuttX
是一个专注于标准合规和小内存占用的实时操作系统(RTOS)
.它可以在8位到32位的微控制器上部署.NuttX
在编写时主要参照了POSIX
和ANSI
标准.对于那些标准中没有的部分,如fork()
等,则参考了VxWorks
或其他RTOS
.NuttX
基本上完全是由C语言实现的,并且通过Kconfig
生成GNU makefile
.NuttX
的发行版包括了NuttX
内核本身和相当一部分的中间件和板级支持包.NuttX
的内核和绝大多数代码完全是由Gregory Nutt
完成的,并由他专门维护.所有的社区贡献都必须经过他批准.NuttX
最早是在2007年由Gregory Nutt
于BSD协议下释出的.
使用BuildRoot
构建工具链(非必要)
如果要使用
BuildRoot
定制编译的工具链就是如下配置: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~$ git clone https://bitbucket.org/nuttx/buildroot.git buildroot
~$ cp configs/cortexm7f-eabi-defconfig-7.4.0 .config
~$ make menuconfig
# 终配置如下
~$ grep -v '^$\|^#' .config
BR2_HAVE_DOT_CONFIG=y
BR2_arm=y
BR2_cortex_m7f=y
BR2_GCC_CORTEX=y
BR2_GCC_CORTEX_M7F=y
BR2_ARM_EABI=y
BR2_ARCH="arm"
BR2_GCC_TARGET_TUNE="cortex-m7"
BR2_GCC_TARGET_ARCH="armv7-m"
BR2_GCC_TARGET_ABI="aapcs-linux"
BR2_WGET="wget --passive-ftp"
BR2_SVN="svn co"
BR2_ZCAT="zcat"
BR2_BZCAT="bzcat"
BR2_TAR_OPTIONS=""
BR2_DL_DIR="$(BASE_DIR)/../archives"
BR2_STAGING_DIR="$(BUILD_DIR)/staging_dir"
BR2_NUTTX_DIR="$(TOPDIR)/../nuttx"
BR2_TOPDIR_PREFIX=""
BR2_TOPDIR_SUFFIX=""
BR2_GNU_BUILD_SUFFIX="pc-elf"
BR2_GNU_TARGET_SUFFIX="nuttx-eabi"
BR2_PACKAGE_BINUTILS=y
BR2_BINUTILS_VERSION_2_28_1=y
BR2_BINUTILS_SUPPORTS_NUTTX_OS=y
BR2_BINUTILS_VERSION="2.28.1"
BR2_EXTRA_BINUTILS_CONFIG_OPTIONS=""
BR2_PACKAGE_GCC=y
BR2_GCC_VERSION_7_4_0=y
BR2_GCC_SUPPORTS_SYSROOT=y
BR2_GCC_SUPPORTS_NUTTX_OS=y
BR2_GCC_SUPPORTS_DOWN_PREREQ=y
BR2_GCC_DOWNLOAD_PREREQUISITES=y
BR2_GCC_VERSION="7.4.0"
BR2_EXTRA_GCC_CONFIG_OPTIONS=""
BR2_INSTALL_LIBSTDCPP=y
BR2_PACKAGE_GDB_HOST=y
BR2_GDB_VERSION_8_0_1=y
BR2_PACKAGE_GDB_TUI=y
BR2_GDB_VERSION="8.0.1"
BR2_PACKAGE_NXFLAT=y
BR2_PACKAGE_GENROMFS=y
BR2_PACKAGE_KCONFIG_FRONTENDS=y
BR2_KCONFIG_VERSION_4_11_0_1=y
BR2_KCONFIG_FRONTENDS_VERSION="4.11.0.1"
BR2_LARGEFILE=y
BR2_SOFT_FLOAT=y
BR2_TARGET_OPTIMIZATION="-Os -pipe"编译成功后,会在
buildroot
生成一个目录,结构如下:1
2
3
4
5
6
7
8
9
10
11
12
13
14~$ tree -L 2 build_arm_hf/
build_arm_hf/
├── root
└── staging_dir
├── arm-elf -> arm-nuttx-eabi
├── arm-nuttx-eabi
├── bin
├── include
├── lib
├── libexec
├── share
└── usr
10 directories, 0 files
编译
- nuttx Wiki
- 把上面工具链的绝对路径加入Shell环境变量中使用,也可以使用第三方的工具链,如:
Zephyr
的arm-zephyr-eabi
,也可以使用如:gcc-arm-none-eabi-6-2017-q2-update
的工具链,在Debian
下可以安装系统自带的gcc-arm-none-eabi
包.在make menuconfig
时,选择CONFIG_ARMV7M_TOOLCHAIN_GNU_EABIL=y
.
1 | ~$ tools/configure.sh -L | grep "f767" |
因为
NULEO-F767ZI
是有一个以太网接口,这里选择使用nucleo-144:f767-netnsh
配置文件.1
2
3
4~$ tools/configure.sh nucleo-144:f767-netnsh
~$ make oldconfig
~$ make menuconfig
~$ make # 如果是使用第三方工具链,就如这样: make CROSSDEV=arm-none-eabi-这里最终测试的系统配置如下:
ESP8266通信
这里是使用板上的
USART6
通信,而USART3
默认是做为系统的CONSOLE
的接口,1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16CONFIG_STM32F7_USART6=y
CONFIG_USART6_SERIALDRIVER=y
CONFIG_DEV_CONSOLE=y
CONFIG_NSH_CONSOLE=y
CONFIG_SERIAL_CONSOLE=y
CONFIG_USART3_SERIAL_CONSOLE=y
CONFIG_NUCLEO_CONSOLE_VIRTUAL=y
CONFIG_NETUTILS_ESP8266_DEV_PATH="/dev/ttyS1"
# 安装CU命令,就是类似于putty,minicom这样的串口通信工具.
CONFIG_SYSTEM_CUTERM=y
CONFIG_SYSTEM_CUTERM_DEFAULT_DEVICE="/dev/ttyS0"
CONFIG_SYSTEM_CUTERM_DEFAULT_BAUD=115200
CONFIG_SYSTEM_CUTERM_STACKSIZE=2048
CONFIG_SYSTEM_CUTERM_PRIORITY=100同时需要在
boards/arm/stm32f7/nucleo-144/include/board.h
添加USART6
的接口定义.
1 | [...] |
连接
ESP8266
1
2
3
4
5
6
7STM32F767ZI-NUCLEO ESP01
D0 RX ---> TX
D1 TX ---> RX
GND ---> GND
3V3 ---> 3V3
3V3 ---> CH_PD # 拉高进入正常模式连接测试
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16nsh> cu -s 115200 -l /dev/ttyS1
AT
OK
AT+GMR
AT version:1.7.4.0(May 11 2020 19:13:04)
SDK version:3.0.4(9532ceb)
compile time:May 27 2020 10:12:17
Bin version(Wroom 02):1.7.4
OK
AT+SYSRAM?
+SYSRAM:51952
OK
外接SPI-SD读卡器
- 这里使用
SPI3:(PB3:CLK),(PB4:MISO),(PB5:MOSI)
来外接SD
读卡器,根据数据手册stm32f767zi.pdf,NSS(CS)
片选可以是软件定义也可以使它硬件(PA4:GPIO_SPI3_NSS_2)
定义的,因为这里的使用场景非常简单,就是用PA4
来做从机的CS
片选. nuttx
的系统内boards/arm/stm32f7/nucleo-144/src
没有mmcsd
相关的文件,这里可以有从其它板子的stm32_mmcsd.c
文件复制修改一下就可以使用.- 在
boards/arm/stm32f7/nucleo-144/src/nucle-144.h
定义CS
.
1 | [...] |
- 在
boards/arm/stm32f7/nucleo-144/src/stm32_mmcsd.c
内定义函数的实现.
1 | [....] |
修改文件
boards/arm/stm32f7/nucleo-144/src/stm32_spi.c
内的相关函数内容.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[...]
#ifdef CONFIG_STM32F7_SPI3
void stm32_spi3select(FAR struct spi_dev_s *dev, uint32_t devid, bool selected)
{
spiinfo("devid: %d CS: %s\n", (int)devid, selected ? "assert" : "de-assert");
#if defined(CONFIG_MMCSD_SPI)
stm32_gpiowrite(GPIO_SPI3_CARD_CS, !selected);
#endif
}
uint8_t stm32_spi3status(FAR struct spi_dev_s *dev, uint32_t devid)
{
uint8_t ret = 0;
#if defined(CONFIG_MMCSD_SPI)
if (devid == SPIDEV_MMCSD(0))
{
/* Note: SD_DET is pulled high when there\'s no SD card present. */
/* 因为读卡没CD脚(插卡检测),或者不用该功能,就必须返回卡已经插入的条件.
* 凭此条件去进行下一步,读卡写卡操作,很重要. */
ret |= SPI_STATUS_PRESENT;
}
#endif
return ret;
}在系统初始化的流程内加入
MMCSD_SPI
的初始流程.修改文件boards/arm/stm32f7/nucleo-144/src/stm32_appinitialize.c
.1
2
3
4
5
6
7
8
9
10
11
12[...]
#ifdef CONFIG_MMCSD_SPI
/* Initialize the MMC/SD SPI driver (SPI2 is used) */
ret = stm32_mmcsd_initialize(3, CONFIG_NSH_MMCSDMINOR);
if (ret < 0)
{
syslog(LOG_ERR, "Failed to initialize SD slot %d: %d\n",
CONFIG_NSH_MMCSDMINOR, ret);
}
#endif
[....]最后是修改
boards/arm/stm32f7/nucleo-144/src/Makefile
文件,加入如下内容.1
2
3
4
5[...]
ifeq ($(CONFIG_MMCSD_SPI),y)
CSRCS += stm32_mmcsd.c
endif
[...]
QSPI驱动(未测试成功)
- 不知为何,工程文件内没有定义
QSPI
的管脚.这里只是通过编译,还未成功读写它.1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22~$ grep "/* QSPI" boards/arm/stm32f7/nucleo-144/include/board.h -A 20
/* QSPI
*
* reference from UM1974 chapter 6.14
* stm32f7/hardware/stm32f76xx77xx_pinmap.h
*
* PB6 GPIO_QSPI_CS CN10-13
* PB2 GPIO_QSPI_SCK CN10-15
* PD11 GPIO_QSPI_IO0 CN10-23
* PD12 GPIO_QSPI_IO1 CN10-21
* PE2 GPIO_QSPI_IO2 CN10-25
* PD13 GPIO_QSPI_IO3 CN10-19
*
* */
#define GPIO_QSPI_CS GPIO_QUADSPI_BK1_NCS_1
#define GPIO_QSPI_SCK GPIO_QUADSPI_CLK_1
#define GPIO_QSPI_IO0 GPIO_QUADSPI_BK1_IO0_3
#define GPIO_QSPI_IO1 GPIO_QUADSPI_BK1_IO1_3
#define GPIO_QSPI_IO2 GPIO_QUADSPI_BK1_IO2_1
#define GPIO_QSPI_IO3 GPIO_QUADSPI_BK1_IO3_2
烧写与测试
编译成功后
nuttx
内会有nuttx,nuttx.bin,nuttx.hex
三个文件,通过openocd
烧写与调试目标板子.1
~$ sudo openocd -f board/stm32f7discovery.cfg -c init -c "reset halt" -c "flash write_image erase nuttx.bin 0x08000000"
连接网卡与USB接口,使用
minicom
连接串口,进入系统.有时引同会长时间无法初始化,尝试按一下板子上的B1 USER
按键.1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16~$ minicom -o -b 115200 -D /dev/ttyACM0
nsh> help
help usage: help [-v] [<cmd>]
. cat df hexdump mkdir mw set umount
[ cd echo ifconfig mkfatfs nslookup sleep unset
? cp exec ifdown mkfifo ps source usleep
addroute cmp exitifup mkrd pwd test wget
arp dirname false kill mh rm time xd
basename dd free ls mount rmdir true
break delroute help mb mv route uname
Builtin Apps:
ping6 renew ntpcstop sh
ntpcstart ping mm nsh
Iotjs
- Build for STM32F4 NuttX
- 这里是参照
STM32F4
来实践的.把iotjs
同步到与nuttx,apps
同一级目录.
1 | ~$ git clone https://github.com/Samsung/iotjs.git |
编译中出现下面的错误,是因为头文件里的一些条件宏定义的结果,也就是说在
nuttx
系统内没有选择CONFIG_SERIAL_TERMIOS=y
,所以才会导至error: field 'orig_termios' has incomplete type
.1
2
3
4
5
6
7
8
9
10
11
12
13
14In file included from /fullpath/iotjs/deps/libtuv/include/uv.h:77:0,
from /fullpath/iotjs/deps/libtuv/src/fs-poll.c:22:
/fullpath/iotjs/deps/libtuv/include/uv-unix.h:428:18: error: field 'orig_termios' has incomplete type
struct termios orig_termios; \
^
/fullpath/iotjs/deps/libtuv/include/uv.h:680:3: note: in expansion of macro 'UV_TTY_PRIVATE_FIELDS'
UV_TTY_PRIVATE_FIELDS
^
make[5]: *** [CMakeFiles/tuv.dir/build.make:63: CMakeFiles/tuv.dir/src/fs-poll.c.obj] Error 1
make[4]: *** [CMakeFiles/Makefile2:73: CMakeFiles/tuv.dir/all] Error 2
make[3]: *** [Makefile:130: all] Error 2
make[2]: *** [CMakeFiles/libtuv.dir/build.make:111: deps/libtuv/src/libtuv-stamp/libtuv-build] Error 2
make[1]: *** [CMakeFiles/Makefile2:184: CMakeFiles/libtuv.dir/all] Error 2
make: *** [Makefile:130: all] Error 2在
apps/system
内,创建一个iotjs
的目录,具的app
内容是来自于STM32F4
下面的.1
2~$ mkdir apps/system/iotjs
~$ cp iotjs/config/nuttx/stm32f4dis/app/* apps/system/iotjs必须要在
app/system/Kconfig
加上一条source "/<fullpath>/apps/system/iotjs/Kconfig"
记录.
使用串口与ESP8266通信
- 在使用
ESP8266
时,要注意配置几个必须项,这里使用板上的UART4
来通信.1
2
3-> System Type -> STM32 Peripheral Support -> [*] UART4
-> Application Configuration -> Network Utilities -> [*] ESP8266
-> Application Configuration -> System Libraries and NSH Add-Ons -> [*] CU minimal serial terminal UART4
定义缺失的错误1
2
3
4
5
6
7
8
9CC: chip/stm32_serial.c
chip/stm32_serial.c:1037:20: error: 'GPIO_UART4_TX' undeclared here (not in a function)
.tx_gpio = GPIO_UART4_TX,
^
chip/stm32_serial.c:1038:20: error: 'GPIO_UART4_RX' undeclared here (not in a function)
.rx_gpio = GPIO_UART4_RX,
^
make[1]: *** [Makefile:154: stm32_serial.o] Error 1
STM32F103最小系统
- 这里使用的最小板系统,标准
JTAG
与大部分管脚能引出来,清晰明了,这里重点参照nuttx
板子内的README.md
.但是这里在使用USB
开启CDC/ACM
串口时没成功.
1 | ~$ tools/configure.sh stm32f103-minimum:usbnsh |
看了这个系统内的文档说明,
STM32F103C8T6
的内部flash
是128KB
而不是它数据文档所说的64KB
,所下这里修改ld
文件如下:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20~$ cat boards/arm/stm32/stm32f103-minimum/scripts/ld.script
[....]
/* The STM32F103C8T6 has 64Kb of FLASH beginning at address 0x0800:0000 and
* 20Kb of SRAM beginning at address 0x2000:0000. When booting from FLASH,
* FLASH memory is aliased to address 0x0000:0000 where the code expects to
* begin execution by jumping to the entry point in the 0x0800:0000 address
* range.
*
* NOTE: While the STM32F103C8T6 states that the part has 64Kb of FLASH,
* all parts that I have seen do, in fact, have 128Kb of FLASH. That
* additional 64Kb of FLASH can be utilized by simply change the LENGTH
* of the flash region from 64K to 128K.
*/
MEMORY
{
flash (rx) : ORIGIN = 0x08000000, LENGTH = 128K
sram (rwx) : ORIGIN = 0x20000000, LENGTH = 20K
}
[...]配置
openocd
通过Jlink-OB
来烧写调试.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~$ cat ~/jlink-ob-stm32f1-swd.cfg
source [find interface/jlink.cfg]
transport select swd
source [find target/stm32f1x.cfg]
# 烧写
~$ openocd -f ~/jlink-ob-stm32f1-swd.cfg -c init -c "reset halt" -c "flash write_image erase nuttx.bin 0x08000000" -c "reset run"
Open On-Chip Debugger 0.10.0+dev-01423-g3ffa14b04-dirty (2020-10-14-08:59)
Licensed under GNU GPL v2
For bug reports, read
http://openocd.org/doc/doxygen/bugs.html
Info : J-Link ARM-OB STM32 compiled Aug 22 2012 19:52:04
Info : Hardware version: 7.00
Info : VTarget = 3.300 V
Info : clock speed 1000 kHz
Info : SWD DPIDR 0x1ba01477
Info : stm32f1x.cpu: hardware has 6 breakpoints, 4 watchpoints
Info : starting gdb server for stm32f1x.cpu on 3333
Info : Listening on port 3333 for gdb connections
target halted due to debug-request, current mode: Thread
xPSR: 0x01000000 pc: 0x08000130 msp: 0x20000f54
Info : device id = 0x20036410
Info : flash size = 128kbytes
auto erase enabled
wrote 78848 bytes from file nuttx.bin in 7.988087s (9.639 KiB/s)配置
openocd
通过其它带有ST-Link
调试板子来烧写调试,一般的官方评估板都会带有调试器如,NUCLEO
的系列,这里是使用NUCLEO-L152RE
板上的ST-LINK
来烧写调试.首先,把NUCLEO-L152RE
板上CN2
跳线取掉,根据官方文档(SWD)CN4
的端线序是1:VDD,2:SWCLK,3:GND,4:SWDIO,5:NRST,6:SWO
,这里只需要三根连接既可,
1 | SWD STM32F103C8T6 |
- 因为
STM32F103C8T6
的内存只有20K
,所以很容易就爆了,最经典的错误就是无法运行内置app
,如下所示:
1 | NuttShell (NSH) NuttX-9.1.0 |
- 原来是因为,内存不够,无法把程序从
FLASH
复制到内存中运行,所以会出现上面错误,如果打开编译调试错误出,会从nsh shell
得到更进一步的错误信息详情,参考. - 我这里处理的方法就是把
各种线程栈(STACKSIZE)的体积
缩小到最大只能是1024
,如上所示,内存只有1800
,但是编译时设置的spi tool
的STACKSIZE
是2048
.
连接ESP8266
- 这里是使用
USART3
,并且是设置:ESP8266的串口路径是1
-> System Type -> U[S]ART Configuration -> Serial Driver Configuration -> [*] Disable reordering of ttySx devices.
/dev/ttyS1
. 连接图如下.
1 | STM32 ESP8266 |
1 | nsh> ? |
读写SD卡(over SPI)
这里只能使用
SPI1
做为SD
接口,因为在boards/arm/stm32/stm32f103-minimum/src/stm32_mmcsd.c
内在已经硬编码如下:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19/*****************************************************************************
* Pre-processor Definitions
****************************************************************************/
#ifndef CONFIG_STM32_SPI1
# error "SD driver requires CONFIG_STM32_SPI1 to be enabled"
#endif
#ifdef CONFIG_DISABLE_MOUNTPOINT
# error "SD driver requires CONFIG_DISABLE_MOUNTPOINT to be disabled"
#endif
/*****************************************************************************
* Private Definitions
****************************************************************************/
static const int SD_SPI_PORT = 1; /* SD is connected to SPI1 port */
static const int SD_SLOT_NO = 0; /* There is only one SD slot */基本的必须配置项如下
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25CONFIG_STM32_SPI=y
CONFIG_STM32_SPI1=y
CONFIG_SPI=y
CONFIG_SPI_EXCHANGE=y
CONFIG_SPI_DRIVER=y
CONFIG_MMCSD_SPI=y
CONFIG_MMCSD_SPICLOCK=20000000
CONFIG_MMCSD_SPIMODE=0
CONFIG_MMCSD=y
CONFIG_MMCSD_NSLOTS=1
CONFIG_MMCSD_SPI=y
CONFIG_MMCSD_SPICLOCK=20000000
CONFIG_MMCSD_SPIMODE=0
CONFIG_MMCSD_IDMODE_CLOCK=400000
CONFIG_NSH_MMCSDMINOR=0
CONFIG_NSH_MMCSDSLOTNO=0
CONFIG_NSH_MMCSDSPIPORTNO=1
CONFIG_FS_FAT=y
CONFIG_FAT_LCNAMES=y
CONFIG_FAT_LFN=y
CONFIG_FAT_MAXFNAME=32
CONFIG_FAT_LFN_ALIAS_TRAILCHARS=0
CONFIG_FSUTILS_MKFATFS=y
读写W25Q32FV
通过查看代码发现,
W25Q32FV
也是使用SPI1
默认也是硬编码写,这里是默认使用SPI1
是的常规必须选项.1
2
3
4
5
6
7
8
9
10
11
12
13
14
15CONFIG_STM32_SPI1=y
CONFIG_STM32_SPI=y
CONFIG_MTD_W25=y
CONFIG_W25_SPIMODE=0
CONFIG_W25_SPIFREQUENCY=20000000
CONFIG_MTD=y
CONFIG_MTD_PARTITION=y
CONFIG_MTD_BYTE_WRITE=y
CONFIG_MTD_SMART=y
CONFIG_MTD_SMART_SECTOR_SIZE=1024
CONFIG_MTD_SMART_WEAR_LEVEL=y
CONFIG_MTD_W25=y
CONFIG_FSUTILS_MKSMARTFS=y按照上面的配置,连接
W25QF32V
的线路如下:1
2
3
4
5
6
7
8W25QF32V STM32F103
CS ----> PA4/NSS
DO ----> PA6/MISO
DI ----> PA7/MOSI
CLK ----> PA5/SCK
GND ----> GND
VCC ----> 3V3格化格,挂载,读写测试.
1
2
3
4
5
6
7
8
9
10
11nsh> mkdir /tmp
nsh> ls /
/:
dev/
mnt/
proc/
nsh> mksmartfs /dev/smart0p1
nsh> mount -t smartfs /dev/smart0p1 /tmp
nsh> echo "11223456" > /tmp/file1.txt
nsh> cat /tmp/file1.txt
11223456STM32F103C8T6
上大部分的接口都描述了Pin
的功能,少部分如:PB12,PB13...
,这些需要查询stm32f103c8.pdf内的,Chapter 3, Table 5
内容.
扩展使用SPI2
STM32F103C8T6
最小板,引出了两个SPI
:SPI1: PA4(NSS), PA5(SCK), PA6(MISO), PA7(MOSI)
SPI2: PB12(NSS), PB13(SCK), PB14(MISO), PB15(MOSI)
但是在
Nuttx
的里只开启了SPI1
,同时只能接一个外设.所以,我要参照文件来修改它,目标是把SPI1
连接到SD over SPI
,SPI2
连接到W25QF32V
.根据
FLASH_SPI1_CS
添加FLASH_SPI2_CS
宏定义,指定PB12
,最终文件如下:1
2
3
4
5
6
7~$ cat boards/arm/stm32/stm32f103-minimum/src/stm32f103_minimum.h
[...]
/* SPI chip selects */
#define FLASH_SPI2_CS (GPIO_OUTPUT|GPIO_CNF_OUTPP|GPIO_MODE_50MHz|\
GPIO_OUTPUT_SET|GPIO_PORTB|GPIO_PIN12)
[...]修改
stm32_spi.c
,这个文件修改比较多,做成patch
文件如: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~$ git diff boards/arm/stm32/stm32f103-minimum/src/stm32_spi.c > spi2.patch
diff --git a/boards/arm/stm32/stm32f103-minimum/src/stm32_spi.c b/boards/arm/stm32/stm32f103-minimum/src/stm32_spi.c
index 6f3a585902..01b5b861e8 100644
--- a/boards/arm/stm32/stm32f103-minimum/src/stm32_spi.c
+++ b/boards/arm/stm32/stm32f103-minimum/src/stm32_spi.c
@@ -75,7 +75,7 @@ void stm32_spidev_initialize(void)
*/
#ifdef CONFIG_MTD_W25
- stm32_configgpio(FLASH_SPI1_CS); /* FLASH chip select */
+ stm32_configgpio(FLASH_SPI2_CS); /* FLASH chip select */
#endif
#ifdef CONFIG_CAN_MCP2515
@@ -197,7 +197,7 @@ void stm32_spi1select(FAR struct spi_dev_s *dev, uint32_t devid,
#endif
#ifdef CONFIG_MTD_W25
- stm32_gpiowrite(FLASH_SPI1_CS, !selected);
+ //stm32_gpiowrite(FLASH_SPI1_CS, !selected);
#endif
}
@@ -227,6 +227,9 @@ uint8_t stm32_spi1status(FAR struct spi_dev_s *dev, uint32_t devid)
void stm32_spi2select(FAR struct spi_dev_s *dev, uint32_t devid,
bool selected)
{
+#ifdef CONFIG_MTD_W25
+ stm32_gpiowrite(FLASH_SPI2_CS, !selected);
+#endif
}
uint8_t stm32_spi2status(FAR struct spi_dev_s *dev, uint32_t devid)
@@ -294,6 +297,16 @@ int stm32_spi1cmddata(FAR struct spi_dev_s *dev, uint32_t devid,
return -ENODEV;
}
#endif
+
+#ifdef CONFIG_STM32_SPI2
+int stm32_spi2cmddata(FAR struct spi_dev_s *dev, uint32_t devid,
+ bool cmd)
+{
+ return -ENODEV;
+}
+#endif
+
+
#endif
#endif /* CONFIG_STM32_SPI1 || CONFIG_STM32_SPI2 */修改
stm32_w25.c
如下: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
30git diff boards/arm/stm32/stm32f103-minimum/src/stm32_w25.c
diff --git a/boards/arm/stm32/stm32f103-minimum/src/stm32_w25.c b/boards/arm/stm32/stm32f103-minimum/src/stm32_w25.c
index 6e9d12718d..63ba5153ce 100644
--- a/boards/arm/stm32/stm32f103-minimum/src/stm32_w25.c
+++ b/boards/arm/stm32/stm32f103-minimum/src/stm32_w25.c
@@ -47,7 +47,7 @@
#include <errno.h>
#include <debug.h>
-#ifdef CONFIG_STM32_SPI1
+#ifdef CONFIG_STM32_SPI2
# include <nuttx/spi/spi.h>
# include <nuttx/mtd/mtd.h>
# include <nuttx/fs/smart.h>
@@ -67,13 +67,13 @@
* timer
*/
-#define W25_SPI_PORT 1
+#define W25_SPI_PORT 2
/* Configuration ************************************************************/
/* Can't support the W25 device if it SPI1 or W25 support is not enabled */
#define HAVE_W25 1
-#if !defined(CONFIG_STM32_SPI1) || !defined(CONFIG_MTD_W25)
+#if !defined(CONFIG_STM32_SPI2) || !defined(CONFIG_MTD_W25)
# undef HAVE_W25
#endif修改
stm32_bringup.c
如下.1
2
3
4
5
6
7
8
9
10
11
12
13
14~$ git diff boards/arm/stm32/stm32f103-minimum/src/stm32_bringup.c
diff --git a/boards/arm/stm32/stm32f103-minimum/src/stm32_bringup.c b/boards/arm/stm32/stm32f103-minimum/src/stm32_bringup.c
index efa651034e..b4b0379bde 100644
--- a/boards/arm/stm32/stm32f103-minimum/src/stm32_bringup.c
+++ b/boards/arm/stm32/stm32f103-minimum/src/stm32_bringup.c
@@ -143,7 +143,7 @@
/* Can't support the W25 device if it SPI1 or W25 support is not enabled */
-#if !defined(CONFIG_STM32_SPI1) || !defined(CONFIG_MTD_W25)
+#if !defined(CONFIG_STM32_SPI2) || !defined(CONFIG_MTD_W25)
# undef HAVE_W25
#endif
开启串口调试
- 如果没有在配置系统里打开相应的
DEBUG
选项,系统只出错时,只会给出一个简单错误号.下面是打开针对SPI,FS,MMC/SD
的出错提示.1
2
3
4
5
6
7
8
9
10
11
12
13
14
15CONFIG_DEBUG_ALERT=y
CONFIG_DEBUG_FEATURES=y
CONFIG_DEBUG_ERROR=y
CONFIG_DEBUG_FS=y
CONFIG_DEBUG_FS_ERROR=y
CONFIG_DEBUG_IRQ=y
CONFIG_DEBUG_IRQ_ERROR=y
CONFIG_DEBUG_MEMCARD=y
CONFIG_DEBUG_MEMCARD_ERROR=y
CONFIG_DEBUG_SPI=y
CONFIG_DEBUG_SPI_ERROR=y
CONFIG_DEBUG_FULLOPT=y
CONFIG_ARCH_HAVE_HARDFAULT_DEBUG=y
CONFIG_ARCH_HAVE_MEMFAULT_DEBUG=y
CONFIG_STM32_DISABLE_IDLE_SLEEP_DURING_DEBUG=y
1 | nsh> mount -t vfat /dev/mmcsd1 /mnt/sd1 |
如果碰到类似的错误号,可以打开
nuttx/include/errno.h
,会看到如下所示:1
2#define ENODEV 19
#define ENODEV_STR "No such device"最终同时开启
SPI1,SPI2
的接口,包含了SPI,FS,MMC/SD,MTD
一些必须选项,配置如下: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
CONFIG_STM32_SPI1=y
CONFIG_STM32_SPI2=y
CONFIG_STM32_SPI=y
CONFIG_ARCH_HAVE_SPI_BITORDER=y
CONFIG_SPI=y
CONFIG_SPI_EXCHANGE=y
CONFIG_SPI_CMDDATA=y
CONFIG_SPI_DRIVER=y
CONFIG_MMCSD=y
CONFIG_MMCSD_NSLOTS=1
CONFIG_MMCSD_SPI=y
CONFIG_MMCSD_SPICLOCK=20000000
CONFIG_MMCSD_SPIMODE=0
CONFIG_MMCSD_IDMODE_CLOCK=400000
CONFIG_MTD=y
CONFIG_MTD_PARTITION=y
CONFIG_MTD_BYTE_WRITE=y
CONFIG_MTD_SMART=y
CONFIG_MTD_SMART_SECTOR_SIZE=1024
CONFIG_MTD_SMART_WEAR_LEVEL=y
CONFIG_MTD_W25=y
CONFIG_W25_SPIMODE=0
CONFIG_W25_SPIFREQUENCY=20000000
CONFIG_FS_NEPOLL_DESCRIPTORS=8
CONFIG_FS_MQUEUE_MPATH="/var/mqueue"
CONFIG_FS_FAT=y
CONFIG_FS_SMARTFS=y
CONFIG_SMARTFS_ERASEDSTATE=0xff
CONFIG_SMARTFS_MAXNAMLEN=16
CONFIG_FS_PROCFS=y
CONFIG_FS_PROCFS_REGISTER=y
CONFIG_FS_PROCFS_EXCLUDE_ENVIRON=y
CONFIG_FSUTILS_MKFATFS=y
CONFIG_FSUTILS_MKSMARTFS=y
CONFIG_NSH_MMCSDMINOR=0
CONFIG_NSH_MMCSDSLOTNO=0
CONFIG_NSH_MMCSDSPIPORTNO=1
CONFIG_NSH_CODECS_BUFSIZE=128测试系统如下.
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
43NuttShell (NSH) NuttX-9.1.0
nsh> ls /dev
/dev:
console
mmcsd0
null
smart0p0
smart0p1
smart0p2
smart0p3
ttyS0
nsh> free
total used free largest
Umem: 17536 12872 4664 4664
nsh> mkdir /mnt /p0
nsh: mkdir: too many arguments
nsh> mkdir /mnt
nsh> mkdir /p0
nsh> mount -t vfat /dev/mmcsd0 /mnt
nsh> mount -t smartfs /dev/smart0p0 /p0
nsh> df
Block Number
Size Blocks Used Available Mounted on
16384 15611 3 15608 /mnt
1024 64 11 53 /p0
0 0 0 0 /proc
nsh> free
total used free largest
Umem: 17536 14888 2648 2584
nsh> ls /p0
/p0:
file.txt
nsh> cat /p0/file.txt
test
nsh> free
total used free largest
Umem: 17536 14888 2648 2584
nsh> ls /mnt
/mnt:
file1.txt
nsh> cat /mnt/file1.txt
1112222ssss
NUCLEO-L152RE (MB1136 c-03)
- ST-Nucleo-L152RE
- TFTLCD原理与驱动与指令介绍
- Description
- how-to-teach-endian
- FSMC-TFT LCD调试记录
- 野火LCD—液晶显示
- LCD有如下控制线:
- CS:
Chip Select
片选,低电平有效 - RS:
Register Select
寄存器选择 - WR:
Write
写信号,低电平有效 - RD:
Read
读信号,低电平有效 - RESET:重启信号,低电平有效
- DB0-DB15:数据线
- CS:
- RS为1(表示DB0-15上传递的是要被写到寄存器的值),如果为0,表示传递的是数据.
- 写(WR=0,RD=1),读(WR=1,RD=0)
- RESET一直为高,如果RESET为低,会导致芯片重启
1
~$ openocd -f board/stm32ldiscovery.cfg -c init -c "reset halt" -c "flash write_image erase nuttx.bin 0x08000000" -c "reset run"
- 操作IO口,参考STM32F10xxx参考手册,第8章,
8.2.5 GPIOx_BSRR
的寄存器内容.
提交代码给NuttX
- Github中文文档
- Making Changes Using Git
NuttX
代码是在Github上,所以要为它提交代码,需要先有Github
帐号.- 在自己的
Github
里fork
NuttX.再在本地克隆刚才fork
的NuttX
. - 并且把原
https://github.com/apache/incubator-nuttx.git
设置成上游(upstream).
1 | ~$ git clone <your forked incubator-nuttx project clone url> |
- 创建一个本地的开发分支,并且把它
pull
自己fork
项目中去.1
2
3
4
5
6
7
8~$ git checkout -b dev/stm32l152re-ili93418b-driver
Switched to a new branch 'dev/stm32l152re-ili93418b-driver'
~$ git push
fatal: The current branch dev/stm32l152re-ili93418b-driver has no upstream branch.
To push the current branch and set the remote as upstream, use
git push --set-upstream origin dev/stm32l152re-ili93418b-driver - 按照提示,需要关联到远程分支,把本地分支
dev/stm32l152re-ili93418b-driver
推送到origin
远程分支上.1
2
3
4
5
6
7
8
9
10
11~$ git push --set-upstream origin dev/stm32l152re-ili93418b-driver
Username for 'https://github.com': xxxxxx
Password for 'https://xxxxxxx@github.com':
Total 0 (delta 0), reused 0 (delta 0)
remote:
remote: Create a pull request for 'dev/stm32l152re-ili93418b-driver' on GitHub by visiting:
remote: https://github.com/xxxxxx/incubator-nuttx/pull/new/dev/stm32l152re-ili93418b-driver
remote:
To https://github.com/xxxxx/incubator-nuttx
* [new branch] dev/stm32l152re-ili93418b-driver -> dev/stm32l152re-ili93418b-driver
Branch 'dev/stm32l152re-ili93418b-driver' set up to track remote branch 'dev/stm32l152re-ili93418b-driver' from 'origin'. - 关联到远程分支后,以后就可以直接
push
,查看.git/config
如下1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18~$ cat .git/config
[core]
repositoryformatversion = 0
filemode = true
bare = false
logallrefupdates = true
[remote "origin"]
url = https://github.com/xxxxx/incubator-nuttx
fetch = +refs/heads/*:refs/remotes/origin/*
[branch "master"]
remote = origin
merge = refs/heads/master
[remote "upstream"]
url = https://github.com/apache/incubator-nuttx.git
fetch = +refs/heads/*:refs/remotes/upstream/*
[branch "dev/stm32l152re-ili93418b-driver"]
remote = origin
merge = refs/heads/dev/stm32l152re-ili93418b-driver - 读取上游的更新并且合并到本地的
master
分支.再push
到自己的origin
的创库.1
2
3
4~$ git checkout master # 本地切换到master分支
~$ git fetch upstream # 读取上游更改,同步.
~$ git merge upstream/master # 合并上游到本地
~$ git push # push同步,把本的master同步远端的origin/master - 创建新的更改或文件并且
push
到远程分支1
2
3~$ git add new-file.c
~$ git commit new-file.c
~$ git push - 此时
github
的分支上面,会有一个提示,Create Pull Request
,把当前的分支推送到upstream
上去,提交合并请求. - 如果运行
rebase upstream/master
后,发现代码有问题,可以使用git reset --hard HEAD~1
回退到指定的节点,~[num]
回退第几个结点.这里可以使用gitg
图形工具可以直观的显示.假如这里是回退到创建分支时第一次commit
之前, 在些可以重新修改或添加文件,再重新commit
, 并且要使用git push --force
才行.之后再可以git fetch upstream; git rebase upstream/master
.
合并多个commit
为一个完整commit
- 为了保持提交记录的更简洁明了,需要把多个
commit
合并到一个完整的commit
,然后再push
到上游库中.命令的方式是:git rebase -i [startpoint] [endpoint]
.如果不指定endpoint
,则该区间的终点默认是当前分支HEAD
所指向的commit
.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~$ git rebase -i HEAD~3
pick a68185edc0f2cbd38c8fdbcffaf516278f4f Fix merge conflicts
pick efe10a20278f53af9e6fff5754de39b8c8c4 net/icmp: add sanity check to avoid wild data length
pick fb7480c67637bfa2164f4f76ceff6f509d24 net/neighbor/neighbor_ethernet_out.c: fix build error without ICMPv6
pick 0a262336bd9964b693b57fe93d992482d5d3 arch/arm/src/stm32/stm32_otghsdev.c: Fix syslog formats
[....]
# Rebase dd4b5e0c68..18d489a8dd onto dd4b5e0c68 (32 commands)
#
# Commands:
# p, pick <commit> = use commit /* 保留该commit */
# r, reword <commit> = use commit, but edit the commit message /* 保留该commit,但我需要修改该commit的注释 */
# e, edit <commit> = use commit, but stop for amending /* 保留该commit, 但我要停下来修改该提交(不仅仅修改注释) */
# s, squash <commit> = use commit, but meld into previous commit /* 将该commit和前一个commit合并 */
# f, fixup <commit> = like "squash", but discard this commit's log message /* 如sqaush,但是不保留该提交的注释信息 */
# x, exec <command> = run command (the rest of the line) using shell /* 执行shell命令 */
# b, break = stop here (continue rebase later with 'git rebase --continue')
# d, drop <commit> = remove commit /* 丢弃该commit */
# l, label <label> = label current HEAD with a name
# t, reset <label> = reset HEAD to a label
# m, merge [-C <commit> | -c <commit>] <label> [# <oneline>]
# . create a merge commit using the original merge commit's
# . message (or the oneline, if no original merge commit was
# . specified). Use -c <commit> to reword the commit message.
#
# These lines can be re-ordered; they are executed from top to bottom.
#
# If you remove a line here THAT COMMIT WILL BE LOST.
#
# However, if you remove everything, the rebase will be aborted.
#
# Note that empty commits are commented out - 如上面的说明一样,支持多种编辑,现在假如改成如下所示.修改完成后保存,就会转到注释的修改界面,再保存.它就执行了
rebase
,再用git push -f
把相应的修改强制提交上去.1
2
3
4pick c029a68185edc0f2cbd38c8fdbcffaf516278f4f Fix merge conflicts
s efe10a20278f53af9e6fff5754de39b8c8c4 net/icmp: add sanity check to avoid wild data length
s fb7480c67637bfa2164f4f76ceff6f509d24 net/neighbor/neighbor_ethernet_out.c: fix build error without ICMPv6
f 0a262336bd9964b693b57fe93d992482d5d3 arch/arm/src/stm32/stm32_otghsdev.c: Fix syslog formats - 它其实是在
.git
下面的文件.1
2
3
4
5
6~$ head .git/rebase-merge/git-rebase-todo.backup
pick a68185edc0f2cbd38c8fdbcffaf516278f4f Fix merge conflicts
pick efe10a20278f53af9e6fff5754de39b8c8c4 net/icmp: add sanity check to avoid wild data length
pick fb7480c67637bfa2164f4f76ceff6f509d24 net/neighbor/neighbor_ethernet_out.c: fix build error without ICMPv6
pick 0a262336bd9964b693b57fe93d992482d5d3 arch/arm/src/stm32/stm32_otghsdev.c: Fix syslog formats
[....] - 分支合并到主线时,可以删除该分支.
1
2~$ git branch -d <本地分支>
~$ git push origin --delete <远端分支> - 如果因为
rebase
时所产生的CONFLICT (content): Merge conflict in src/xxxx.cpp
,并且确定冲突可以以一方为标准处理,可以使用下面命令自动处理.--theirs
就是使用pull
上游仓库版本,--ours
是使用本地版本,再把它commit
就算是合并成功了.1
2~$ git checkout --theirs src/xxxx.cpp
~$ git commit
Git其它应用
- 使用
git
把指定的一个commit
导出成patch
.how can i generate a git patch for a specific commit
1 | ~$ git format-patch -1 HEAD |
- 在自动处理合并分支的冲突时,如果只有一边是修改的情况下,参考这里可以使用如下:
1 | ~$ git merge --strategy-option theirs |
git
提交时自动修改(自增)版本号的文件
1 | ~$ cat .git/hooks/pre-commit |
git
使用图形工具(meld)对比代码
在
.git/config
添加下面内容1
2
3
4
5
6
7# Add the following to your .gitconfig file.
[diff]
tool = meld
[difftool]
prompt = false
[difftool "meld"]
cmd = meld "$LOCAL" "$REMOTE"对比不同分支上的同一个文件
1
~$ git difftool mybranch master -- target.file
对比当前分支与
other-branch
的src
目录下的文件,--
后的参数可以省掉,也可以具体指某一个文件或者目录名.1
~$ git difftool other-branch -- src
当前分支的文件与其它的
commit
对比.1
~$ git difftool HEAD~2 -- src/file.txt
合并
other-branch
到当前分支,并使用other-branch
来解决冲突(theirs).1
~$ git merge -X theirs other-branch
回退一个合并
1
git reset --merge HEAD~1
强制
fetch
远程仓库,覆盖本地仓库,替代pull
时冲突提示(慎用)1
2
3
4# fetch from the default remote, origin
~$ git fetch
# reset your current branch (master) to origin's master
~$ git reset --hard origin/master
STM32F4-Discovery(MB997C)
Audio(CS43L22)支持
SPI SD卡支持
USB-OTG
BLE Sniffer
- [Faking Bluetooth LE](Inspired by http://dmitry.gr/index.php?r=05.Projects&proj=11.%20Bluetooth%20LE%20fakery)
- Bluetooth_Sniffing_with_Ubertooth:_A_Step-by-step_guide
- how-to-install-nrf-sniffer-through-nrf52-dk-board
- btlejack-bluetooth-low-energy-swiss-army-knife
- nrf24l01-arduino-wireless-temperature-monitor-dht11
- arduino-wireless-temperature-lcd-display-nrf24l01-dht11
Ethernet 8720A
Arm Mbed-OS
配置开发环境
- 这里使用的是当前最新的
v6.3
版本.Mbed
支持三种不同类型的开发环境(桌面IDE,在线IDE,命令行),且支持多系统平台(Win,Mac,Linux),这是使用Keil,IAR
所不能比拟的.这里会根据官方文档说明,实践一下桌面与命令行的开发.而且它使用的是C++
语言开发,这样有别于传统的Keil,IAR
的C语开发,它的代码风格与Arduino
一样.并且它内置的实时操作系统就是FreeRTOS
.
Mbed Studio
使用
Mbed Studio
需要注册一个帐号,安装完成第一次打开IDE
,会需要先登录.它与Web Stduio
还有同一个优点,可以从线上导入官方的模版工程.1
2
3
4
5
6~$ wget -c https://studio.mbed.com/installers/latest/linux/MbedStudio.sh
~$ ./MbedStudio.sh
~$ du -sh ~/.local/bin/mbed-studio
~$ ls ~/.config/Mbed Studio
api-targets.json Cache Cookies GPUCache library-pipeline mbed-studio.log 'Network Persistent State'
blob_storage config.json Cookies-journal library-cache 'Local Storage' mbed-studio-tools recentworkspace.jsonMbed Studio
原本是使用Arm Compiler 6
,这里可以也可以切换到Arm Embedded GCC Compiler
1 | ~$ cat > ~/.config/Mbed Studio/external-tools.json <<EOF |
- 如上面所示,
Mbed Studio
也是如同VScode
这样的IDE,也是使用json
格式配置文件,
打开界面菜单:File -> Settings -> Open Perferences
.
测试FRDM-KL25Z
更新OpenSDA
的固件
Mbed Studio
需要最新的固件来支持调试FRDM-KL25Z
,至少需要mbed_if_v2.0_frdm_kl25z.s19
才能支持CMSIS-DAP
,所以需按照上述链接下载到固件(Pemicro_OpenSDA_Debug_MSD_Update_Apps_2020_05_12.zip).解压后,文件夹有*.SDA
后缀的固件文件,还有一些Notes
与指导手册等.电脑连到KL25Z
的SDA
接口时,会在系统内看到一个FRDM-KL25Z
的盘符.- 这里还有一个问题,升级固件时,必须让板子进入
Bootloder
模式,此时它会挂载盘符叫BOOTLODER
.发现只能Windows
的系统下进行升级,按住板子上的RST
键,接入SDA
上电,因为板子内的固件是v1.01
,在Linux
下无法挂载出一个USB
盘符, 而只能在windows XP,Win 7
下是可以挂载的且可以升级成功.这里原因没有深究它了. - 解压固件后的目录内还有一个
OpenSDA_Bootloader_Update_App_v111_2013_12_11.zip
,再解压出就是BOOTUPDATEAPP_Pemicro_v111.SDA
要升级的固件文件,这里把MSD-DEBUG-FRDM-KL25Z_Pemicro_v118.SDA,BOOTUPDATEAPP_Pemicro_v111.SDA,20140530_k20dx128_kl25z_if_opensda.s19
三个文件直接复制进BOOTLOADER
盘符内,就可以升级了.升级完成后,接入SDA
后在Linux
下会自动挂载一个MBED
盘. - 再次按住板子上的
RST
键,接入SDA
上电,进入BOOTLOADER
模式,打开BOOTLOADER
盘内的SDA_INFO.HTM
跳转到网页,查看网页的信息是否与升级的固件版本对应上.并且固件在v1.11
进,也就可以自动在Linux
下挂载BOOTLOADER
盘了,可以方便的进行后续版本的升级了. - 新建工程,导入官方示例
mbed-os-example-blinky
,界面如下: - 更新后,可以使用
openocd
连接调试.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~$ openocd -c "adapter driver cmsis-dap" -f board/frdm-kl25z.cfg
Open On-Chip Debugger 0.10.0+dev-01423-g3ffa14b04-dirty (2020-10-14-08:59)
Licensed under GNU GPL v2
For bug reports, read
http://openocd.org/doc/doxygen/bugs.html
Warn : Interface already configured, ignoring
Info : auto-selecting first available session transport "swd". To override use 'transport select <transport>'.
Info : add flash_bank kinetis kl25.pflash
Info : Listening on port 6666 for tcl connections
Info : Listening on port 4444 for telnet connections
Info : CMSIS-DAP: SWD Supported
Info : CMSIS-DAP: FW Version = 1.0
Info : CMSIS-DAP: Interface Initialised (SWD)
Info : SWCLK/TCK = 0 SWDIO/TMS = 1 TDI = 0 TDO = 0 nTRST = 0 nRESET = 1
Info : CMSIS-DAP: Interface ready
Info : clock speed 1000 kHz
Info : SWD DPIDR 0x0bc11477
Info : SWD DPIDR 0x0bc11477
Error: Failed to write memory at 0xe000edf0
Info : kl25.cpu: external reset detected
Warn : **** Your Kinetis MCU is probably locked-up in RESET/WDOG loop. ****
Warn : **** Common reason is a blank flash (at least a reset vector). ****
Warn : **** Issue 'kinetis mdm halt' command or if SRST is connected ****
Warn : **** and configured, use 'reset halt' ****
Warn : **** If MCU cannot be halted, it is likely secured and running ****
Warn : **** in RESET/WDOG loop. Issue 'kinetis mdm mass_erase' ****
Info : starting gdb server for kl25.cpu on 3333
Info : Listening on port 3333 for gdb connections
Mbed CLI
- 这里是在
Linux
下面的安装需求,需要系统先安装了Git,Python3.7.x,Mercurial
等环境.1
2~$ sudo apt-get install python3 python3-pip git mercurial -y
~$ pip install mbed-cli
安装配置交叉工具链
- 根据这里提示,支持三种厂商工具:Arm Compiler 6.13 Professional., Keil MDK 5.29,[GNU Arm Embedded version 9 (9-2019-q4-major)](GNU Arm Embedded version 9 (9-2019-q4-major).这里根据上述中的链接去下载安装通用的
GCC ARM
工具链.
1 | ~$ mbed config -G ARM_GCC_PATH /fullpath/gcc-arm-none-eabi-9-2020-q2-update/bin |
新建工程
1 | ~$ mbed new mbed-example-program |
- 上面新建的工程,默认添加了
mbed-os
的支持,也可以使用--create-only
选项创建不含系统的工程.1
2
3
4
5
6~$ mbed new project2 --create-only
[mbed] Working path "/fullpath/Mbed Programs" (directory)
[mbed] Creating new program "project2" (git)
~$ tree -L 1 project2/
project2/
└── mbed_settings.py
导入工程
1 | ~$ mbed import https://github.com/ARMmbed/mbed-os-example-blinky#mbed-os-5.15.0 my-blink |
为工程添加库
1 | ~$ cd my-blink |
- 如果要删除库就直接:
mbed remove mbed-cloud-client
编译工程
查看可以支持的板子.
1
2
3
4
5
6
7
8
9
10
11~$ mbed compile --supported # mbed compile -S
[mbed] Working path "/fullpath/ArmMbed/mbed-os-example-blinky" (program)
| Target | mbed OS 2 | mbed OS 5 | ARM | uARM | GCC_ARM | IAR |
| ------------- | --------- | --------- | --------- | ---- | --------- | --------- |
| ADV_WISE_1510 | - | Supported | Supported | - | Supported | Supported |
| ADV_WISE_1570 | - | Supported | Supported | - | Supported | Supported |
| ARCH_MAX | - | Supported | Supported | - | Supported | Supported |
| ARCH_PRO | - | Supported | Supported | - | Supported | Supported |
[......]
~$编译
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~$ mbed compile -m KL25Z -t GCC_ARM
[mbed] Working path "/fullpath/ArmMbed/my-blink" (program)
Building project my-blink (KL25Z, GCC_ARM)
Scan: my-blink
Compile [ 0.4%]: at24mac.cpp
[...]
Link: my-blink
Elf2Bin: my-blink
| Module | .text | .data | .bss |
| ---------------- | ------------- | ----------- | ----------- |
| [fill] | 48(+48) | 0(+0) | 28(+28) |
| [lib]/c.a | 4828(+4828) | 2108(+2108) | 89(+89) |
| [lib]/gcc.a | 1004(+1004) | 0(+0) | 0(+0) |
| [lib]/misc | 200(+200) | 4(+4) | 28(+28) |
| main.o | 84(+84) | 0(+0) | 0(+0) |
| mbed-os/drivers | 92(+92) | 0(+0) | 0(+0) |
| mbed-os/hal | 1440(+1440) | 4(+4) | 67(+67) |
| mbed-os/platform | 4204(+4204) | 264(+264) | 220(+220) |
| mbed-os/rtos | 6468(+6468) | 168(+168) | 5973(+5973) |
| mbed-os/targets | 2424(+2424) | 4(+4) | 19(+19) |
| Subtotals | 20792(+20792) | 2552(+2552) | 6424(+6424) |
Total Static RAM memory (data + bss): 8976(+8976) bytes
Total Flash memory (text + data): 23344(+23344) bytes
Image: ./BUILD/KL25Z/GCC_ARM/my-blink.bin设置默认的
target
与交叉工具链1
2
3
4
5
6
7~$ mbed target KL25Z
[mbed] Working path "/fullpath/Mbed Programs/my-blink" (program)
[mbed] KL25Z now set as default target in program "my-blink"
~$ mbed toolchain GCC_ARM
[mbed] Working path "/fullpath/Mbed Programs/my-blink" (program)
[mbed] GCC_ARM now set as default toolchain in program "my-blink"
测试与调试
运行代码测试
1
2~$ mbed test -m KL25Z -t GCC_ARM
[...]查看测试列表
1
2
3
4
5
6
7
8
9~$ mbed test --compile-list | head
Test Case:
Name: mbed-os-features-device_key-tests-device_key-functionality
Path: ./mbed-os/features/device_key/TESTS/device_key/functionality
Test Case:
Name: mbed-os-features-frameworks-utest-tests-unit_tests-basic_test
Path: ./mbed-os/features/frameworks/utest/TESTS/unit_tests/basic_test
Test Case:
[....]连接板子运行测试
1
2
3
4
5
6
7
8
9
10
11
12
13~$ mbed test -m KL25Z -t GCC_ARM --run
[mbed] Working path "/home/michael/3TB-DISK/Mbed Programs/my-blink" (program)
mbedgt: greentea test automation tool ver. 1.7.4
mbedgt: test specification file './BUILD/tests/KL25Z/GCC_ARM/test_spec.json' (specified with --test-spec option)
mbedgt: using './BUILD/tests/KL25Z/GCC_ARM/test_spec.json' from current directory!
mbedgt: detecting connected mbed-enabled devices...
mbedgt: detected 1 device
mbedgt: processing target 'KL25Z' toolchain 'GCC_ARM' compatible platforms... (note: switch set to --parallel 1)
mbedgt: running 4 tests for platform 'KL25Z' and toolchain 'GCC_ARM'
mbedgt: mbed-host-test-runner: started
mbedgt: retry mbedhtrun 1/1
mbedgt: ['mbedhtrun', '-m', 'KL25Z', '-p', '/dev/ttyACM0:9600', '-f', '"BUILD/tests/KL25Z/GCC_ARM/mbed-os/TESTS/psa/spm_smoke/spm_smoke.bin"', '-e', '"mbed-os/TESTS/host_tests"', '-d', '/media/michael/MBED', '-c', 'default', '-t', '02000201242BD1925E8A1EE0', '-r', 'default', '-C', '4', '--sync', '5', '-P', '60'] failed after 1 count
[...]
Ardunio
库
- Links:
- stm32duino
- wiki
Nucleo-F767ZI
与Nucleo-L152RE
都是兼容Arduino
管脚的,这里是使用Nucleo-L152RE
为目标对像.
添加STM32 Cores
- 打开
Arduino IDE
的File->Preferences
,在Additional Board Manager URLs:
内,加入这个链接https://github.com/stm32duino/BoardManagerFiles/raw/master/STM32/package_stm_index.json - 添加完成,它会更新数据.进入
Tools -> Boards -> Boards Manager
过滤”stm32”或者下拉,选择安装STM32 Cores
.
烧写方式
下载stm32-programmers,解压后,直接运行
Linux
下的安装程序,根据向导提示,安装在当前用户的目录下.安装完后,目录如下:1
2
3
4~/STMicroelectronics/STM32Cube/STM32CubeProgrammer/bin$ ls
ExternalLoader HSM libssl.so libstp11_SAM.so.conf STM32CubeProgrammer STM32MP_KeyGen_CLI STM32_Programmer_CLI
FlashLoader libcrypto.so libstp11_SAM.so RSSe STM32CubeProgrammerLauncher STM32MP_SigningTool_CLI STM32_Programmer.sh这里是使用
Nucleo-L152RE
为目标板,选择Tools -> Boards: <any> -> STM32 Boards (select from submenu -> Nucleo-64
.Upload
方法,选择Tools -> Upload method -> STM32CubeProgrammer (SWD)
更新ST-Link的固件
烧写时提示如下的错误.
1
2
3
4
5
6
7
8STM32CubeProgrammer v2.4.0
-------------------------------------------------------------------
Error: Old ST-LINK firmware version. Upgrade ST-LINK firmware
Error: Old ST-LINK firmware version. Upgrade ST-LINK firmware
Error: Old ST-LINK firmware!Please upgrade it.
Error: Old ST-LINK firmware!Please upgrade it.下载stsw-link007,后解压它.
解压目录如下:
1
2
3
4
5
6
7
8
9
10~$ tree -L 2 stsw-link007
stsw-link007
├── AllPlatforms
│ ├── native
│ ├── StlinkRulesFilesForLinux
│ └── STLinkUpgrade.jar
├── readme.txt
└── Windows
├── ST-LinkUpgrade.exe
└── STLinkUSBDriver.dll根据它的
readme.txt
提示,安装完成StlinkRulesFilesForLinux
后下面,就可以运行更新GUI程序更新固件了.1
~$ java -jar STLinkUpgrade.jar
更新完最新的固件后可以,用
ST官方
的STM32CubeProgrammer
读写,但是想用它的ST-link
外接给STM32F103
最小系统板做SWD
烧写调试时出错了.
开源Stlink-tools
- Plug in Nucleo-144 STM32F767ZI
- 在
Linux
下有开源stlink,也可以直接运行apt-get install stlink-tools
安装发行版.
1 | ~$ st-info --probe |
- stlink-gui
1 | ~$ apt-get install stlink-gui |
- 连接成功后读取内存如下。
SPI SD
示例
- 这里选择标准库内的
File -> Examples -> Examples for any board -> SD -> listfiles
的示例,程序如下所示,管脚定义兼容Nucleo-L152RE
,只是CS
这里与原程序定义不符.Nucleo-L152RE
里是pin 10 (CS)
,所以只需要在程序内改成!SD.begin(10)
.
1 | The circuit: |
- 一键
upload
,如果编译烧写成功后,使用串口查看它的输出.
树莓派相关
- Arbitrary Wave Generator With the Raspberry Pi Pico
- Reversing 2.4GHz remote control
- River’s Educational Channel
- F5OEO/rpitx
FreeRTOS
协议分析工具
FTDI232H
- FTDI FT232H for hardware hacking
- SWD all the things!
- Programming FTDI devices in Python: Part 4
- Getting Started with OPENOCD Using FT2232H Adapter for SWD Debugging
- Viewing ARM CPU activity in real time
PyFTDI
- PyFTDI doc
- FTDI232H BoB P. II: E-Z SPI & I2C
- 显示所有设备
1
2
3
4
5from pyftdi.ftdi import Ftdi
Ftdi.show_devices()
Available interfaces:
ftdi://ftdi:232h:6:49/1 (Single RS232-HS)
I2C
- i2c通信,
SCL(AD0),SDA(AD1,AD2)
.I2C
的地址是一个7-bit
的数值,加上第8-bit
方向位(0:写,1:读),构成一个8-bit
数值.1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
from pyftdi.i2c import I2cController
# Instantiate an I2C controller
i2c = I2cController()
# Configure the first interface (IF/1) of the FTDI device as an I2C master
i2c.configure('ftdi://ftdi:2232h/1')
# Get a port to an I2C slave device
slave = i2c.get_port(0x21)
# Send one byte, then receive one byte
slave.exchange([0x04], 1)
# Write a register to the I2C slave
slave.write_to(0x06, b'\x00')
# Read a register from the I2C slave
slave.read_from(0x00, 1)
SPI
下面是通过使用
UM232H
来读取一颗裸SPI NOR Flash W25Qxx
的厂商编号(jedec_id).接线如下:1
2
3
4
5
6
7
8
9UM232H W25Q64FV
AD0 <-----> CLK pin6
AD1 <-----> DI pin5
AD2 <-----> DO pin2
AD3 <-----> CS pin1
GND <-----> GND pin4
VCC <-----> VCC pin8
VCC <-----> /HOLD pin7
VCC <-----> /WP pin3简单测试读取
jedec_id
1 | import usb |
- 使用pyspiflash测试
SPI flash
读写.
1 | pyspiflash/spiflash/tests$ ./serialflash.py |
FlashROM读取
探测flash的类型。
1
2
3
4
5
6
7
8
9
10
11
12
13
14~$ flashrom -L
~$ flashrom -p ft2232_spi:type=2232H,port=A
flashrom v1.2 on Linux 5.16.13-20220310 (x86_64)
flashrom is free software, get the source code at https://flashrom.org
Using clock_gettime for delay loops (clk_id: 1, resolution: 1ns).
Found Macronix flash chip "MX25L6405" (8192 kB, SPI) on ft2232_spi.
Found Macronix flash chip "MX25L6405D" (8192 kB, SPI) on ft2232_spi.
Found Macronix flash chip "MX25L6406E/MX25L6408E" (8192 kB, SPI) on ft2232_spi.
Found Macronix flash chip "MX25L6436E/MX25L6445E/MX25L6465E/MX25L6473E/MX25L6473F" (8192 kB, SPI) on ft2232_spi.
Multiple flash chip definitions match the detected chip(s): "MX25L6405", "MX25L6405D", "MX25L6406E/MX25L6408E", "MX25L6436E/MX25L6445E/MX25L6465E/MX25L6473E/MX25L6473F"
Please specify which chip definition to use with the -c <chipname> option.读取flash内容。
1 | ~$ flashrom -p ft2232_spi:type=2232H,port=A -r test-mx25l6445e.rom -c "MX25L6436E/MX25L6445E/MX25L6465E/MX25L6473E/MX25L6473F" |
屏幕驱动
OpenOCD
- 让
OpenOCD
支持FTDI
的MPSSE
功能,--enable-ftdi Enable building support for the MPSSE mode of FTDI
1 | ~$ cd openocd |
- 除了需要开启
openocd
的支持,还有就是接线,这里试用了interface/ftdi/ft232h-module-swd.cfg
,interface/ftdi/minimodule-swd.cfg
两个配置文件都可以连接成功.配置文件内有接线注释,参考上面的一些链接好像是说要在ADBUS1,ADBUS2
中间接一个470 ohm
的电阻, 但是这里没有接.只是要确认配置文件内的vid_pid
与所连接的硬件匹配. - 使用
Jlink-ob
或者其它板上的STLink
只需要三根线,但是这里必需要接nTRST
,如:stm32f103zet6
就是PB4
.1
2
3
4
5
6
7
8
9
10# FT232HQ minimodule channel 0 (Channel A)
# Connector FTDI Target
# Pin Name
# --------- ------ ------
# CN2-10 GND GND
# CN2-13 ADBUS0 (TCK) SWCLK
# CN2-14 ADBUS2 (TDI/TDO) SWDIO
# CN2-15 ADBUS1 (TDO/TDI) SWDIO
# CN2-17 ADBUS4 (GPIOL0) nTRST
1 | ~$ openocd -f interface/ftdi/ft232h-module-swd.cfg -f target/stm32f1x.cfg -c init \ |
树莓派(RassberyPi)
Saleae 逻辑分析仪
Saleae
逻辑分析仪除了它官方内置支持的一些协议,还可以使用一些第三方Unofficially Supported Protocols协议扩展.
Saleae AnalzerSDK
SDIO协议插件
- SaleaeSDIOAnalyzer
AnalyzerSDK
与SaleaeSDIOAnalyzer
两个目录必需要在同一级目录内,再进入到SaleaeSDIOAnalyzer
内,直接cmake . && make
.如果无错,就会生成libSDIOAnalyzer.so
.- Configure Logic to look for the Analyzer Plugin
Launch Logic manually
Options -> Preferences
Under [For Developers], “Search this path for Analyzer Plugins”
Browse for the ../sdmmc-analyzer/xcode4/build/Debug directory
Click “Save” and close Logic
SDMMC协议
- SD/MMC Analyzer for Logic
- 这个源码是用
python
脚本去编译的,这里在它的目录建一个CMake
脚本来处理编译.成功后会看到一个libSDMMCAnalyzer.so
.
1 | sdmmc-analyzer$ cat CMakeLists.txt |
QSPI协议插件
- dedicatedcomputing /saleae_qspi
也类似如上面的操作,添加CMake
脚本处理.
STM8S103
Links:
STM8S103
是支持SDCC (Small Devices C compiler)
编译器的,而且SDCC
版本须大于v3.4.0
以上。
SDCC示例编译
Arduino支持
编程工具
- stm8flash
stm8flash
开源工具,是针对stlink
硬件烧写的,我这里还是使用openocd+ft2232
这样的方式对它进行编程烧写。
其它资源
- A little whimsy copter based on a PCB frame, not at all premium components.
- Klipper is a 3d-printer firmware
- RTEMS
谢谢支持
- 微信二维码: