SPI Master RTOS Driver

The driver is intended for using the SPI master functions in a Real-Time operating system, i.e. is thread safe.

The transfer functions of the SPI Master RTOS driver are optimized for RTOS support. When data transfer is in progress, the transfer functions use semaphore to block the current task or thread until the transfer ends. So the transfer functions do not work without RTOS as the transfer functions must be called in an RTOS task or thread.

During data transfer, the SPI transfer process is not protected, so that a more flexible way can be chosen in application.

Summary of the API's Functional Features

The API provides functions to:
  • Initialize and deinitialize the driver and associated hardware

  • Register I/O descriptor

  • Enable or disable SPI master

  • Hookup callback handlers on read/write/transfer complete, or error events

  • Read/Write message to/from the slave

Summary of Configuration Options

Below is a list of the main SPI master parameters that can be configured in START. Many of these parameters are used by the spi_m_os_init function when initializing the driver and underlying hardware. Most of the initial values can be overridden and changed runtime by calling the appropriate API functions.
  • Select character size

  • Set SPI baudrate

  • Which clock source is used

Driver Implementation Description

After the SPI hardware initialization, the spi_m_os_get_io_descriptor function is needed to register an I/O descriptor. Then control the slave select (SS) pin, and start the read/write operation.

Limitations

The slave select (SS) is not automatically inserted during read/write/transfer, user must use I/O to control the devices' SS.

While read/write/transfer is in progress, the data buffer used must be kept unchanged.

Example of Usage

The following shows a simple example of using the SPI master. The SPI master must have been initialized by spi_m_os_init. This initialization will configure the operation of the SPI master.

The example registers an I/O descriptor and then starts a reading operation.
/** * Example task of using SPI_0 to echo using the I/O abstraction. */void SPI_0_example_task(void *p){    struct io_descriptor *io;    uint16_t              data;    (void)p;    spi_m_os_get_io_descriptor(&SPI_0, &io);    /* Control the slave select (SS) pin */    //gpio_set_pin_level(SPI_0_SS, false);    for (;;) {        if (io_read(io, (uint8_t *)&data, 2) == 2) {            /* read OK, handle data. */;        } else {            /* error. */;        }    }}#define TASK_TRANSFER_STACK_SIZE            ( 256/sizeof( portSTACK_TYPE ))#define TASK_TRANSFER_STACK_PRIORITY        ( tskIDLE_PRIORITY + 0 )static TaskHandle_t xCreatedTransferTask;static void task_transfer_create(void){    /* Create the task that handles the CLI. */    if (xTaskCreate(SPI_0_example_task, "transfer", TASK_TRANSFER_STACK_SIZE, NULL,    TASK_TRANSFER_STACK_PRIORITY, &xCreatedTransferTask) != pdPASS) {        while(1) {;        }    }}static void tasks_run(void){    vTaskStartScheduler();}int main(void){    /* Initializes MCU, drivers and middleware */    atmel_start_init();    task_transfer_create();    tasks_run();    /* Replace with your application code */    while (1) {    }}

Dependencies

  • The SPI master peripheral and its related I/O lines and clocks

  • The NVIC must be configured so that SPI interrupt requests are periodically serviced

  • RTOS