If you want to start your application on NuttX directly without using the NSH you can setup your “app_main” in the ENTRYPOINT, although you will see that some drivers will not start anymore.
You can fix it enabling the “Board Late Init” in the menuconfig:
RTOS Features ---> RTOS hooks ---> [*] Custom board late initialization
Also you need to disable the architecture-specific initialization:
Application Configuration ---> NSH Library ---> Have architecture-specific initialization
qa -- Record a macro in hotkey a
0 -- Go to the beginning of the line
f= -- Go to the first equals sign
100i <Esc> -- (There's a single space after the i, and the <Esc> means press escape, don't type "<Esc>".) Insert 100 spaces
8| -- Go to the 8th column (sorry, you'll have to manually figure out which column to align to)
dw -- Delete until the next non-space character
j -- Go to the next line
q -- Stop recording.
In my case I just replaced the “f=” with “f0” and “8|” with “33|”
Found SW-DP with ID 0x2BA01477 Unknown DP version. Assuming DPv0 Scanning AP map to find all available APs AP[1]: Stopped AP scan as end of AP map has been reached AP[0]: AHB-AP (IDR: 0x24770011) Iterating through AP map to find AHB-AP to use AP[0]: Core found AP[0]: AHB-AP ROM base: 0xE00FF000 CPUID register: 0x410FC241. Implementer code: 0x41 (ARM) Found Cortex-M4 r0p1, Little endian. FPUnit: 6 code (BP) slots and 2 literal slots CoreSight components: ROMTbl[0] @ E00FF000 ROMTbl[0][0]: E000E000, CID: B105E00D, PID: 000BB00C SCS-M7 ROMTbl[0][1]: E0001000, CID: B105E00D, PID: 003BB002 DWT ROMTbl[0][2]: E0002000, CID: B105E00D, PID: 002BB003 FPB ROMTbl[0][3]: E0000000, CID: B105E00D, PID: 003BB001 ITM ROMTbl[0][4]: E0040000, CID: B105900D, PID: 000BB9A1 TPIU ROMTbl[0][5]: E0041000, CID: B105900D, PID: 000BB925 ETM Cortex-M4 identified. J-Link>loadbin nuttx.bin, 0 Halting CPU for downloading file. Downloading file [nuttx.bin]… Writing target memory failed.
J-Link>erase Erasing device… J-Link: Flash download: Only internal flash banks will be erased. To enable erasing of other flash banks like QSPI or CFI, it needs to be enabled via "exec EnableEraseAllFlashBanks" Erasing flash [100%] Done.
Error: Failed to erase chip @ address 0x08000000 (Algo87: Unspecified error #1) Failed to erase chip. Failed to execute RAMCode for chip erase! J-Link: Flash download: Total time needed: 0.105s (Prepare: 0.064s, Compare: 0.000s, Erase: 0.001s, Program: 0.000s, Verify: 0.000s, Restore: 0.038s) ERROR: Erase returned with error code -5. J-Link>
Strange, after resetting the board and writing a .hex instead of a .bin worked…
I was trying to run NuttX RTOS on iMXRT1060_EVK board (it has an external 8MiB QSPI Flash), but because my JLink EDU is version V8 it doesn’t supports Cortex-M7.
Using the DAPLink drag-and-drop I can copy small nuttx firmwares (i.e.: up to 73KB worked), but when I compile NuttX to PROTECTED Mode it doesn’t work. Because the kernel is at the beginning of the flash and the userspace is at offset +2MB. Then during the copy it reports timeout.
Then I tried to use OpenOCD. I got it working for debugging, but it doesn’t have support to flash the QSPI for NXP chips, only for STMicro.
“You can actually run the LPC-Link2 firmware on the onboard debug probe of the RT1064-EVK board, in place of the default DAP-Link firmware. For more details see:”
[ 638.833516] usb 1-1: new high-speed USB device number 9 using xhci_hcd [ 638.982422] usb 1-1: New USB device found, idVendor=1fc9, idProduct=000c, bcdDevice= 1.00 [ 638.982428] usb 1-1: New USB device strings: Mfr=1, Product=2, SerialNumber=3 [ 638.982434] usb 1-1: Product: LPC [ 638.982436] usb 1-1: Manufacturer: NXP [ 638.982439] usb 1-1: SerialNumber: ABCD
I have a LPCXpresso54628 board here, then I thought about the idea of using its LPC-Link2 to program the iMXRT1060. But that should be more complicated.
“You can actually run the LPC-Link2 firmware on the onboard debug probe of the RT1064-EVK board, in place of the default DAP-Link firmware. For more details see:”
I decided to document the steps needed to get the Low Power SPI working on iMXRT1050-EVKB and I hope it could be useful for other people using this board. But the basic idea apply to any other board supported by NuttX.
Everything starts with the schematic, you need to spot the SPI pins that you want to use and which SPI Port it belongs to.
Perfect, but here you need to know an important information about NuttX: normally the NuttX SPI drivers don’t use the native CS (Chip Select) pin, instead it use ordinary GPIO pins to work as CS. The reason behind it is because normally the SPI Hardware has a limited number os HW CS pins (normally 4 pins). So instead of limiting the user to only 4 devices (CS), NuttX allow you to use how many CS pins as you wish.
Now we need to see in the LPSPI driver what is the name of pins it uses, so we will associate these pins to those from the pinmux header file.
Just open the file arch/arm/src/imxrt/imxrt_lpspi.c and search for imxrt_config_gpio(), this is the function used to configure the pins on iMXRT10xx chips.
Don’t worry, if you look at iMXRT1050 Datasheet you will see that this CS pin (GPIO_SD_B0_01) is the GPIO3.IO[13] and it is already defined at boards/arm/imxrt/imxrt1050-evk/src/imxrt1050-evk.h this way:
So, with the basic configuration in place, now we can start defining our SPI device initialization. Let me think what SPI device we could you. Well, since I want you to “see” the SPI working, let’s to use the MAX7219 7-segment numeric display!
Fortunately we have the boards/arm/stm32/stm32f4discovery/src/stm32_max7219_leds.c as example to initialize our MAX7219 display.
We can copy it and modify to become an iMXRT file:
And to call the initialization we just add these lines to boards/arm/imxrt/imxrt1050-evk/src/imxrt_bringup.c inside imxrt_bringup() function:
#ifdef CONFIG_LEDS_MAX7219 ret = imxtrt_max7219init("/dev/numdisp0"); if (ret < 0) { syslog(LOG_ERR, "ERROR: max7219_leds_register failed: %d\n", ret); } #endif
After everything is in place you can configure your iMXRT1050-EVK board, enter in the menuconfig and select:
System Type -> i.MX RT Peripheral Selection -> LPSPI Peripherals -> [*] LPSPI1
Device Drivers -> [*] SPI Driver Support
Device Drivers -> LED Support -> [*] MAX7219 Numeric Display
Save and Exit. Just type “make” to compile.
When the compilation finish you can look at the System.map file and search for max7219, you should see these symbols:
6000f954 T imxrt_max7219init 6000f974 t max7219_open 6000f978 t max7219_read 6000f97e t max7219_write16.isra.0 6000f9f4 t max7219_write 6000fb4e t max7219_close 6000fb52 T max7219_leds_register
Flash the firmware in the board (with SW7 1-off 2-on 3-on 4-off I just dropped the nuttx.hex in the disk), open the /dev/ttyACM0 and reset the board, you show see:
NuttShell (NSH) NuttX-9.1.0
nsh> uname -a
NuttX 9.1.0 9a1391d36b-dirty Aug 8 2020 12:23:10 arm imxrt1050-evk
nsh> ls /dev
/dev:
console
null
numdisp0
ttyS0
nsh>
As you can see our /dev/numdisp0 is there!
Note: you need to solder the resistors R281, R279, R278 and R280 to get LPSPI1 working.
I decided to test the SDCard support on iMXRT1050-EVK board, but go these errors:
CC: chip/imxrt_lowputc.c
chip/imxrt_lowputc.c: In function 'imxrt_lpuart_configure':
chip/imxrt_lowputc.c:559:2: warning: #warning missing logic [-Wcpp]
559 | #warning missing logic
| ^
CC: chip/imxrt_idle.c
CC: chip/imxrt_timerisr.c
chip/imxrt_timerisr.c:63:2: warning: #warning REVISIT these clock settings [-Wcpp]
63 | #warning REVISIT these clock settings
| ^
CC: chip/imxrt_usdhc.c
chip/imxrt_usdhc.c:100:4: error: #error "CONFIG_SDIO_BLOCKSETUP is mandatory for this driver"
100 | # error "CONFIG_SDIO_BLOCKSETUP is mandatory for this driver"
| ^
In file included from chip/imxrt_usdhc.c:60:
chip/imxrt_usdhc.c: In function 'imxrt_usdhc_initialize':
chip/imxrt_usdhc.c:3144:25: error: 'GPIO_USDHC1_DATA0' undeclared (first use in this function); did you mean 'GPIO_USDHC1_DATA0_1'?
3144 | imxrt_config_gpio(PIN_USDHC1_D0);
| ^
chip/imxrt_usdhc.c:3144:25: note: each undeclared identifier is reported only once for each function it appears in
chip/imxrt_usdhc.c:3145:25: error: 'GPIO_USDHC1_CLK' undeclared (first use in this function); did you mean 'GPIO_USDHC1_CLK_1'?
3145 | imxrt_config_gpio(PIN_USDHC1_DCLK);
| ^
chip/imxrt_usdhc.c:3146:25: error: 'GPIO_USDHC1_CMD' undeclared (first use in this function); did you mean 'GPIO_USDHC1_CMD_1'?
3146 | imxrt_config_gpio(PIN_USDHC1_CMD);
| ^
make[1]: *** [Makefile:151: imxrt_usdhc.o] Error 1
The first error as easy to fix: just run “make menuconfig” press the key “/” and search for “CONFIG_SDIO_BLOCKSETUP” you will find the:
Prompt: SDIO block setup
Just press 1 do go directly to it and then enable it:
[*] SDIO block setup
After trying to compile again you will see that the pins definition still missing: PIN_USDHC1_D0, PIN_USDHC1_DCLK, PIN_USDHC1_CMD. Just like we did for SPI in the previous post, you need to start looking the schematics.
First let see the SDCard slot:
So, let search for these pins: SD1_CLK, SD1_CMD, SD1_D0, SD1_D1, SD1_SD2, SD1_D3 and SD_CD_SW:
Ok, after defining these pins the compilation finished correctly. But the fact of the USDHC driver is only failing because DATA0 rings a bell! Probably it is using SD Card with 1-bit interface, we need to enable 4-bits interface:
$ make menuconfig
System Type -> USDHC Configuration -> Bus width for USDHC1 (Four bit)
Perfect, now the compilation is failing, this is exactly what I was waiting for:
CC: chip/imxrt_usdhc.c In file included from chip/imxrt_usdhc.c:60: chip/imxrt_usdhc.c: In function 'imxrt_usdhc_initialize': chip/imxrt_usdhc.c:3138:25: error: 'GPIO_USDHC1_DATA1' undeclared (first use in this function); did you mean 'GPIO_USDHC1_DATA2_1'? 3138 | imxrt_config_gpio(PIN_USDHC1_D1); | ^ chip/imxrt_usdhc.c:3138:25: note: each undeclared identifier is reported only once for each function it appears in chip/imxrt_usdhc.c:3139:25: error: 'GPIO_USDHC1_DATA2' undeclared (first use in this function); did you mean 'GPIO_USDHC1_DATA2_1'? 3139 | imxrt_config_gpio(PIN_USDHC1_D2); | ^ chip/imxrt_usdhc.c:3140:25: error: 'GPIO_USDHC1_DATA3' undeclared (first use in this function); did you mean 'GPIO_USDHC1_DATA3_1'? 3140 | imxrt_config_gpio(PIN_USDHC1_D3); | ^ make[1]: *** [Makefile:151: imxrt_usdhc.o] Error 1 make[1]: Leaving directory '/comum/workspace/Consultancy/iDTech/NuttX/nuttx/arch/arm/src' make: *** [tools/LibTargets.mk:155: arch/arm/src/libarch.a] Error 2
You already know what to do, right? Just insert all the pins to board.h :
Excellent! Now it is compiling with 4-bit SDCard interface.
But wait! What about the SDCard insertion pin (SD_CD_SW)? If you look at arch/arm/src/imxrt/imxrt_usdhc.c you will see that it is waiting for a pin named PIN_USDHC1_CD_GPIO, so let to declare it pointing to our pin:
NuttX is evolving all the time and although I created a video tutorial at NuttX Channel explaining how to create a RAMDISK, that information is already outdated.
Let’s do it again using the current NuttX version (9.1)
First select the needed options at menuconfig:
Device Drivers --->
[*] RAM disk wrapper (mkrd)
Board Selection --->
[*] Enable boardctl() interface
[*] Enable application space creation of RAM disks
File Systems --->
[*] FAT file system
Compile it and run these commands when NuttX’s nsh show up on serial console:
NuttShell (NSH) NuttX-9.1.0
nsh> ?
help usage: help [-v] []
. cd echo hexdump mkrd pwd test usleep
[ cp exec kill mh rm time xd
? cmp exit ls mount rmdir true
basename dirname false mb mv set uname
break dd free mkdir mw sleep umount
cat df help mkfatfs ps source unset
Builtin Apps:
sh nsh
nsh> mkrd 64
nsh> ls /dev
/dev:
console
null
ram0 <---
ttyS0
nsh> mkfatfs /dev/ram0
nsh> mount -t vfat /dev/ram0 /mnt
nsh> echo "This is a file in RAMDISK" > /mnt/file.txt
nsh> cat /mnt/file.txt
This is a file in RAMDISK
nsh>
This is common error on NuttX, but unfortunately the build system is not clear to explain to the user about it.
$ git clone https://github.com/apache/incubator-nuttx
$ cd incubator-nuttx
$ ./tools/configure.sh esp32-core:nsh
...
This program built for x86_64-pc-linux-gnu
Report bugs to bug-make@gnu.org
make: *** [tools/Makefile.unix:319: dirlinks] Error 2
ERROR: failed to refresh
This problem happens because you missed to clone the apps/ repository:
$ cd .. $ git clone https://github.com/apache/incubator-nuttx-apps apps
Now you can configure it correctly:
$ cd incubator-nuttx
$ ./tools/configure.sh esp32-core:nsh
...
#
# configuration written to .config
#
I’m using the Mi Earbuds for two days and these are my impressions so far:
Pros:
It is comfortable because it fits perfectly in the ears! At first I thought I was going to feel like the Frankenstein with his bolts in his neck, but it was my prejudice;
The battery duration is fine, of course it could be nice if it could run for days instead of a single day;
It is very light weight compared to others Wireless headsets.
Cons:
It often drops off your ears mainline when you are speaking or eating;
It starts to cut the connection when you are more than 5 meter far from your smartphone (in my case I’m using a high-end Xiaomi smartphone);
There is not a button to move to the next music, hopefully I found a solution for it:
So, I’m happy with this product, but I think Xiaomi could make improvements for the next models to fix these points.
Some time ago I needed to link with ARM DSP library on NuttX to use FFT feature and I decided to document who I did it and some tricks to reduce the final binary size.
In fact to include a library all you need to do is add it to your board Make.defs. See a simple patch file to stm32f4discovery:
It means you need to create a “3rdpary” directory at root of nuttx/ and put your library there.
But after the compilation you will notice that your nuttx.bin binary will become very big. It happens because the linker will include all the functions in the library.
You can instruct it to include only the needed functions using this parameter with LDFLAGS:
If you decide you create your own NuttX application based on apps/examples/hello you could eventually face this issue:
CC: my_app_main.c
:0:6: error: expected identifier or '(' before numeric constant
:0:6: error: expected identifier or '(' before numeric constant
my_app_main.c:51:5: note: in expansion of macro 'main'
int main(int argc, FAR char *argv[])
^
make[3]: *** [/home/alan/apps/Application.mk:189: my_app_main.home.alan.apps.examples.my_app.o] Error 1
This error happens because your PROGNAME defined inside the Kconfig differs from your application name:
If your PROGNAME is myapp then you need to have apps/examples/myapp/myapp_main.c otherwise it will not work. So don’t my_app for your app directory neither my_app_main.c for your main file, it needs to be myapp_main.c