Tracing thru #NuttX Virtual File System ... We see that ioctl() maps the File Descriptor to a File Struct
https://github.com/lupyuen/incubator-nuttx/blob/master/fs/vfs/fs_ioctl.c#L118-L138
#NuttX File Struct contains a Private Pointer to the SPI Driver "spi_driver_s"
https://github.com/lupyuen/incubator-nuttx/blob/master/drivers/spi/spi_driver.c#L112-L147
#NuttX SPI Driver "spi_driver_s" contains the SPI Device "spi_dev_s" ... That we need for testing the SPI Interface! But the SPI Device is private and hidden from apps 🙁
https://github.com/lupyuen/incubator-nuttx/blob/master/drivers/spi/spi_driver.c#L55-L65
Instead we copy an existing #NuttX SPI Device Driver to test the SPI Interface ... We pick the simplest smallest SPI Device Driver: dat-31r5-sp
https://docs.google.com/spreadsheets/d/1MDps5cPe7tIgCL1Cz98iVccJAUJq1lgctpKgg9OwztI/edit#gid=0
We create a new #NuttX SPI Device Driver ... By copying "dat-31r5-sp.c" to "spi_test_driver.c"
https://github.com/lupyuen/incubator-nuttx/blob/newdriver/drivers/rf/spi_test_driver.c
In our SPI Test Driver: Change all "dat31r5sp" to "spi_test_driver" ... Remember to Preserve Case!
https://github.com/lupyuen/incubator-nuttx/commit/8fee69215163180b77dc9d5b9e7449ebe00ac1cc
Do the same to create the Header File for our #NuttX Driver: spi_test_driver.h
https://github.com/lupyuen/incubator-nuttx/blob/newdriver/include/nuttx/rf/spi_test_driver.h
Add our SPI Test Driver to #NuttX Kconfig
https://github.com/lupyuen/incubator-nuttx/blob/newdriver/drivers/rf/Kconfig#L22-L27
Our SPI Test Driver for #NuttX appears in "make menuconfig"!
https://github.com/lupyuen/incubator-nuttx/blob/newdriver/drivers/rf/Kconfig#L22-L27
Remember to enable "SPI0" and "SPI Character Driver" in #NuttX ... Or our SPI Test Driver won't start
https://github.com/lupyuen/incubator-nuttx/blob/newdriver/drivers/rf/spi_test_driver.c
Here's what happens when we make a boo-boo and #NuttX won't start
https://gist.github.com/lupyuen/ccfd90125f9a180b4cfb459e8a57b323
Update the Makefile "Make.defs" ... So that #NuttX will build our SPI Test Driver
https://github.com/lupyuen/incubator-nuttx/blob/newdriver/drivers/rf/Make.defs#L33-L37
Build, flash and run #NuttX ... Our SPI Test Driver appears as "/dev/spitest0"! 🎉
https://github.com/lupyuen/incubator-nuttx/blob/newdriver/drivers/rf/spi_test_driver.c
Back to our #NuttX SPI Test App ... Here's how we open the SPI Test Driver and write data
https://github.com/lupyuen/incubator-nuttx-apps/blob/spi_test/examples/spi_test/spi_test_main.c
This appears when we run our #NuttX SPI Test App ... Let's study our SPI Test Driver
https://github.com/lupyuen/incubator-nuttx-apps/blob/spi_test/examples/spi_test/spi_test_main.c
Every #NuttX Device Driver defines the File Operations for the device ... Here are the open(), close(), read(), write() and ioctl() operations for our SPI Test Driver
https://github.com/lupyuen/incubator-nuttx/blob/spi_test/drivers/rf/spi_test_driver.c#L80-L89
In the write() operation for our #NuttX SPI Test Driver, we 1️⃣ Lock the SPI Bus 2️⃣ Config the SPI Interface 3️⃣ Select the SPI Device 4️⃣ Transfer SPI Data 5️⃣ Deselect and Unlock
https://github.com/lupyuen/incubator-nuttx/blob/spi_test/drivers/rf/spi_test_driver.c#L182-L239
Here's how we configure the #NuttX SPI Interface
https://github.com/lupyuen/incubator-nuttx/blob/spi_test/drivers/rf/spi_test_driver.c#L95-L117
To watch what happens inside #NuttX's SPI Driver for #BL602 ... Turn on SPI Debug Logging
https://github.com/lupyuen/incubator-nuttx/blob/spi_test/arch/risc-v/src/bl602/bl602_spi.c
Now we see every byte transferred by #NuttX's SPI Driver for #BL602!
https://github.com/lupyuen/incubator-nuttx/blob/spi_test/drivers/rf/spi_test_driver.c
How to verify the #NuttX SPI Output? We sniff the #BL602 SPI Bus with a Logic Analyser
https://lupyuen.github.io/articles/spi#appendix-troubleshoot-bl602-spi-with-logic-analyser
#NuttX's SPI Pins match the #BL602 Reference Manual: MOSI = GPIO 1, MISO = GPIO 0 ... But we're about to witness a BL602 SPI Quirk
https://github.com/bouffalolab/bl_docs/tree/main/BL602_RM/en
Logic Analyser connected to #BL602 shows that MISO and MOSI are swapped! This happens in BL602 IoT SDK ... Also in #NuttX!
https://lupyuen.github.io/articles/spi#spi-data-pins-are-flipped
We can swap MISO and MOSI on #BL602 by setting a Hardware Register ... Let's do this on #NuttX
https://lupyuen.github.io/articles/pinedio#spi-pins-are-swapped
Let's test #NuttX SPI with #BL602 and Semtech SX1262 LoRa Transceiver
https://www.semtech.com/products/wireless-rf/lora-core/sx1262
We implement the Read Operation for our #NuttX SPI Driver ... So that we can fetch the SPI Response from SX1262
https://github.com/lupyuen/incubator-nuttx/blob/spi_test/drivers/rf/spi_test_driver.c#L210-L233
Our #NuttX App transmits an SPI Command to SX1262 ... And reads the SPI Response from SX1262
#BL602 SPI Chip Select has a problem ... It goes High after EVERY byte ... Which is no-no for SX1262 ... Solution: We control Chip Select via GPIO
For #NuttX on #BL602, we use SPI Mode 1 instead of Mode 0 ... To work around the SPI Mode Quirk
https://github.com/lupyuen/incubator-nuttx/blob/spi_test/drivers/rf/spi_test_driver.c#L51-L57
Our #NuttX App now reads the SX1262 Register correctly! 🎉
https://github.com/lupyuen/incubator-nuttx-apps/blob/spi_test/examples/spi_test2/spi_test2_main.c
Our #NuttX App runs OK on PineDio Stack BL604 with onboard SX1262! 🎉
https://github.com/lupyuen/incubator-nuttx-apps/blob/spi_test/examples/spi_test2/spi_test2_main.c
How we transmit and receive data over SPI on Apache #NuttX OS ... And what's inside the SPI Driver ... All shall be explained here
To test the #NuttX SPI Functions, we create an App and a Device Driver
https://lupyuen.github.io/articles/spi2?3#spi-test-app-and-driver
#NuttX Apps can't call the SPI Driver directly ... Here's why
https://lupyuen.github.io/articles/spi2?3#spi-test-app-and-driver
Here's how we create a #NuttX App
https://lupyuen.github.io/articles/spi2?4#appendix-create-a-nuttx-app
How we create a Device Driver in #NuttX ... The copy-n-paste way
https://lupyuen.github.io/articles/spi2?5#appendix-create-a-nuttx-device-driver
During #NuttX Startup, we register our Device Driver
https://lupyuen.github.io/articles/spi2?8#register-device-driver
Our Custom Device Driver appears as "/dev/spitest0" in #NuttX
https://lupyuen.github.io/articles/spi2?9#verify-device-driver
Why we chose to clone the "dat-31r5-sp" driver in #NuttX ... Yep we did a Quantitative Analysis of NuttX Drivers!
https://lupyuen.github.io/articles/spi2?10#verify-device-driver
What's inside our SPI Test Driver for #NuttX
https://lupyuen.github.io/articles/spi2?11#inside-the-spi-test-driver
Every #NuttX Device Driver defines a list of File Operations ... Here are the operations for our SPI Test Driver
Here's how we load our SPI Test Driver in #NuttX
https://lupyuen.github.io/articles/spi2?18#load-the-spi-test-driver
Checking that our SPI Test Driver has been loaded in #NuttX
https://lupyuen.github.io/articles/spi2?19#load-the-spi-test-driver
Here are the #NuttX Pin Definitions for PineDio Stack BL604 with onboard SX1262 ... As derived from the schematic
https://github.com/lupyuen/incubator-nuttx/blob/pinedio/boards/risc-v/bl602/bl602evb/include/board.h#L42-L95