SPI slave select deassert callback

I am starting a new project that uses the RTL8720CM SoC and the goal is for it to be used as a SPI slave device. Because the master will be a low end MCU with not as much RAM (compared to RTL8720CM) to work with it will be performing variable byte length SPI transactions. I need to know when the SPI transaction is completed. Most MCUs I have worked with provide such an event by a chip/salve select (CS / SS) inactive/deassert interrupt.

I am not seeing a SPI slave SS deassert event callback in the ambz2_sdk’s SPI library. I only see spi_irq_hook() and spi_bus_tx_done_irq_hook() callback register functions are provided but neither cause my handler function to be called upon SPI SS deassert. Only when DMA buffers are empty (transmit) or full (receive) for former and looks like SPI transmit FIFO is empty for the latter.

It does look like there is SPI slave deassert interrupt as described by the memory mapped register definition structure SSI0_Type but apparently not used by the SPI library. And unfortunately there does not appear to be a way to install my own SSI/SPI interrupt service routine so I can handle the SSI0_Type.isr_b.ssris interrupt on my own in order to workaround the current SPI library limitations.

I looked through the ambd_sdk and come to find out it offers two APIs for working with the peripheral controllers. One the same mbed API that Ameba ZII SDK offers and a raw API. Raw SPI is exactly what I could use to resolve the issue, but unfortunately raw API does not appear to be available in the Ameba ZII SDK. :frowning:

Alternatively I have looked into using the GPIO external interrupt hook to get SPI slave deassert. However the gpio_irq API refuses to operate with the pin when it is already assigned for SPI CS. Even though all other SoC and MCUs I have worked with (ARM9, Cortex-M, Blackfin, AVR) are commonly designed in such a way that the GPIO peripheral controller is always physically connected to all GPIO pins, with the exception when configured for analog input mode. Therefore having alt function set for a pin does not normally prevent from still using the GPIO input edge interrupt. However the ambz2_sdk API prevents such a configuration (Unless there is a workaround I am not aware of).

Also due to my project’s needs for all other peripheral ports and GPIOs it does not have a spare pin to externally tie together with the SPI CS pin.

Any help is appreciated. Thanks.

1 Like

Hi @VD-Nate
Here is the raw api for Ameba Z2

Thank you for getting back to me.

I have looked into that API and it is unfortunately not raw/low level enough. That API is going through the HAL (a blackbox API) which does not appear to support registering our own interrupt service request handler for the SSI as the SSI HAL appears to register its own ISR when hal_ssi_init_setting() is called (via hal_ssi_init()). Mbed API directly uses those functions to operate the SSI.

The raw API Ameba D is this: ambd_sdk/rtl8721dhp_ssi.c at master · ambiot/ambd_sdk · GitHub

As you can see looking at that file the raw API directly manipulates the peripheral controller’s memory mapped registers without involving the HAL.

Also the better raw API SPI example that is closer to what I am trying to accomplish: ambd_sdk/main.c at master · ambiot/ambd_sdk · GitHub

That example uses InterruptRegister() (macro to irq_register_check() which calls irq_register()) to install an ISR hook for SSI making it possible to handle the SPI IRQ and service it accordingly. There does not appear to be direct equivalent function to InterruptRegister()(irq_register()) for ambz2_sdk. Closest one I found is hal_irq_set_vector() but there are no usage examples and when I tried to use it causes a system segfault because I do not know how to correctly configure and handle an IRQ via that API.

After thinking about it what I really do need is a proper hal_irq_set_vector() usage example that will not crash the ARM core. From there I should be able to port and modify the SSI raw API library for Ameba ZII myself to accomplish my goal.

If you could provide me with a working hal_irq_set_vector() example that would be much appreciated. Thanks. :slight_smile:

Can anyone at Realtek please provide a working hal_irq_set_vector() usage example?


1 Like

Hi @VD-Nate
Sorry for the delay, I hate to say this but there is no

in the open source SDK for RTL8720CM

I did eventually figure it out. Can use sys_irq_set_vector() to install my own interrupt service routine. However come to find out that the SSI rising edge interrupt does not trigger the SPI interrupt, even when mask enabled. Just shows up in the interrupt status register and nothing else occurrs. Weirdly it does actually correspond to chip select rising as documented in the memory mapped register structure, except it does not trigger an interrupt.

Luckily the GPIO peripheral controller is still physically tied in even when pinmux is configured for SPI. So I was able to fallback to using the gpio_irq API to install a callback on rising edge of chip select pin, unregister it from pinmux via hal_pinmux_unregister((uint8_t)SPI0_CS, PID_GPIO); (to force HAL mark the pin as unused) then perform the usual SPI library setup procedures. The callback on rising edge for SPI0_CS pin continued to operate as expected.

So the issue is resolved for me.

1 Like

Clever move :+1: :+1:

Nice it worked out for you~