Month: September 2022

How to get NuttX RTOS working on old ESP32-Devkit with 2MB SPIFLASH

After compiling and flash NuttX with wapi example:
$ ./tools/configure.sh esp32-devkitc:wapi

$ make -j flash ESPTOOL_PORT=/dev/ttyUSB0


I got this error:

I (29) boot: ESP-IDF v5.0-dev-1181-g0132079fa5 2nd stage bootloader
I (29) boot: compile time 14:26:53
I (29) boot: chip revision: 1
I (34) boot_comm: chip revision: 1, min. bootloader chip revision: 0
I (41) boot.esp32: SPI Speed      : 40MHz
I (45) boot.esp32: SPI Mode       : DIO
I (50) boot.esp32: SPI Flash Size : 2MB
I (54) boot: Enabling RNG early entropy source...
I (60) boot: Partition Table:
I (63) boot: ## Label            Usage          Type ST Offset   Length
I (71) boot:  0 nvs              WiFi data        01 02 00009000 00006000
I (78) boot:  1 phy_init         RF data          01 01 0000f000 00001000
I (86) boot:  2 factory          factory app      00 00 00010000 00100000
I (93) boot: End of partition table
I (97) boot_comm: chip revision: 1, min. application chip revision: 0
I (104) esp_image: segment 0: paddr=00010020 vaddr=3f400020 size=13030h ( 77872) map
I (141) esp_image: segment 1: paddr=00023058 vaddr=3ffbca40 size=02284h (  8836) load
I (145) esp_image: segment 2: paddr=000252e4 vaddr=40080000 size=0ad34h ( 44340) load
I (165) esp_image: segment 3: paddr=00030020 vaddr=400d0020 size=6c2c0h (443072) map
I (326) esp_image: segment 4: paddr=0009c2e8 vaddr=4008ad34 size=01730h (  5936) load
I (335) boot: Loaded app from partition at offset 0x10000
I (335) boot: Disabling RNG early entropy source...
�ABup_assert: Assertion failed at file:chip/esp32_spiflash.c line: 2011 task: nsh_main
xtensa_registerdump:    PC: 400d76e5    PS: 00060f20
xtensa_registerdump:    A0: 800d7019    A1: 3ffe1350    A2: 00000000    A3: 3ffb25fe
xtensa_registerdump:    A4: 20000000    A5: 3ffafc90    A6: 3ffb04a8    A7: fffffffc
xtensa_registerdump:    A8: 800f6ac8    A9: 3ffe12c0   A10: 00000054   A11: 3f4009b4
xtensa_registerdump:   A12: 3ffe13a0   A13: 3ffe1380   A14: 00000008   A15: 00000000
xtensa_registerdump:   SAR: 00000004 CAUSE: 3ffe1380 VADDR: 00000008
xtensa_registerdump:  LBEG: 4000c46c  LEND: 4000c477  LCNT: 00000000
xtensa_dump_stack: IRQ Stack:
xtensa_dump_stack: sp:     3ffe1370
xtensa_dump_stack:   base: 3ffbca40
xtensa_dump_stack:   size: 00000800
xtensa_dump_stack:   used: 00000000
xtensa_dump_stack: ERROR: IRQ Stack pointer is not within the stack
xtensa_dump_stack: User Stack:
xtensa_dump_stack: sp:     3ffe1370
xtensa_dump_stack:   base: 3ffe0570
xtensa_dump_stack:   size: 00000fc0
xtensa_dump_stack:   used: 000004d8
xtensa_stackdump: 3ffe1360: 800d68c2 3ffe13a0 00000000 3f4009b4 00000000 3ffe1380 00000008 deadbeef
xtensa_stackdump: 3ffe1380: 3ffafd00 3ffe1370 3ffb23e4 00000002 800d445c 3ffe13c0 3ffbec84 000007db
xtensa_stackdump: 3ffe13a0: 3f400a57 3ffbec84 000007db 3ffafd7c 80084a60 3ffe13e0 3ffbec84 000007db
xtensa_stackdump: 3ffe13c0: 00060920 00000041 00000000 00000000 800f4d52 3ffe1400 00280000 000b0000
xtensa_stackdump: 3ffe13e0: 00000064 3ffe13b0 3ffbf060 3ffae700 800f4d10 3ffe1420 00000000 3ffe1600
xtensa_stackdump: 3ffe1400: 00000000 3ffae700 3f401c4d 3f401c51 800f4ce6 3ffe1440 00000000 00000035
xtensa_stackdump: 3ffe1420: 3f402360 00000000 00000003 00000000 800e9590 3ffe1460 00000000 0000007e
xtensa_stackdump: 3ffe1440: 3ffafc90 3ffafc70 3ffafd00 00000000 800d7b47 3ffe1480 ffffffe7 00000000
xtensa_stackdump: 3ffe1460: 3ffafcb0 3ffafc90 3ffb04a8 fffffffc 800d7b00 3ffe14a0 00000000 3ffe14c0
xtensa_stackdump: 3ffe1480: 00000000 3ffe15a0 00060020 3ffb04a0 800d4498 3ffe14c0 00000001 3ffe0550
xtensa_stackdump: 3ffe14a0: 00000000 3ffafcd0 00000002 00000000 800d290f 3ffe14f0 400d7ae0 00000001
xtensa_stackdump: 3ffe14c0: 00000064 00000000 00000000 00000000 00000064 3ffe15dc 3ffafdb0 3ffb0368
xtensa_stackdump: 3ffe14e0: 00000000 3ffe1510 00000000 00000000 3ffe0550 3f400420 00000000 3ffb00dc
xtensa_stackdump: 3ffe1500: 00000000 3ffe1530 00000000 00000000 00000000 00000000 00000000 00000000
xtensa_showtasks:    PID    PRI     STACK      USED   FILLED    COMMAND
xtensa_showtasks:   ----   ----      2048         0     0.0%    irq
xtensa_dump_task:      0      0      3040       512    16.8%    Idle Task
xtensa_dump_task:      1    100      4032       376     9.3%    lpwork 0x3ffb04a0
xtensa_dump_task:      2    100      4032      1336    33.1%    nsh_main

