How to run NuttX on Freedom Board FRDM-K64F

NuttX has support to Freedom K64F and the README file (see nuttx/configs/freedom-k64f/README.txt) give much information about things it supports.

After plugging it on my computer (connected to SDA USB connector) I saw these messages after running dmesg:

$ dmesg
[  194.521661] usb 3-3: new full-speed USB device number 3 using xhci_hcd
[ 194.671658] usb 3-3: New USB device found, idVendor=0d28, idProduct=0204
[ 194.671663] usb 3-3: New USB device strings: Mfr=1, Product=2, SerialNumber=3
[ 194.671667] usb 3-3: Product: MBED CMSIS-DAP
[ 194.671670] usb 3-3: Manufacturer: MBED
[ 194.671672] usb 3-3: SerialNumber: 024002015928CE6CA4DXXXXXX
[ 194.674782] hid-generic 0003:0D28:0204.0005: hiddev0,hidraw4: USB HID v1.00 Device [MBED MBED CMSIS-DAP] on usb-0000:00:14.0-3/input3
[ 194.744180] cdc_acm 3-3:1.1: ttyACM0: USB ACM device
[ 194.744627] usbcore: registered new interface driver cdc_acm
[ 194.744629] cdc_acm: USB Abstract Control Model driver for USB modems and ISDN adapters
[ 194.765883] usb-storage 3-3:1.0: USB Mass Storage device detected
[ 194.766177] scsi host6: usb-storage 3-3:1.0
[ 194.766444] usbcore: registered new interface driver usb-storage
[ 194.783993] usbcore: registered new interface driver uas
[ 195.794345] scsi 6:0:0:0: Direct-Access MBED microcontroller 1.0 PQ: 0 ANSI: 2
[ 195.795065] sd 6:0:0:0: Attached scsi generic sg2 type 0
[ 195.795296] sd 6:0:0:0: [sdb] 2096 512-byte logical blocks: (1.07 MB/1.02 MiB)
[ 195.795482] sd 6:0:0:0: [sdb] Write Protect is off
[ 195.795486] sd 6:0:0:0: [sdb] Mode Sense: 03 00 00 00
[ 195.795666] sd 6:0:0:0: [sdb] No Caching mode page found
[ 195.795674] sd 6:0:0:0: [sdb] Assuming drive cache: write through
[ 195.803484] sdb:
[ 195.804512] sd 6:0:0:0: [sdb] Attached SCSI removable disk

Also the MBED partition appeared on nautilus file explorer with mbed.htm file on it.

So it is show time:

$ cd nuttxspace/nuttx
$ make distclean
$ ./tools/configure.sh freedom-k64f/nsh
$ make menuconfig
Build Setup --->
Build Host Platform (Linux) --->

wow, nice it was already configured to Linux!

Binary Output Formats  --->
  [*] Raw binary format

But the Raw binary format wasn’t selected.

Leave and save and then run the magical compilation command:

$ make

I had not luck flashing the firmware nuttx.bin just dropping it on MBED partition. Also using the OpenSDA firmware with OpenOCD to flash didn’t work! Fortunately you can use the Segger Jlink firmware “J-Link OpenSDA – Board-Specific Firmwares”:

https://www.segger.com/downloads/jlink#JLinkOpenSDABoardSpecificFirmwares

With the board powered-off press and hold the reset button (RESET SW1) and connect the USB cable to the computer. When the BOOTLOADER directory appear on your file explorer drop the 02_OpenSDA_FRDM-K64F.bin there!

Reset the board, install the Jlink software tool for Linux and run:

$ JLinkExe -if SWD -device MK64FN1M0xxx12

SEGGER J-Link Commander V6.40 (Compiled Oct 26 2018 15:08:38)
DLL version V6.40, compiled Oct 26 2018 15:08:28

Connecting to J-Link via USB…O.K.
Firmware: J-Link OpenSDA 2 compiled Oct 10 2018 16:29:19
Hardware version: V1.00
S/N: 621000000
VTref=3.300V

Type "connect" to establish a target connection, '?' for help
J-Link>connect
Specify target interface speed [kHz]. : 4000 kHz
Speed> 4000
Device "MK64FN1M0XXX12" selected.

Connecting to target via SWD
InitTarget()
Found SW-DP with ID 0x2BA01477
Scanning AP map to find all available APs
AP[2]: Stopped AP scan as end of AP map has been reached
AP[0]: AHB-AP (IDR: 0x24770011)
AP[1]: JTAG-AP (IDR: 0x001C0000)
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
ROMTbl[0][6]: E0042000, CID: B105900D, PID: 003BB907 ETB
ROMTbl[0][7]: E0043000, CID: B105900D, PID: 001BB908 CSTF
Cortex-M4 identified.

J-Link>loadbin ./nuttx.bin 0

Downloading file [./nuttx.bin]…
Comparing flash [100%] Done.
Erasing flash [100%] Done.
Programming flash [100%] Done.
Verifying flash [100%] Done.
J-Link: Flash download: Bank 0 @ 0x00000000: 1 range affected (81920 bytes)
J-Link: Flash download: Total time needed: 1.024s (Prepare: 0.043s, Compare: 0.013s, Erase: 0.024s, Program: 0.930s, Verify: 0.005s, Restore: 0.007s)
O.K.

J-Link> exit

The RGB LED will turn on in Green color

How to use a JLX1602G-390 display with NuttX

I just created a driver for NuttX to use JLX1602G-390 display.

This display is based on Siatronix ST7032i the I2C version.

First you need to wire it connecting an external capacitor and a resistor as explained on this schematic:

