Demo example or instructions to use SPI Slave library in Wiced 6.2?

Tip / Sign in to post questions, reply, level up, and achieve exciting badges. Know more

cross mob
Anonymous
Not applicable

Hi,

I am trying to use SPI Slave library in WICED 6.2. I want to implement SPI using DMA for micro STM32F412.

Do we have any example app or document that could show how to implement it?

While going through the library I came across following code in spi_slave.c:

I have two questions about it,

1) where does the variable device->quit value is changed to either WICED_TRUE or WICED_FALSE?

2) once the device->quit value changes to WICED_FALSE, the WICED_END_OF_CURRENT_THREAD( ) is executed. So how does the spi_slave_thread_main is called again? or do we have to call 'spi_slave_init()' for every SPI transaction?

static void spi_slave_thread_main( uint32_t arg )

{

    spi_slave_t* device = (spi_slave_t*)arg;

    while ( device->quit != WICED_TRUE )

    {

        const spi_slave_register_t* current_register = NULL;

        wiced_spi_slave_command_t   command;

        wiced_result_t              result;

        uint32_t                    a;

        /* Wait for command indefinitely */

        result = wiced_spi_slave_receive_command( device->config->spi, &command, WICED_NEVER_TIMEOUT );

        if ( result != WICED_SUCCESS )

        {

            continue;

        }

        /* Command has been received. Search for register */

        for ( a = 0; a < device->config->register_count; a++ )

        {

            if ( command.address == device->config->register_list.address )

            {

                current_register = &device->config->register_list;

            }

        }

        if ( current_register == NULL )

        {

            wiced_spi_slave_send_error_status( device->config->spi, SPI_SLAVE_TRANSFER_ADDRESS_UNAVAILABLE );

            continue;

        }

        /* Check for register access */

        if ( command.direction == SPI_SLAVE_TRANSFER_READ && current_register->access == SPI_SLAVE_ACCESS_WRITE_ONLY )

        {

            wiced_spi_slave_send_error_status( device->config->spi, SPI_SLAVE_TRANSFER_READ_NOT_ALLOWED );

            continue;

        }

        if ( command.direction == SPI_SLAVE_TRANSFER_WRITE && current_register->access == SPI_SLAVE_ACCESS_READ_ONLY )

        {

            wiced_spi_slave_send_error_status( device->config->spi, SPI_SLAVE_TRANSFER_WRITE_NOT_ALLOWED );

            continue;

        }

        /* Check for correct data length */

        if ( command.data_length != current_register->data_length )

        {

            wiced_spi_slave_send_error_status( device->config->spi, SPI_SLAVE_TRANSFER_LENGTH_MISMATCH );

            continue;

        }

        /* All conditions have been satisfied. Call read callback before transfer */

        if ( current_register->read_callback != NULL && command.direction == SPI_SLAVE_TRANSFER_READ )

        {

            current_register->read_callback( device, device->buffer->data );

        }

        /* If data type is static, copy data from static data pointer to buffer.

         * If data type is dynamic, user is expected to fill in data in the access start callback.

         */

        if ( current_register->data_type == SPI_SLAVE_REGISTER_DATA_STATIC )

        {

            memset( device->buffer, 0, device->buffer_size );

            memcpy( device->buffer->data, current_register->static_data, current_register->data_length );

        }

        device->buffer->data_length = current_register->data_length;

        /* Read/write data from/to the SPI master */

        result = wiced_spi_slave_transfer_data( device->config->spi, command.direction, device->buffer, WICED_NEVER_TIMEOUT );

        /* Call read callback after transfer */

        if ( result == WICED_SUCCESS && current_register->write_callback != NULL && command.direction == SPI_SLAVE_TRANSFER_WRITE )

        {

            current_register->write_callback( device, device->buffer->data );

        }

    }

    WICED_END_OF_CURRENT_THREAD( );

}

0 Likes
1 Solution
lock attach
Attachments are accessible only for community members.
RaktimR_11
Moderator
Moderator
Moderator
500 replies posted 250 replies posted 100 replies posted

I am sorry if I was not clear in my earlier statement when I said you were referring to the incorrect library. device->quit value is not used in the implementation of SPI slave for STM32F4xx devices at all which is why I mentioned the buffer related implementation details. You can set the timeout parameter in wiced_spi_slave_transfer_data to WICED_NEVER_TIMEOUT and I will try to address the question about the data transaction in the attached pseudo-code. Hope it helps!

View solution in original post

5 Replies
RaktimR_11
Moderator
Moderator
Moderator
500 replies posted 250 replies posted 100 replies posted

I think you are looking at the wrong library (Check the call hierarchy of the APIs to be confirmed). The library for SPI block in STM32F4xx is present in 43xxx_Wi-Fi/WICED/platform/MCU/STM32F4xx/peripherals/platform_spi.c. If you check the underlying implementation and the platform files (platform.c, platform.h) of BCM94343WWCD2 (which has STM32F412 as host MCU), you can see that it is implemented using DMA only.

For example code, you can use the wiced_spi_slave_init() API to initialize spi_slave in STM32F412 and you can use a buffer of datatype wiced_spi_slave_data_buffer_t (based on your data size you can dynamically allocate the memory) as already present in 43xxx_Wi-Fi/include/wiced_platform.h and use the wiced_spi_slave_transfer_data() API (Refer to 43xxx_Wi-Fi/WICED/platform/MCU/wiced_platform_common.c) to transfer the data.

Anonymous
Not applicable

Hi Rroy,

I get that the SPI implementation is using DMA only. My questions are still same,

1) where does the variable device->quit value is changed to either WICED_TRUE or WICED_FALSE?

2) once the device->quit value changes to WICED_FALSE, the WICED_END_OF_CURRENT_THREAD( ) is executed. So how does the spi_slave_thread_main is called again? or do we have to call 'spi_slave_init()' for every SPI transaction?

Regarding your comment about example code I have one additional question,

3)we use wiced_spi_slave_init for SPI slave initialisation, and then use wiced_spi_slave_transfer_data for first data transfer. If we need some more data transactions , what should be done: a)use 'wiced_spi_slave_transfer_data' again or b)use 'wiced_spi_slave_init' before using wiced_spi_slave_init.?

Answers for above 3 questions are important for implementing SPI in our application

Regards,

Aniket.

0 Likes
lock attach
Attachments are accessible only for community members.
RaktimR_11
Moderator
Moderator
Moderator
500 replies posted 250 replies posted 100 replies posted

I am sorry if I was not clear in my earlier statement when I said you were referring to the incorrect library. device->quit value is not used in the implementation of SPI slave for STM32F4xx devices at all which is why I mentioned the buffer related implementation details. You can set the timeout parameter in wiced_spi_slave_transfer_data to WICED_NEVER_TIMEOUT and I will try to address the question about the data transaction in the attached pseudo-code. Hope it helps!

Anonymous
Not applicable

Hi rroy,

Thanks for your prompt reply.

I get it, after your explanation my first two questions are no more valid.

Regarding data transaction, in your pseudocode you have showed just 1 transaction.

If you decide to perform one more transaction, should 'wiced_spi_slave_init' be used again?

Regards,

Aniket.

0 Likes
RaktimR_11
Moderator
Moderator
Moderator
500 replies posted 250 replies posted 100 replies posted

You should use wiced_spi_slave_transfer_data() API only; no need to go through the slave initialization process again. Please check the way buffer is allocated which should help you in your implementation.