It is happening because the MTD partitions are located at OFFSET+SIZE that went over the 2MB Flash:

CONFIG_ESP32_STORAGE_MTD_OFFSET=0x180000
CONFIG_ESP32_STORAGE_MTD_SIZE=0x80000
...
CONFIG_ESP32_WIFI_MTD_OFFSET=0x280000
CONFIG_ESP32_WIFI_MTD_SIZE=0xb0000

See 2MB means 0x200000 then the partitions are going beyond that.

An option to fix it is reducing the partition size and moving the WIFI_MTD_OFFSET to below 0x200000:

CONFIG_ESP32_STORAGE_MTD_OFFSET=0x180000
CONFIG_ESP32_STORAGE_MTD_SIZE=0x10000
...
CONFIG_ESP32_WIFI_MTD_OFFSET=0x190000
CONFIG_ESP32_WIFI_MTD_SIZE=0x10000

Now everything is working as expected:

nsh> wapi psk wlan0 MyPassword 3
nsh> wapi essid wlan0 MyRouterName 1
nsh> renew wlan0
nsh> ifconfig
wlan0   Link encap:Ethernet HWaddr ac:67:b2:53:8b:ec at UP
        inet addr:192.168.0.7 DRaddr:192.168.0.1 Mask:255.255.255.0
                                                                        
             IPv4   TCP   UDP  ICMP                                     
Received     0004  0000  0002  0002                                     
Dropped      0000  0000  0000  0000                                     
  IPv4        VHL: 0000   Frg: 0000
  Checksum   0000  0000  0000  ----
  TCP         ACK: 0000   SYN: 0000
              RST: 0000  0000
  Type       0000  ----  ----  0000
Sent         0004  0000  0002  0002
  Rexmit     ----  0000  ----  ----
