Platform drivers for Mbed.

Dependents:   EVAL-CN0535-FMCZ EVAL-CN0535-FMCZ EVAL-AD568x-AD569x EVAL-AD7606 ... more

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers spi.cpp Source File

spi.cpp

Go to the documentation of this file.
00001 /***************************************************************************//**
00002  *   @file   spi.cpp
00003  *   @brief  Implementation of SPI Mbed platform driver interfaces
00004 ********************************************************************************
00005  * Copyright (c) 2019-2021 Analog Devices, Inc.
00006  * All rights reserved.
00007  *
00008  * This software is proprietary to Analog Devices, Inc. and its licensors.
00009  * By using this software you agree to the terms of the associated
00010  * Analog Devices Software License Agreement.
00011 *******************************************************************************/
00012 
00013 /******************************************************************************/
00014 /***************************** Include Files **********************************/
00015 /******************************************************************************/
00016 
00017 #include <stdio.h>
00018 #include <mbed.h>
00019 
00020 // Platform drivers needs to be C-compatible to work with other drivers
00021 #ifdef __cplusplus
00022 extern "C"
00023 {
00024 #endif //  _cplusplus
00025 
00026 #include "error.h"
00027 #include "spi.h "
00028 #include "gpio.h"
00029 #include "spi_extra.h"
00030 
00031 /******************************************************************************/
00032 /********************** Macros and Constants Definitions **********************/
00033 /******************************************************************************/
00034 
00035 #define     SPI_8_BIT_FRAME         8       // SPI 8-bit frame size
00036 
00037 /******************************************************************************/
00038 /********************** Variables and User defined data types *****************/
00039 /******************************************************************************/
00040 
00041 /******************************************************************************/
00042 /************************ Functions Declarations ******************************/
00043 /******************************************************************************/
00044 
00045 /******************************************************************************/
00046 /************************ Functions Definitions *******************************/
00047 /******************************************************************************/
00048 
00049 /**
00050  * @brief Initialize the SPI communication peripheral.
00051  * @param desc - The SPI descriptor.
00052  * @param init_param - The structure that contains the SPI parameters.
00053  * @return SUCCESS in case of success, FAILURE otherwise.
00054  */
00055 int32_t spi_init_noos(struct spi_desc **desc,
00056               const struct spi_init_param *param)
00057 {
00058     mbed::SPI *spi;                 // Pointer to new spi instance
00059     DigitalOut *csb;                // pointer to new CSB gpio instance
00060     mbed_spi_desc *mbed_desc;       // Pointer to mbed spi descriptor
00061     use_gpio_ssel_t use_gpio_ssel;  // For CSB hardware (implicit) control
00062     spi_desc *new_desc;
00063 
00064     if ((desc) && (param) && (param->extra)) {
00065         // Create the spi description object for the device
00066         new_desc = (spi_desc *)malloc(sizeof(spi_desc));
00067         if (!new_desc) {
00068             goto err_new_desc;
00069         }
00070 
00071         new_desc->chip_select = param->chip_select;
00072         new_desc->mode = param->mode;
00073         new_desc->max_speed_hz = param->max_speed_hz;
00074 
00075         // Create the SPI extra descriptor object to store new SPI instances
00076         mbed_desc = (mbed_spi_desc *)malloc(sizeof(mbed_spi_desc));
00077         if (!mbed_desc) {
00078             goto err_mbed_desc;
00079         }
00080 
00081         // Configure and instantiate SPI protocol
00082         if (((mbed_spi_init_param *)param->extra)->use_sw_csb) {
00083             /* CSB pin toggled explicitly (s/w controlled) during SPI transaction */
00084             spi = new SPI(
00085                 (PinName)(((mbed_spi_init_param *)param->extra)->spi_mosi_pin),
00086                 (PinName)(((mbed_spi_init_param *)param->extra)->spi_miso_pin),
00087                 (PinName)(((mbed_spi_init_param *)param->extra)->spi_clk_pin));
00088 
00089             if (spi) {
00090                 /* Configure and instantiate chip select pin */
00091                 csb = new DigitalOut((PinName)(new_desc->chip_select));
00092                 if (csb) {
00093                     mbed_desc->use_sw_csb = true;
00094                     mbed_desc->csb_gpio = (DigitalOut *)csb;
00095                     csb->write(GPIO_HIGH);
00096                 } else {
00097                     goto err_csb;
00098                 }
00099             }
00100         } else {
00101             /* CSB pin toggled implicitly (through HAL layer) during SPI transaction */
00102             spi = new SPI(
00103                 (PinName)(((mbed_spi_init_param *)param->extra)->spi_mosi_pin),
00104                 (PinName)(((mbed_spi_init_param *)param->extra)->spi_miso_pin),
00105                 (PinName)(((mbed_spi_init_param *)param->extra)->spi_clk_pin),
00106                 (PinName)(param->chip_select),
00107                 use_gpio_ssel);
00108 
00109             mbed_desc->use_sw_csb = false;
00110             mbed_desc->csb_gpio = NULL;
00111         }
00112 
00113         if (!spi) {
00114             goto err_spi;
00115         }
00116 
00117         mbed_desc->spi_port = (SPI *)spi;
00118 
00119         new_desc->extra = (mbed_spi_desc *)mbed_desc;
00120         *desc = new_desc;
00121 
00122         /**
00123             NOTE: Actual frequency of SPI clk will be somewhat device
00124             dependent, relating to clock-settings, prescalars etc. If absolute
00125             SPI frequency is required, consult your device documentation.
00126           **/
00127         spi->frequency(param->max_speed_hz);
00128         spi->format(SPI_8_BIT_FRAME, param->mode);   // data write/read format
00129         spi->set_default_write_value(0x00);          // code to write when reading back
00130 
00131         return SUCCESS;
00132     }
00133 
00134 err_spi:
00135     if (((mbed_spi_init_param *)param->extra)->use_sw_csb) {
00136         free(csb);
00137     }
00138 err_csb:
00139     free(spi);
00140     free(mbed_desc);
00141 err_mbed_desc:
00142     free(new_desc);
00143 err_new_desc:
00144     // Nothing to free
00145 
00146     return FAILURE;
00147 }
00148 
00149 
00150 /**
00151  * @brief Free the resources allocated by spi_init().
00152  * @param desc - The SPI descriptor.
00153  * @return SUCCESS in case of success, FAILURE otherwise.
00154  */
00155 int32_t spi_remove(struct spi_desc *desc)
00156 {
00157     if (desc) {
00158         if (((mbed_spi_desc *)desc->extra)->use_sw_csb) {
00159             // Free the CSB gpio object
00160             if((DigitalOut *)(((mbed_spi_desc *)(desc->extra))->csb_gpio)) {
00161                 delete((DigitalOut *)(((mbed_spi_desc *)(desc->extra))->csb_gpio));
00162             }
00163         }
00164 
00165         // Free the SPI port object
00166         if ((SPI *)(((mbed_spi_desc *)(desc->extra))->spi_port)) {
00167             delete((SPI *)(((mbed_spi_desc *)(desc->extra))->spi_port));
00168         }
00169 
00170         // Free the SPI extra descriptor object
00171         if ((mbed_spi_desc *)(desc->extra)) {
00172             free((mbed_spi_desc *)(desc->extra));
00173         }
00174 
00175         // Free the SPI descriptor object
00176         free(desc);
00177 
00178         return SUCCESS;
00179     }
00180 
00181     return FAILURE;
00182 }
00183 
00184 
00185 /**
00186  * @brief Write and read data to/from SPI.
00187  * @param desc - The SPI descriptor.
00188  * @param data - The buffer with the transmitted/received data.
00189  * @param bytes_number - Number of bytes to write/read.
00190  * @return SUCCESS in case of success, FAILURE otherwise.
00191  */
00192 int32_t spi_write_and_read(struct spi_desc *desc,
00193                uint8_t *data,
00194                uint16_t bytes_number)
00195 {
00196     mbed::SPI *spi;             // pointer to new spi instance
00197     mbed::DigitalOut *csb;      // pointer to new CSB instance
00198 
00199     if (desc) {
00200         spi = (SPI *)(((mbed_spi_desc *)(desc->extra))->spi_port);
00201 
00202         if (((mbed_spi_desc *)desc->extra)->use_sw_csb) {
00203             csb = (DigitalOut *)(((mbed_spi_desc *)(desc->extra))->csb_gpio);
00204             csb->write(GPIO_LOW);
00205         }
00206 
00207         /* Perform synchronous SPI write and read */
00208         spi->write((const char *)data, bytes_number, (char *)data, bytes_number);
00209 
00210         if (((mbed_spi_desc *)desc->extra)->use_sw_csb) {
00211             csb->write(GPIO_HIGH);
00212         }
00213 
00214         return SUCCESS;
00215     }
00216 
00217     return FAILURE;
00218 }
00219 
00220 
00221 /**
00222  * @brief Transfer (write/read) the number of SPI messages
00223  * @param desc - The SPI descriptor
00224  * @param msgs - Pointer to SPI messages
00225  * @param num_of_msgs - Number of SPI messages
00226  * @return SUCCESS in case of success, FAILURE otherwise.
00227  * @note Use of this function requires CSB pin to be software controlled
00228  */
00229 int32_t spi_transfer(struct spi_desc *desc, struct spi_msg *msgs,
00230              uint32_t num_of_msgs)
00231 {
00232     mbed::SPI *spi;             // pointer to new spi instance
00233     mbed::DigitalOut *csb;      // pointer to new CSB instance
00234     uint8_t msg_cnt;            // SPI message counter
00235 
00236     if (desc) {
00237         if (!((mbed_spi_desc *)desc->extra)->use_sw_csb)
00238             return FAILURE;
00239 
00240         spi = (SPI *)(((mbed_spi_desc *)(desc->extra))->spi_port);
00241         csb = (DigitalOut *)(((mbed_spi_desc *)(desc->extra))->csb_gpio);
00242 
00243         if (!spi || !csb)
00244             return FAILURE;
00245 
00246         for (msg_cnt = 0; msg_cnt < num_of_msgs; msg_cnt++) {
00247             csb->write(GPIO_LOW);
00248 
00249             /* Perform synchronous SPI write and read */
00250             if (!msgs[msg_cnt].tx_buff) {
00251                 spi->write(NULL, 0,
00252                        (char *)msgs[msg_cnt].rx_buff, msgs[msg_cnt].bytes_number);
00253             } else {
00254                 spi->write((const char *)msgs[msg_cnt].tx_buff, msgs[msg_cnt].bytes_number,
00255                        (char *)msgs[msg_cnt].rx_buff, msgs[msg_cnt].bytes_number);
00256             }
00257 
00258             if (msgs[msg_cnt].cs_change) {
00259                 csb->write(GPIO_HIGH);
00260             }
00261         }
00262 
00263         csb->write(GPIO_HIGH);
00264         return SUCCESS;
00265     }
00266 
00267     return FAILURE;
00268 }
00269 
00270 #ifdef __cplusplus  // Closing extern c
00271 }
00272 #endif //  _cplusplus