As mentioned in earlier sections, Linux based ESP-Hosted solution supports Raspberry-Pi as a MCU host. It is fairly easy to use this solution on other Linux MCU platforms, but there are few parts of the solution that are tied to Raspberry-Pi. This document identifies such dependencies. One should take care of these dependencies while porting to other Linux platforms.
- Please make sure to use exact power adapter and correct power cable which is expected by your platform
- If the power is not enough, the peripherals might not work or underperform
When you are opting microprocessor with Linux other than Raspberry, hardware peripherals and GPIO functions would need changes. GPIO pins for UART, SPI and SDIO would differ.
- ResetPin GPIO
- You need to choose any unused GPIO for reseting ESP and configure in your SoC's Device Tree Config
- Peripheral GPIOs
- Check the pincontrol device tree blobs and verify if the correct GPIOs are in place for your expected SDIO hardware instance.
- SDIO GPIOs
- You may need to change connections from ESP to mapping pins for
SDIO_CLK
,SDIO_CMD
,SDIO_DAT0
,SDIO_DAT1
,SDIO_DAT2
andSDIO_DAT3
from your SoC's Device Tree Pin Control.
- You may need to change connections from ESP to mapping pins for
- SPI GPIOs
- You may need to change connections from ESP to mapping pins for
SPI_ChipSelect
,SPI_CLK
,SPI_MISO
,SPI_MOSI
from your SoC's Device Tree Pin Control. - Additionally you need another two unused GPIOs for
SPI_Handshake
andSPI_DataReady
new pins to be defined in your DeviceTree
- You may need to change connections from ESP to mapping pins for
- Changing GPIOs
- SPI GPIOs
- MISO, MOSI, CLK & CS are mapped to IO_MUX. They allowed to be changed with little overhead of GPIO Matrix routing.
- Data Ready & Handshake could be chosed from any free GPIOs
- SDIO GPIOs
- Non changeable
- UART GPIOs
- 4 pin uart is suggested to use and all pins are configurable for ESP32/ESP32-C3/S3
- 2 pin uart is available in ESP32-C2/C6. All pins configurable.
- From 4 pin to 2 pin solution is possible by disabling hardware flow control at slave (& host).
- SPI GPIOs
- SPI or UART peripherals
- Chip Select is suggested to be externally pulled
- SDIO peripheral
- In general, For Most of ESP32 boards, additional external pull-up of at least 10k Ohm resistor will be required for pins CMD and DATA(DAT0-DAT3) lines.
- In our PCB we use 51k Ohm pull-ups
- Please go through a detailed document which details pull-up requirement depending upon your ESP chipset. In top left, choose your expected target ESP chipset from combo box.
- Device Tree (DT) and dtoverlay are way to express hardware and hardware configurations of them. While porting, Need to focus how configurations for UART, SPI and SDIO are translated for your device.
- Please note that every Linux platform or Soc vary in terms of device instances, their configurations. You might want to check the datasheet and GPIOs supported for the expected peripherals to be used.
- Please spare some time and Cross-check the parameters for peripherals, for example min or max frequncy of peripheral, peripheral config wrt timing phases of SPI protocol
- For SDIO, We suggest
broken-cd;
argument to be added/enabled DT which allows the ESP chipset hot-pluggable - Please understand all the SoCs have different drivers and do not exactly follow one rule to make them work. Host Device Tree is user's responsibility to configure
- ESP-Hosted expects/assumes the platform with correct Device Tree or configuration is up. Although we try to help, but unfortunately, most of the bugs we received generally end up in host platform issues, which are in fact not ESP-Hosted software bugs.
- Power your Linux SoC with a correct adapter, which confirms the expected power rating.
- If correct power rated adapters are not used, the peripherals may poorly perform or may not work at all.
- ESP can be powered with microUSB/USB-C cables from your computer.
Driver underlies heavily over underlying kernel. ESP-Hosted is tested over Linux kernel version 4.19.X, although it should work on lower versions as well.
- HCI in older kernel versions
- HCI had compiled, but not tested for kernel version 3.18.16. Please refer esp_bt_api.h for details.
- In Linux kernel, BT over SPI i.e. symbol HCI_SPI is supported over kernel version 4.7.0. Please refer esp_bt.c. Ideally there should be no change required here.
- rpi_init.sh is utility script to load the ESP kernel module
- You can rename script as per your convenience, although it needs to be ported for kernel module building
- Reset Pin
- Reset pin could be chosen over unused GPIO.
- Input parameter to script,
resetpin=X
to be changed accordingly. This is used to reset ESP on loading the kernel module.
- Note: See Section 2.4.1 for changes in Raspberry Pi OS GPIO mappings.
- UART configuration
bt_init()
listsraspi-gpio
commands.rapi-gpio
are simple utilities used to configure GPIO pins for their levels, alternate functions and pull up values.- As per Raspberry Pi documentation, these UART pins are configured.
- These pins and any other peripheral pins which are not already taken care in their drivers, need to be configured.
- spidev_disabler
- This is applicable for SPI peripheral configuration and explained in next section.
- Kernel Module
- Within rpi_init.sh, make command used is Raspberry Pi specific. Following tags in
make
command should be changed as per platform
- CROSS_COMPILE - This to be point to toolchain path. For arm example, it should point till
<Toolchain-Path>/bin/arm-linux-gnueabihf-
- KERNEL - Place where kernel is checked out and built
- ARCH - Expected architecture
- For example, For architecture
arm64
, toolchain checked out at/home/user1/arm64_toolchain/
and kernel source built at/home/user1/arm64_kernel/
, cross compilation commands should look like,
- Within rpi_init.sh, make command used is Raspberry Pi specific. Following tags in
make target=$IF_TYPE \
ARCH=arm64 \
CROSS_COMPILE=/home/user1/arm64_toolchain/bin/aarch64-linux-gnu- \
KERNEL=/home/user1/arm64_kernel
target
may take have value, spi
or sdio
. It defaults to sdio
if not provided.
* Less likely, but if you are running 64-bit kernel on 32-bit OS, you may face building issues. Please check this for resolution
- C control path test application
Test application is located athost/linux/host_control/c_support
. If application built within target, there is no need for cross compilation and simplemake
is sufficient. To cross-copile from host, below additional option to be used- CROSS_COMPILE - This point to toolchain path
For example, For if toolchain checked out at /home/user1/arm64_toolchain/
, make command should look like,
make CROSS_COMPILE=/home/user1/arm64_toolchain/bin/aarch64-linux-gnu-
The GPIO numbering for Raspberry Pi OS has changed since 2024. See this for more info.
To discover the current GPIO mapping, do cat /sys/kernel/debug/gpio
. You will see lines similar to this:
gpiochip0: GPIOs 512-569, parent: platform/fe200000.gpio, pinctrl-bcm2711:
gpio-512 (ID_SDA )
gpio-513 (ID_SCL )
gpio-514 (GPIO2 )
gpio-515 (GPIO3 )
gpio-516 (GPIO4 )
gpio-517 (GPIO5 )
gpio-518 (GPIO6 )
Function | Old GPIO | New GPIO |
---|---|---|
Reset | 6 | 518 |
SPI Handshake | 22 | 534 |
SPI Data Ready | 27 | 539 |
-
Verify user space SPI driver
- If the user space drivers like spidev works as expected in Tx & Rx, then we would be assured that the SPI Linux drivers for your SoCs are working fine & SPI bus is correctly configured
-
Disable default SPI driver
- Linux kernel has a default SPI controller driver which needs to be disabled in order to make esp32_spi module work. Please see following code snippet from rpi_init.sh script
# Disable default spidev driver dtc spidev_disabler.dts -O dtb > spidev_disabler.dtbo sudo dtoverlay -d . spidev_disabler
- While porting, equivalent commands or steps need to be run to disable default SPI driver through the Device Tree for expected SoC.
-
Verify disabling of spidev
- Default spidev when not disabled, create a device file, /dev/spidevX.Y where X refers SPI bus and Y refers to Chip Select to be used.
- For example, Say User disables SPI bus 1 and Chip select 0 through Device Tree, then verify after loading Device Tree changes, /dev/spidev1.0 is no more listed
-
Additional GPIOs
- Apart from regular MOSI, MISO, CLK and Chip select, there are two additional GPIO pins used for SPI implementation.
- These pins should be selected such that they would not interfere other any peripheral work.
- Alter
HANDSHAKE_PIN
andSPI_DATA_READY_PIN
in esp_spi.h. - Note: See Section 2.4.1 for changes in Raspberry Pi OS GPIO mappings.
- Additional pins functionality details mentioned in 1.1.1 additional pin setup of spi protocol documentation.
-
cs_change
- Reason why this setting was enabled is, SPI transfer was loosing first byte in transfer. Although this issue is only observed while testing with Raspberry Pi. Enabling cs_change=1 makes CS always de-assert after each transfer request. While porting, you may want to remove line,
trans.cs_change = 1;
.
- Reason why this setting was enabled is, SPI transfer was loosing first byte in transfer. Although this issue is only observed while testing with Raspberry Pi. Enabling cs_change=1 makes CS always de-assert after each transfer request. While porting, you may want to remove line,
-
Tune the SPI slave clock
- Maximum SPI slave clock supported by ESP chipsets are:
- ESP32 : 10MHZ
- ESP32-S2: 40MHz
- ESP32-C2: 60MHz
- ESP32-C3: 60MHz
- ESP32-S3: 60MHz
- Above frequencies cannot be used while using Raspberry Pi as SPI master because of its limitation.
However, you can increase the SPI clock stepwise to see what maximum frequency works for your SoC. - Higher the frequency set, better the throughput would be.
- SPI clock frequency could be changed from macro
SPI_CLK_MHZ
inesp/esp_driver/network_adapter/main/spi_slave_api.c
- Maximum SPI slave clock supported by ESP chipsets are:
-
Identify peripheral limitations
- For Raspberry Pi, add this line to
/etc/default/cpu_governor
as mentioned in SPI setupCPU_DEFAULT_GOVERNOR="performance"
- Raspberry Pi could not perform reliably when the SPI clock was set higher frequency than 30MHz
- Any such limitation for your Soc should be checked. Also power saving modes and peripheral clocks for your platform should be known.
- For Raspberry Pi, add this line to
-
SPI Bus instance and Chip select number
- Default value for both is 0, i.e. SPI0 and chip select 0.
- It could be changed using variables,
esp_board.bus_num
andesp_board.chip_select
in functionspi_dev_init()
from filehost/linux/host_driver/esp32/spi/esp_spi.c
-
SPI mode
- Refrain from using SPI mode 0 at Slave side (no limitation at host for this as such)
- If the correct software settings are loaded, you can expect first event received from ESP to Host in dmesg
- If first event is not received, you can change SPI mode at both ESP and Host to other values, lower SPI freq and retry
-
SPI interrupt handlers
- If even after porting only first event received and nothing works ahead, you can suspect the GPIOs
Handshake
andDataReady
not correctly configured as Interrupts. - Try to add log
printk(KERN_ERR "%s\n",__func__);
inspi_data_ready_interrupt_handler()
andspi_interrupt_handler()
functions if the interrupts are hit by assessing dmesg log
- If even after porting only first event received and nothing works ahead, you can suspect the GPIOs
User verified things like:
- Reset Pin
- On host reload of driver, ESP is reseting
- Data_Ready / Handshake
- Debug logs in ISR are getting printed on manual logic change on GPIOs
- spidev is correctly disabled
- host driver is able to claim the spi bus on expected chip select
- Shorten the jumper wires
- Try to use all jumper wires of smaller than 6cm and all jumper wires be of same length.
- SPI frequency
- Lower the frequency to 1MHz
- SPI modes
- Try different SPI modes like SPI mode 1/2/3 (Make sure, both ESP & Host have both have same changed SPI mode in one testing).
Despite all above trials, the ESP-Hosted fail to get first INIT event from ESP to Host OR
only first event is received and fails to work after that
you can suspect SPI timings mismatch. In such case, tuning might be required
Tuning of SPI timing
is a one time activity for any ESP<->Host setup.- Please refer to SPI timing considerations. Scroll to top, Change your ESP chipset from first combobox for timing consideration for your ESP chipset.
- It is possible that the timings of the sampling and the MISO or MOSI transitions are not aligned within time limit. To correct timings:
- It is always recommended to check the SPI timings on any Logic analyzer. This way timings could be understood accurately.
- To adjust timing, Go to IDF setup (esp_hosted_fg/esp/esp_driver/esp-idf), in file components/hal/<esp_chipset>/include/hal/spi_ll.h, locate function, spi_ll_slave_set_mode()
- In your currently configured SPI mode, tweak values of
ck_idle_edge
,ck_i_edge
,miso_delay_mode
,miso_delay_num
,mosi_delay_mode
andmosi_delay_num
and retry on every change
- In your currently configured SPI mode, tweak values of
- Set different SPI modes at Slave and Host and test again
- File: esp/esp_driver/network_adapter/main/sdio_slave_api.c
- If first event is not received at SDIO, you can tune
SDIO Timing
- SDIO driver timing could be tuned from ESP slave code
Function
sdio_init()
->sdio_slave_config_t config
->timing
structure element. this can be changed toSDIO_SLAVE_TIMING_NSEND_PSAMPLE
or other values to adjust sdio timing.
- SDIO driver timing could be tuned from ESP slave code
Function
- For higher SDIO frequencies to be enabled, you can remove line
config.flags |= SDIO_SLAVE_FLAG_DEFAULT_SPEED;
-
Raw throughput testing
- To test the transport is correctly ported and working fine, please run Raw throughput tests in
ESP-> Host
andHost->ESP
direction. - Reboot/Reset both ESP and Host on raw throughput direction change
- In this testing, frames are pumped continously and throughput at transport is measured.
- Reasonable speed in comparison to the Clock used should be deduced (no standard figure)
- If the speed is very less, this could mean that the transport is not correctly ported
- To test the transport is correctly ported and working fine, please run Raw throughput tests in
-
Verify you loaded correct software
- Sometimes a silly mistake could happen that we load inconsistent drivers at ESP and Linux.
- For example, SDIO firmware loaded at ESP and running SPI ESP kernel module at Linux, will simply fail to work
- Sometimes a silly mistake could happen that we load inconsistent drivers at ESP and Linux.
-
Troubleshoot guide
- Check some common known issues in Troubleshoot guide
- While porting host from Raspberry-Pi, There should be no changes ESP side. But, it is better to keep in mind the expected peripheral counterpart, their GPIOs used in ESP and their configurations.
- Getting Linux platform up and running, Getting the peripherals working for your specific platform is out of scope for ESP-Hosted project. Why? The problem is that, every Linux platform has its own drivers and own way of device configurations.
- Porting sometimes can take very less time and tireless but sometimes a time consuming process.
- Finally, We would be happy know how your board was ported. Please open an issue for this with starting string 'porting done: ' This would be tremendous help for someone who is using your platform.
Please feel free to reach us at https://github.com/espressif/esp-hosted/issues in case of issues.