nsh> ping 8.8.8.8
PING 8.8.8.8 56 bytes of data
56 bytes from 8.8.8.8: icmp_seq=0 time=50.0 ms
56 bytes from 8.8.8.8: icmp_seq=1 time=40.0 ms
56 bytes from 8.8.8.8: icmp_seq=2 time=50.0 ms
56 bytes from 8.8.8.8: icmp_seq=3 time=50.0 ms
56 bytes from 8.8.8.8: icmp_seq=4 time=60.0 ms
56 bytes from 8.8.8.8: icmp_seq=5 time=50.0 ms
56 bytes from 8.8.8.8: icmp_seq=6 time=40.0 ms
56 bytes from 8.8.8.8: icmp_seq=7 time=40.0 ms
56 bytes from 8.8.8.8: icmp_seq=8 time=40.0 ms
56 bytes from 8.8.8.8: icmp_seq=9 time=50.0 ms
10 packets transmitted, 10 received, 0% packet loss, time 10100 ms
rtt min/avg/max/mdev = 40.000/47.000/60.000/6.403 ms

Timer countdown used on nuttx events

<!DOCTYPE HTML>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<style>
p {
  text-align: center;
  font-size: 60px;
  margin-top: 0px;
}
</style>
</head>
<body>

<p id="demo"></p>

<script>
// Set the date we're counting down to
var countDownDate = new Date("Jan 5, 2024 15:37:25").getTime();