I am using the STM32F4Discovery board with this display connecting pins PB6 to SCL and PB9 to SDA. These pins are configured to enable an internal pull-up resistor, but case your microcontroller doesn’t have it, you need to connect external pull-up 4k7 resistors to SCL and SDA pins.

After configuring the NuttX to use this display, you can execute the slcd command from NuttShell:

nsh> slcd
Opening /dev/disp0 for read/write access
Attributes:
  rows: 2 columns: 16 nbars: 0
  max contrast: 0 max brightness: 1
Clear screen
WRITING:
0000: 1b5b46                                                            .[F 
Set brightness to 1
Print [Hello World NuttX]
WRITING:
0000: 48656c6c6f20576f726c64204e757474 58                               Hello World Nutt X
Test complete
nsh> 

You can see the step-by-step video tutorial here:

Source of this schematic: https://bitbucket.org/ospringauf/mecanumrover/wiki/JLX1602G-390

Sheding some (infrared) light on MLX90614

After implementing the MLX90614 driver for NuttX I noticed that although the write command to change the device I2C address in the EEPROM was reporting success, after the power cycle the new address was not working. Worst: even the previous address was not working.

Basically the device appears damaged and didn’t respond to any I2C command.

Then doing my research I discovered a Melexis document about SMBus communication:

https://www.pololu.com/file/0J171/MLX90614_SMBus.pdf

In this document I noticed they are using the address 0x00 instead of the default 0x5a address. After modifying the driver to use the 0x00 address the device accepted the new command.

There are many discussing about this subject on Arduino and similar forum:

https://chrisramsay.co.uk/posts/2014/09/arduino-and-multiple-mlx90614-sensors/
http://forum.arduino.cc/index.php?topic=54170.msg539601#msg539601
https://forum.mikroe.com/viewtopic.php?f=178&t=67842
http://wiki.wiring.co/wiki/Connecting_Infrared_Thermometer_MLX90614_to_Wiring

Note that someone discovered that using a brute force CRC approach eventually will work and everybody decided to copy it. Too bad guys!

The MLX90614 uses CRC8-CCITT standard to check if data are correct, so any CRC8-CCITT implementation will work, for example this one: https://3dbrew.org/wiki/CRC-8-CCITT

Now on NuttX you can call the mlx90614 example application to change the device’s I2C address this way: (changing from default 0x5a to 0x3a)

nsh> mlx90614 0x3a
Address 0x3a stored on your device!
Please do a power cycle and update the I2C board address!
nsh>

Checking the CRC-8 PEC byte of MLX90614

I am creating a NuttX device driver for Melexis MLX90614 and it is a nice adventure.

First I downloaded the adafruit lib and tested it on Arduino Uno just to confirm the sensor was working, but I didn’t look the source code because I always prefer to read the datasheet and implement the driver from scratch.

All things fine, the mlxtest example worked correctly and I got the ambient temperature and the object temperature printed correctly.

Then I created the driver and decided to test it on STM32F103, but discovered that I2C_TRANSFER() for STM32F103 is broken. No problem, let to test it on STM32F4Discovery board:

nsh> dd if=/dev/thermo0 of=/dev/null bs=2 count=1
mlx90614_read_word: value[0]: 0xDF | value[1]: 0x3A | value[2]: 0xCF | ret: 0

Let see in the logic analyzer to confirm:

Very good! But how to check if CRC-8 PEC field (third received byte: 0xCF) is correct?

I found this nice online CRC calculator:

http://www.sunshine2k.de/coding/javascript/crc/crc_js.html

But putting all values as suggested in the datasheet didn’t work:

0x5A 0x06 0x5A 0xDF 0x3A
Result CRC value: 0x2F

Then just web searching for: MLX90614 PEC CRC-8 example

Returned me this thread:

https://stackoverflow.com/questions/20554869/implementing-crc8-on-arduino-to-write-to-mlx90614

The “thb” guy saved me:

“I haven’t checked your CRC implementation but there is a mistake in the MLX datasheet or at least it’s badly written. You have to include all the I2C frame’s data for the PEC’s calculation not just the replied data. For a read word command you have to include [SA_W, Command, SA_R, LSB, MSB] and for a write word command [SA_W, Command, LSB, MSB]. So, for their first example the calculation must be made on [ 0xB4, 0x07, 0xB5, 0xD2, 0x3A ] and not just on [ 0xD2, 0x3A ] and this way you get the expected 0x30.”

What this guy is saying is: we need to include all the bits of the Slave Address, the address needs to be seen as 8-bit including the the less significant bit Write or Read. So I2C Write at address 0x5A is seen as 0xB4 and I2C Read is seen as 0xB5 (pay attention at bits over the “5A” in the logic analyzer image above).

So, let to try his idea:

0xB4 0x06 0xB5 0xDF 0x3A
Result CRC value: 0xCF

Bingo!

Using coroutine on Lua

The Lua documentation about coroutine is not much clear and the example is not much useful. Fortunately I found an explanation how to use it and simplify the idea here:

sleep_awhile = function (period)
        os.execute("sleep "..period)
        end

func_a = function()
        nnew = 0
        while true do
           nnew = nnew + 1
           print ("func_a ", nnew)
           coroutine.yield(nnew)
           print ("AGAIN ...")
        end
end

func_b = function()
        count = 0
        while true do
           count = count + 1
           print ("func_b ", count)
           coroutine.yield()
        end
end

-- ======= Main code =============

cor_a = coroutine.create(func_a)
cor_b = coroutine.create(func_b)

while true do
        itdidit,newcount = coroutine.resume(cor_a)
        sleep_awhile(1)
        print (newcount)
        itdidit = coroutine.resume(cor_b)
end

I hope it be useful for you too.

Source: http://www.wellho.net/resources/ex.php4?item=u114/ff2.lua