// Update the count down every 1 second
var x = setInterval(function() {

  // Get today's date and time
  var now = new Date().getTime();
    
  // Find the distance between now and the count down date
  var distance = countDownDate - now;
    
  // Time calculations for days, hours, minutes and seconds
  var days = Math.floor(distance / (1000 * 60 * 60 * 24));
  var hours = Math.floor((distance % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
  var minutes = Math.floor((distance % (1000 * 60 * 60)) / (1000 * 60));
  var seconds = Math.floor((distance % (1000 * 60)) / 1000);
    
  // Output the result in an element with id="demo"
  document.getElementById("demo").innerHTML = days + "d " + hours + "h "
  + minutes + "m " + seconds + "s ";
    
  // If the count down is over, write some text 
  if (distance < 0) {
    clearInterval(x);
    document.getElementById("demo").innerHTML = "EXPIRED";
  }
}, 1000);
</script>

</body>
</html> 

The header order matter

I was having a nasty error when adding W5500 for ESP32S2:


board/esp32s2_w5500.c: In function 'up_enable':
board/esp32s2_w5500.c:139:13: warning: implicit declaration of function 'ESP32S2_PIN2IRQ'; did you mean 'ESP32S2_PERIPH2IRQ'? [-Wimplicit-function-declaration]
  139 |   int irq = ESP32S2_PIN2IRQ(GPIO_W5500_INTR);
      |             ^~~~~~~~~~~~~~~
      |             ESP32S2_PERIPH2IRQ
board/esp32s2_w5500.c:135:13: note: declared here
  135 | static void up_enable(const struct w5500_lower_s *lower, bool enable)



After spend much time trying to fix it I looked the esp32s2_gpio.c and decided to follow the same header files order, then it worked:

#include <nuttx/config.h>

#include <sys/types.h>
#include <syslog.h>
#include <assert.h>
#include <debug.h>

#include <nuttx/irq.h>
#include <arch/irq.h>

#include <nuttx/spi/spi.h>
#include <nuttx/net/w5500.h>
#include <nuttx/ioexpander/gpio.h>

#include <arch/board/board.h>

#include "esp32s2-saola-1.h"
#include "esp32s2_spi.h"
#include "esp32s2_gpio.h"
#include "hardware/esp32s2_gpio_sigmap.h"

Testing ENC28J60 on NuttX

ABCDF
netdev_register: Registered MAC: 00:00:00:00:00:00 as dev: eth0
arm_netinitialize: Bound SPI port 1 to ENC28J60 device 0
nsh_telnetstart: Starting the Telnet daemon
netdev_ifr_ioctl: cmd: 1813
netdev_ifr_ioctl: cmd: 1794
netdev_ifr_ioctl: cmd: 1796
netdev_ifr_ioctl: cmd: 1800
netdev_ifr_ioctl: cmd: 1818
enc_ifup: Bringing up: 192.168.0.16
enc_reset: WARNING: Reset
enc_reset: Rev ID: 06
enc_pwrfull: Clear PWRSV
Nutelnetd_daemon: Accepting connections on port 23
ttShell (NSH) NuttX-10.4.0
nsh> enc_irqworker: EIR: 10
nsh> ifconfig
netdev_ifr_ioctl: cmd: 1819
netdev_ifr_ioctl: cmd: 1819
netdev_ifr_ioctl: cmd: 1819
netdev_ifr_ioctl: cmd: 1819
eth0 Link encap:Ethernet HWaddr 00:e0:de:ad:be:ef at UP
inet addr:192.168.0.16 DRaddr:192.168.0.1 Mask:255.255.255.0
         IPv4   TCP   UDP  ICMP
Received 0000 0000 0000 0000
Dropped 0000 0000 0000 0000
IPv4 VHL: 0000 Frg: 0000
Checksum 0000 0000 0000 ----
TCP ACK: 0000 SYN: 0000
RST: 0000 0000
Type 0000 ---- ---- 0000
Sent 0000 0000 0000 0000
Rexmit ---- 0000 ---- ----
nsh> ping 192.168.0.1
PIsendto_eventhandler: flags: 4000
sendto_eventhandler: Send ICMP request
sendto_request: Outgoing ICMP packet length: 84 (84)
sendto_eventhandler: Resuming
enc_txpoll: Poll result: d_len=84
arp_out: ARP request for IP 0100a8c0
enc_transmit: Sending packet, pktlen: 42
NGenc_irqworker: EIR: 08
enc_txpoll: Poll result: d_len=0
1enc_irqworker: EPKTCNT: 01
9enc_pktif: Receiving packet, nextpkt: 0046 pktlen: 64 rxstat: 00c0
2enc_rxdispatch: ARP packet received (608)
arp_arpin: ARP reply for IP .1000a8c0
168.0.1 56 bytes of data
Nosendto_eventhandler: flags: 4000
sendto_eventhandler: Send ICMP request
sendto_request: Outgoing ICMP packet length: 84 (84)
sendto_eventhandler: Resuming
enc_txpoll: Poll result: d_len=84
enc_transmit: Sending packet, pktlen: 98
reenc_irqworker: EIR: 08
senc_txpoll: Poll result: d_len=0
penc_irqworker: EPKTCNT: 01
oenc_pktif: Receiving packet, nextpkt: 00b2 pktlen: 102 rxstat: 00c0
nsenc_rxdispatch: IPv4 frame
eicmp_poll_eventhandler: flags: 0002
icmp_datahandler: Buffered 81 bytes
ficmp_readahead: Received 64 bytes (of 81)
rom 192.168.0.1: icmp_seq=0 time=1000 ms
56 bytes from 192.168.0.1: icmp_seq=1 time=40.0 ms
sendto_eventhandler: flags: 4000
sendto_eventhandler: Send ICMP request
sendto_request: Outgoing ICMP packet length: 84 (84)
sendto_eventhandler: Resuming
enc_txpoll: Poll result: d_len=84
enc_transmit: Sending packet, pktlen: 98
enc_irqworker: EIR: 08
enc_txpoll: Poll result: d_len=0
enc_irqworker: EPKTCNT: 01
enc_pktif: Receiving packet, nextpkt: 011e pktlen: 102 rxstat: 00c0
enc_rxdispatch: IPv4 frame
icmp_poll_eventhandler: flags: 0002
icmp_datahandler: Buffered 81 bytes
icmp_readahead: Received 64 bytes (of 81)
56 bytes from 192.168.0.1: icmp_seq=2 time=40.0 ms
sendto_eventhandler: flags: 4000
sendto_eventhandler: Send ICMP request
sendto_request: Outgoing ICMP packet length: 84 (84)
sendto_eventhandler: Resuming
enc_txpoll: Poll result: d_len=84
enc_transmit: Sending packet, pktlen: 98
enc_irqworker: EIR: 08
enc_txpoll: Poll result: d_len=0
enc_irqworker: EPKTCNT: 01
enc_pktif: Receiving packet, nextpkt: 018a pktlen: 102 rxstat: 00c0
enc_rxdispatch: IPv4 frame
icmp_poll_eventhandler: flags: 0002
icmp_datahandler: Buffered 81 bytes
icmp_readahead: Received 64 bytes (of 81)
56 bytes from 192.168.0.1: icmp_seq=3 time=40.0 ms
sendto_eventhandler: flags: 4000
sendto_eventhandler: Send ICMP request
sendto_request: Outgoing ICMP packet length: 84 (84)
sendto_eventhandler: Resuming
enc_txpoll: Poll result: d_len=84
enc_transmit: Sending packet, pktlen: 98
enc_irqworker: EIR: 08
enc_txpoll: Poll result: d_len=0
enc_irqworker: EPKTCNT: 01
enc_pktif: Receiving packet, nextpkt: 01f6 pktlen: 102 rxstat: 00c0
enc_rxdispatch: IPv4 frame
icmp_poll_eventhandler: flags: 0002
icmp_datahandler: Buffered 81 bytes
icmp_readahead: Received 64 bytes (of 81)
56 bytes from 192.168.0.1: icmp_seq=4 time=40.0 ms
sendto_eventhandler: flags: 4000
sendto_eventhandler: Send ICMP request
sendto_request: Outgoing ICMP packet length: 84 (84)
sendto_eventhandler: Resuming
enc_txpoll: Poll result: d_len=84
enc_transmit: Sending packet, pktlen: 98
enc_irqworker: EIR: 08
enc_txpoll: Poll result: d_len=0
enc_irqworker: EPKTCNT: 01
enc_pktif: Receiving packet, nextpkt: 0262 pktlen: 102 rxstat: 00c0
enc_rxdispatch: IPv4 frame
icmp_poll_eventhandler: flags: 0002
icmp_datahandler: Buffered 81 bytes
icmp_readahead: Received 64 bytes (of 81)
56 bytes from 192.168.0.1: icmp_seq=5 time=40.0 ms
sendto_eventhandler: flags: 4000
sendto_eventhandler: Send ICMP request
sendto_request: Outgoing ICMP packet length: 84 (84)
sendto_eventhandler: Resuming
enc_txpoll: Poll result: d_len=84
enc_transmit: Sending packet, pktlen: 98
enc_irqworker: EIR: 08
enc_txpoll: Poll result: d_len=0
enc_irqworker: EPKTCNT: 01
enc_pktif: Receiving packet, nextpkt: 02ce pktlen: 102 rxstat: 00c0
enc_rxdispatch: IPv4 frame
icmp_poll_eventhandler: flags: 0002
icmp_datahandler: Buffered 81 bytes
icmp_readahead: Received 64 bytes (of 81)
56 bytes from 192.168.0.1: icmp_seq=6 time=40.0 ms
enc_irqworker: EIR: 40
enc_irqworker: EPKTCNT: 01
enc_pktif: Receiving packet, nextpkt: 0314 pktlen: 64 rxstat: 00c0
enc_rxdispatch: ARP packet received (608)
arp_arpin: ARP request for IP 1000a8c0
enc_transmit: Sending packet, pktlen: 42
enc_irqworker: EIR: 08
enc_txpoll: Poll result: d_len=0
sendto_eventhandler: flags: 4000
sendto_eventhandler: Send ICMP request
sendto_request: Outgoing ICMP packet length: 84 (84)
sendto_eventhandler: Resuming
enc_txpoll: Poll result: d_len=84
enc_transmit: Sending packet, pktlen: 98
enc_irqworker: EIR: 08
enc_txpoll: Poll result: d_len=0
enc_irqworker: EPKTCNT: 01
enc_pktif: Receiving packet, nextpkt: 0380 pktlen: 102 rxstat: 00c0
enc_rxdispatch: IPv4 frame
icmp_poll_eventhandler: flags: 0002
icmp_datahandler: Buffered 81 bytes
icmp_readahead: Received 64 bytes (of 81)
56 bytes from 192.168.0.1: icmp_seq=7 time=40.0 ms
sendto_eventhandler: flags: 4000
sendto_eventhandler: Send ICMP request
sendto_request: Outgoing ICMP packet length: 84 (84)
sendto_eventhandler: Resuming
enc_txpoll: Poll result: d_len=84
enc_transmit: Sending packet, pktlen: 98
enc_irqworker: EIR: 08
enc_txpoll: Poll result: d_len=0
enc_irqworker: EPKTCNT: 01
enc_pktif: Receiving packet, nextpkt: 03ec pktlen: 102 rxstat: 00c0
enc_rxdispatch: IPv4 frame
icmp_poll_eventhandler: flags: 0002
icmp_datahandler: Buffered 81 bytes
icmp_readahead: Received 64 bytes (of 81)
56 bytes from 192.168.0.1: icmp_seq=8 time=40.0 ms
sendto_eventhandler: flags: 4000
sendto_eventhandler: Send ICMP request
sendto_request: Outgoing ICMP packet length: 84 (84)
sendto_eventhandler: Resuming
enc_txpoll: Poll result: d_len=84
enc_transmit: Sending packet, pktlen: 98
enc_irqworker: EIR: 08
enc_txpoll: Poll result: d_len=0
enc_irqworker: EPKTCNT: 01
enc_pktif: Receiving packet, nextpkt: 0458 pktlen: 102 rxstat: 00c0
enc_rxdispatch: IPv4 frame
icmp_poll_eventhandler: flags: 0002
icmp_datahandler: Buffered 81 bytes
icmp_readahead: Received 64 bytes (of 81)
56 bytes from 192.168.0.1: icmp_seq=9 time=40.0 ms
10 packets transmitted, 9 received, 10% packet loss, time 10110 ms
rtt min/avg/max/mdev = 40.000/40.000/40.000/0.000 ms
nsh>

Testing SX127x on NuttX

I’m testing the TTGO_LORA32 board (sch here: https://raw.githubusercontent.com/LilyGO/TTGO-LORA32/master/schematic1in6.pdf) with NuttX RTOS and noticed the `sx127x` app is not working with default LoRa Modulation, but at least I got it working with FSK modulation:

$ ./tools/configure.sh ttgo_lora_esp32:sx127x

$ make -j flash ESPTOOL_PORT=/dev/ttyUSB0

Board 1:

NuttShell (NSH) NuttX-10.4.0                                                    
nsh> sx127x -m 1 -t                                                             
Start sx127x_demo                                                               
FSK modulation                                                                  
Set frequency to 868000000                                                      
Set power to 14

Board 2:

nsh> sx127x -m 1
Start sx127x_demo
FSK modulation
Set frequency to 868000000
Set power to 14
Waiting for data

Received:
SNR  = 0
RSSI = -66
len  = 5
0x00 0x01 0x02 0x03 0x04 

wait 5 sec ...

Update:

I discovered an interesting fact (that at least happens for TTGO_LORA32 board) :
If CONFIG_LPWAN_SX127X_MODULATION_DEFAULT=3 the sx127x app doesn’t work on LoRa mode (-m 0), but works on FSK mode (-m 1). If CONFIG_LPWAN_SX127X_MODULATION_DEFAULT=2 the app will work fine for LoRa and FSK mode, but not for OOK. If CONFIG_LPWAN_SX127X_MODULATION_DEFAULT=1 none mode will work.

NuttX Binary to Test Particle Photon board

A NuttX user reported an issue when using Particle Photon board: https://github.com/apache/incubator-nuttx/issues/6938

Then I decided to test it and discovered that some recent modification damaged that board configuration and decided to test an older version that I knew was working.

I converted my nuttx.bin to text (using base64) and created a gist with it. Then you can test yourself:

Download “nuttx_base64.txt”: https://gist.github.com/acassis/4479c13e029415cd05a4b52493f1da52

$ cat nuttx_base64.txt | base64 --decode > nuttx.bin

Confirm the file was created correctly:

$ md5sum nuttx.bin
56f9b321ca946f092e89f42723a0cea3 nuttx.bin

Press the RESET and SETUP buttons of your board, release the RESET and keep SETUP pressed until the LED start blinking on yellow color, then release it as well.

Now that your board is in DFU mode you can flash it using DFU command:

$ sudo dfu-util -d 2b04:d006 -a 0 -s 0x08020000 -D nuttx.bin

We will need a router configured with SSID: DLINK and password: dlinkphoto to test this firmware. It will connected on your board and will assume the fixed IP 192.168.0.16. You can telnet to this IP and get the NSH terminal working over telnet.