NXP's driver library for LPC17xx, ported to mbed's online compiler. Not tested! I had to fix a lot of warings and found a couple of pretty obvious bugs, so the chances are there are more. Original: http://ics.nxp.com/support/documents/microcontrollers/zip/lpc17xx.cmsis.driver.library.zip

Dependencies:   mbed

Committer:
igorsk
Date:
Wed Feb 17 16:22:39 2010 +0000
Revision:
0:1063a091a062

        

Who changed what in which revision?

UserRevisionLine numberNew contents of line
igorsk 0:1063a091a062 1 /**
igorsk 0:1063a091a062 2 * @file : lpc17xx_spi.c
igorsk 0:1063a091a062 3 * @brief : Contains all functions support for SPI firmware library on LPC17xx
igorsk 0:1063a091a062 4 * @version : 1.0
igorsk 0:1063a091a062 5 * @date : 3. April. 2009
igorsk 0:1063a091a062 6 * @author : HieuNguyen
igorsk 0:1063a091a062 7 **************************************************************************
igorsk 0:1063a091a062 8 * Software that is described herein is for illustrative purposes only
igorsk 0:1063a091a062 9 * which provides customers with programming information regarding the
igorsk 0:1063a091a062 10 * products. This software is supplied "AS IS" without any warranties.
igorsk 0:1063a091a062 11 * NXP Semiconductors assumes no responsibility or liability for the
igorsk 0:1063a091a062 12 * use of the software, conveys no license or title under any patent,
igorsk 0:1063a091a062 13 * copyright, or mask work right to the product. NXP Semiconductors
igorsk 0:1063a091a062 14 * reserves the right to make changes in the software without
igorsk 0:1063a091a062 15 * notification. NXP Semiconductors also make no representation or
igorsk 0:1063a091a062 16 * warranty that such application will be suitable for the specified
igorsk 0:1063a091a062 17 * use without further testing or modification.
igorsk 0:1063a091a062 18 **********************************************************************/
igorsk 0:1063a091a062 19
igorsk 0:1063a091a062 20 /* Peripheral group ----------------------------------------------------------- */
igorsk 0:1063a091a062 21 /** @addtogroup SPI
igorsk 0:1063a091a062 22 * @{
igorsk 0:1063a091a062 23 */
igorsk 0:1063a091a062 24
igorsk 0:1063a091a062 25 /* Includes ------------------------------------------------------------------- */
igorsk 0:1063a091a062 26 #include "lpc17xx_spi.h"
igorsk 0:1063a091a062 27 #include "lpc17xx_clkpwr.h"
igorsk 0:1063a091a062 28
igorsk 0:1063a091a062 29 /* If this source file built with example, the LPC17xx FW library configuration
igorsk 0:1063a091a062 30 * file in each example directory ("lpc17xx_libcfg.h") must be included,
igorsk 0:1063a091a062 31 * otherwise the default FW library configuration file must be included instead
igorsk 0:1063a091a062 32 */
igorsk 0:1063a091a062 33 #ifdef __BUILD_WITH_EXAMPLE__
igorsk 0:1063a091a062 34 #include "lpc17xx_libcfg.h"
igorsk 0:1063a091a062 35 #else
igorsk 0:1063a091a062 36 #include "lpc17xx_libcfg_default.h"
igorsk 0:1063a091a062 37 #endif /* __BUILD_WITH_EXAMPLE__ */
igorsk 0:1063a091a062 38
igorsk 0:1063a091a062 39 #ifdef _SPI
igorsk 0:1063a091a062 40
igorsk 0:1063a091a062 41 /* Private Types -------------------------------------------------------------- */
igorsk 0:1063a091a062 42 /** @defgroup SPI_Private_Types
igorsk 0:1063a091a062 43 * @{
igorsk 0:1063a091a062 44 */
igorsk 0:1063a091a062 45
igorsk 0:1063a091a062 46 /** @brief SPI device configuration structure type */
igorsk 0:1063a091a062 47 typedef struct
igorsk 0:1063a091a062 48 {
igorsk 0:1063a091a062 49 int32_t dataword; /* Current data word: 0 - 8 bit; 1 - 16 bit */
igorsk 0:1063a091a062 50 uint32_t txrx_setup; /* Transmission setup */
igorsk 0:1063a091a062 51 void (*inthandler)(void); /* Transmission interrupt handler */
igorsk 0:1063a091a062 52 } SPI_CFG_T;
igorsk 0:1063a091a062 53
igorsk 0:1063a091a062 54 /**
igorsk 0:1063a091a062 55 * @}
igorsk 0:1063a091a062 56 */
igorsk 0:1063a091a062 57
igorsk 0:1063a091a062 58
igorsk 0:1063a091a062 59 /* Private Variables ---------------------------------------------------------- */
igorsk 0:1063a091a062 60 /* SPI configuration data */
igorsk 0:1063a091a062 61 static SPI_CFG_T spidat;
igorsk 0:1063a091a062 62
igorsk 0:1063a091a062 63
igorsk 0:1063a091a062 64 /* Private Functions ---------------------------------------------------------- */
igorsk 0:1063a091a062 65 /** @defgroup SPI_Private_Functions
igorsk 0:1063a091a062 66 * @{
igorsk 0:1063a091a062 67 */
igorsk 0:1063a091a062 68
igorsk 0:1063a091a062 69 /*********************************************************************//**
igorsk 0:1063a091a062 70 * @brief Standard Private SPI Interrupt handler
igorsk 0:1063a091a062 71 * @param[in] None
igorsk 0:1063a091a062 72 * @return None
igorsk 0:1063a091a062 73 ***********************************************************************/
igorsk 0:1063a091a062 74 void SPI_IntHandler(void)
igorsk 0:1063a091a062 75 {
igorsk 0:1063a091a062 76 SPI_DATA_SETUP_Type *xf_setup;
igorsk 0:1063a091a062 77 uint16_t tmp;
igorsk 0:1063a091a062 78
igorsk 0:1063a091a062 79 xf_setup = (SPI_DATA_SETUP_Type *)spidat.txrx_setup;
igorsk 0:1063a091a062 80
igorsk 0:1063a091a062 81 /* Dummy read to clear SPI interrupt flag */
igorsk 0:1063a091a062 82 if (LPC_SPI->SPINT & SPI_SPINT_INTFLAG){
igorsk 0:1063a091a062 83 LPC_SPI->SPINT = SPI_SPINT_INTFLAG;
igorsk 0:1063a091a062 84 }
igorsk 0:1063a091a062 85
igorsk 0:1063a091a062 86 // save status
igorsk 0:1063a091a062 87 tmp = LPC_SPI->SPSR;
igorsk 0:1063a091a062 88 xf_setup->status = tmp;
igorsk 0:1063a091a062 89 // Check for error
igorsk 0:1063a091a062 90 if (tmp & (SPI_SPSR_ABRT | SPI_SPSR_MODF | SPI_SPSR_ROVR | SPI_SPSR_WCOL)){
igorsk 0:1063a091a062 91 xf_setup->status |= SPI_STAT_ERROR;
igorsk 0:1063a091a062 92 // Disable Interrupt and call call-back
igorsk 0:1063a091a062 93 SPI_IntCmd(LPC_SPI, DISABLE);
igorsk 0:1063a091a062 94 if (xf_setup->callback != NULL){
igorsk 0:1063a091a062 95 xf_setup->callback();
igorsk 0:1063a091a062 96 }
igorsk 0:1063a091a062 97 return;
igorsk 0:1063a091a062 98 }
igorsk 0:1063a091a062 99
igorsk 0:1063a091a062 100 /* Check SPI complete flag */
igorsk 0:1063a091a062 101 if (tmp & SPI_SPSR_SPIF){
igorsk 0:1063a091a062 102 // Read data from SPI data
igorsk 0:1063a091a062 103 tmp = SPI_ReceiveData(LPC_SPI);
igorsk 0:1063a091a062 104 if (xf_setup->rx_data != NULL)
igorsk 0:1063a091a062 105 {
igorsk 0:1063a091a062 106 // if (spidat.dataword == 0){
igorsk 0:1063a091a062 107 // *(uint8_t *)(xf_setup->rx_data + xf_setup->counter) = (uint8_t) tmp;
igorsk 0:1063a091a062 108 // } else {
igorsk 0:1063a091a062 109 // *(uint16_t *)(xf_setup->rx_data + xf_setup->counter) = (uint8_t) tmp;
igorsk 0:1063a091a062 110 // }
igorsk 0:1063a091a062 111 if (spidat.dataword == 0){
igorsk 0:1063a091a062 112 *(uint8_t *)((uint8_t *)(xf_setup->rx_data) + xf_setup->counter) = (uint8_t) tmp;
igorsk 0:1063a091a062 113 } else {
igorsk 0:1063a091a062 114 *(uint16_t *)((uint8_t *)(xf_setup->rx_data) + xf_setup->counter) = (uint8_t) tmp;
igorsk 0:1063a091a062 115 }
igorsk 0:1063a091a062 116 }
igorsk 0:1063a091a062 117 // Increase counter
igorsk 0:1063a091a062 118 if (spidat.dataword == 0){
igorsk 0:1063a091a062 119 xf_setup->counter++;
igorsk 0:1063a091a062 120 } else {
igorsk 0:1063a091a062 121 xf_setup->counter += 2;
igorsk 0:1063a091a062 122 }
igorsk 0:1063a091a062 123 }
igorsk 0:1063a091a062 124
igorsk 0:1063a091a062 125 if (xf_setup->counter < xf_setup->length){
igorsk 0:1063a091a062 126 // Write data to buffer
igorsk 0:1063a091a062 127 if(xf_setup->tx_data == NULL){
igorsk 0:1063a091a062 128 if (spidat.dataword == 0){
igorsk 0:1063a091a062 129 SPI_SendData(LPC_SPI, 0xFF);
igorsk 0:1063a091a062 130 } else {
igorsk 0:1063a091a062 131 SPI_SendData(LPC_SPI, 0xFFFF);
igorsk 0:1063a091a062 132 }
igorsk 0:1063a091a062 133 } else {
igorsk 0:1063a091a062 134 // if (spidat.dataword == 0){
igorsk 0:1063a091a062 135 // SPI_SendData(SPI, (*(uint8_t *)(xf_setup->tx_data + xf_setup->counter)));
igorsk 0:1063a091a062 136 // } else {
igorsk 0:1063a091a062 137 // SPI_SendData(SPI, (*(uint16_t *)(xf_setup->tx_data + xf_setup->counter)));
igorsk 0:1063a091a062 138 // }
igorsk 0:1063a091a062 139 if (spidat.dataword == 0){
igorsk 0:1063a091a062 140 SPI_SendData(LPC_SPI, (*(uint8_t *)((uint8_t *)(xf_setup->tx_data) + xf_setup->counter)));
igorsk 0:1063a091a062 141 } else {
igorsk 0:1063a091a062 142 SPI_SendData(LPC_SPI, (*(uint16_t *)((uint8_t *)(xf_setup->tx_data) + xf_setup->counter)));
igorsk 0:1063a091a062 143 }
igorsk 0:1063a091a062 144 }
igorsk 0:1063a091a062 145 }
igorsk 0:1063a091a062 146 // No more data to send
igorsk 0:1063a091a062 147 else {
igorsk 0:1063a091a062 148 xf_setup->status |= SPI_STAT_DONE;
igorsk 0:1063a091a062 149 // Disable Interrupt and call call-back
igorsk 0:1063a091a062 150 SPI_IntCmd(LPC_SPI, DISABLE);
igorsk 0:1063a091a062 151 if (xf_setup->callback != NULL){
igorsk 0:1063a091a062 152 xf_setup->callback();
igorsk 0:1063a091a062 153 }
igorsk 0:1063a091a062 154 }
igorsk 0:1063a091a062 155 }
igorsk 0:1063a091a062 156
igorsk 0:1063a091a062 157
igorsk 0:1063a091a062 158 /**
igorsk 0:1063a091a062 159 * @}
igorsk 0:1063a091a062 160 */
igorsk 0:1063a091a062 161
igorsk 0:1063a091a062 162 /* Public Functions ----------------------------------------------------------- */
igorsk 0:1063a091a062 163 /** @addtogroup SPI_Public_Functions
igorsk 0:1063a091a062 164 * @{
igorsk 0:1063a091a062 165 */
igorsk 0:1063a091a062 166
igorsk 0:1063a091a062 167 /*********************************************************************//**
igorsk 0:1063a091a062 168 * @brief Setup clock rate for SPI device
igorsk 0:1063a091a062 169 * @param[in] SPIx SPI peripheral definition, should be SPI
igorsk 0:1063a091a062 170 * @param[in] target_clock : clock of SPI (Hz)
igorsk 0:1063a091a062 171 * @return None
igorsk 0:1063a091a062 172 ***********************************************************************/
igorsk 0:1063a091a062 173 void SPI_SetClock (LPC_SPI_TypeDef *SPIx, uint32_t target_clock)
igorsk 0:1063a091a062 174 {
igorsk 0:1063a091a062 175 uint32_t spi_pclk;
igorsk 0:1063a091a062 176 uint32_t prescale, temp;
igorsk 0:1063a091a062 177
igorsk 0:1063a091a062 178 CHECK_PARAM(PARAM_SPIx(SPIx));
igorsk 0:1063a091a062 179
igorsk 0:1063a091a062 180 if (SPIx == LPC_SPI){
igorsk 0:1063a091a062 181 spi_pclk = CLKPWR_GetPCLK (CLKPWR_PCLKSEL_SPI);
igorsk 0:1063a091a062 182 } else {
igorsk 0:1063a091a062 183 return;
igorsk 0:1063a091a062 184 }
igorsk 0:1063a091a062 185
igorsk 0:1063a091a062 186 prescale = 8;
igorsk 0:1063a091a062 187 // Find closest clock to target clock
igorsk 0:1063a091a062 188 while (1){
igorsk 0:1063a091a062 189 temp = target_clock * prescale;
igorsk 0:1063a091a062 190 if (temp >= spi_pclk){
igorsk 0:1063a091a062 191 break;
igorsk 0:1063a091a062 192 }
igorsk 0:1063a091a062 193 prescale += 2;
igorsk 0:1063a091a062 194 if(prescale >= 254){
igorsk 0:1063a091a062 195 break;
igorsk 0:1063a091a062 196 }
igorsk 0:1063a091a062 197 }
igorsk 0:1063a091a062 198
igorsk 0:1063a091a062 199 // Write to register
igorsk 0:1063a091a062 200 SPIx->SPCCR = SPI_SPCCR_COUNTER(prescale);
igorsk 0:1063a091a062 201 }
igorsk 0:1063a091a062 202
igorsk 0:1063a091a062 203
igorsk 0:1063a091a062 204 /*********************************************************************//**
igorsk 0:1063a091a062 205 * @brief De-initializes the SPIx peripheral registers to their
igorsk 0:1063a091a062 206 * default reset values.
igorsk 0:1063a091a062 207 * @param[in] SPIx SPI peripheral selected, should be SPI
igorsk 0:1063a091a062 208 * @return None
igorsk 0:1063a091a062 209 **********************************************************************/
igorsk 0:1063a091a062 210 void SPI_DeInit(LPC_SPI_TypeDef *SPIx)
igorsk 0:1063a091a062 211 {
igorsk 0:1063a091a062 212 CHECK_PARAM(PARAM_SPIx(SPIx));
igorsk 0:1063a091a062 213
igorsk 0:1063a091a062 214 if (SPIx == LPC_SPI){
igorsk 0:1063a091a062 215 /* Set up clock and power for SPI module */
igorsk 0:1063a091a062 216 CLKPWR_ConfigPPWR (CLKPWR_PCONP_PCSPI, DISABLE);
igorsk 0:1063a091a062 217 }
igorsk 0:1063a091a062 218 }
igorsk 0:1063a091a062 219
igorsk 0:1063a091a062 220
igorsk 0:1063a091a062 221
igorsk 0:1063a091a062 222 /********************************************************************//**
igorsk 0:1063a091a062 223 * @brief Initializes the SPIx peripheral according to the specified
igorsk 0:1063a091a062 224 * parameters in the UART_ConfigStruct.
igorsk 0:1063a091a062 225 * @param[in] SPIx SPI peripheral selected, should be SPI
igorsk 0:1063a091a062 226 * @param[in] SPI_ConfigStruct Pointer to a SPI_CFG_Type structure
igorsk 0:1063a091a062 227 * that contains the configuration information for the
igorsk 0:1063a091a062 228 * specified SPI peripheral.
igorsk 0:1063a091a062 229 * @return None
igorsk 0:1063a091a062 230 *********************************************************************/
igorsk 0:1063a091a062 231 void SPI_Init(LPC_SPI_TypeDef *SPIx, SPI_CFG_Type *SPI_ConfigStruct)
igorsk 0:1063a091a062 232 {
igorsk 0:1063a091a062 233 uint32_t tmp;
igorsk 0:1063a091a062 234
igorsk 0:1063a091a062 235 CHECK_PARAM(PARAM_SPIx(SPIx));
igorsk 0:1063a091a062 236
igorsk 0:1063a091a062 237 if(SPIx == LPC_SPI){
igorsk 0:1063a091a062 238 /* Set up clock and power for UART module */
igorsk 0:1063a091a062 239 CLKPWR_ConfigPPWR (CLKPWR_PCONP_PCSPI, ENABLE);
igorsk 0:1063a091a062 240 } else {
igorsk 0:1063a091a062 241 return;
igorsk 0:1063a091a062 242 }
igorsk 0:1063a091a062 243
igorsk 0:1063a091a062 244 // Configure SPI, interrupt is disable as default
igorsk 0:1063a091a062 245 tmp = ((SPI_ConfigStruct->CPHA) | (SPI_ConfigStruct->CPOL) \
igorsk 0:1063a091a062 246 | (SPI_ConfigStruct->DataOrder) | (SPI_ConfigStruct->Databit) \
igorsk 0:1063a091a062 247 | (SPI_ConfigStruct->Mode) | SPI_SPCR_BIT_EN) & SPI_SPCR_BITMASK;
igorsk 0:1063a091a062 248 // write back to SPI control register
igorsk 0:1063a091a062 249 SPIx->SPCR = tmp;
igorsk 0:1063a091a062 250
igorsk 0:1063a091a062 251 if (SPI_ConfigStruct->Databit > SPI_DATABIT_8){
igorsk 0:1063a091a062 252 spidat.dataword = 1;
igorsk 0:1063a091a062 253 } else {
igorsk 0:1063a091a062 254 spidat.dataword = 0;
igorsk 0:1063a091a062 255 }
igorsk 0:1063a091a062 256
igorsk 0:1063a091a062 257 // Set clock rate for SPI peripheral
igorsk 0:1063a091a062 258 SPI_SetClock(SPIx, SPI_ConfigStruct->ClockRate);
igorsk 0:1063a091a062 259
igorsk 0:1063a091a062 260 // If interrupt flag is set, Write '1' to Clear interrupt flag
igorsk 0:1063a091a062 261 if (SPIx->SPINT & SPI_SPINT_INTFLAG){
igorsk 0:1063a091a062 262 SPIx->SPINT = SPI_SPINT_INTFLAG;
igorsk 0:1063a091a062 263 }
igorsk 0:1063a091a062 264 }
igorsk 0:1063a091a062 265
igorsk 0:1063a091a062 266
igorsk 0:1063a091a062 267
igorsk 0:1063a091a062 268 /*****************************************************************************//**
igorsk 0:1063a091a062 269 * @brief Fills each SPI_InitStruct member with its default value:
igorsk 0:1063a091a062 270 * - CPHA = SPI_CPHA_FIRST
igorsk 0:1063a091a062 271 * - CPOL = SPI_CPOL_HI
igorsk 0:1063a091a062 272 * - ClockRate = 1000000
igorsk 0:1063a091a062 273 * - DataOrder = SPI_DATA_MSB_FIRST
igorsk 0:1063a091a062 274 * - Databit = SPI_DATABIT_8
igorsk 0:1063a091a062 275 * - Mode = SPI_MASTER_MODE
igorsk 0:1063a091a062 276 * @param[in] SPI_InitStruct Pointer to a SPI_CFG_Type structure
igorsk 0:1063a091a062 277 * which will be initialized.
igorsk 0:1063a091a062 278 * @return None
igorsk 0:1063a091a062 279 *******************************************************************************/
igorsk 0:1063a091a062 280 void SPI_ConfigStructInit(SPI_CFG_Type *SPI_InitStruct)
igorsk 0:1063a091a062 281 {
igorsk 0:1063a091a062 282 SPI_InitStruct->CPHA = SPI_CPHA_FIRST;
igorsk 0:1063a091a062 283 SPI_InitStruct->CPOL = SPI_CPOL_HI;
igorsk 0:1063a091a062 284 SPI_InitStruct->ClockRate = 1000000;
igorsk 0:1063a091a062 285 SPI_InitStruct->DataOrder = SPI_DATA_MSB_FIRST;
igorsk 0:1063a091a062 286 SPI_InitStruct->Databit = SPI_DATABIT_8;
igorsk 0:1063a091a062 287 SPI_InitStruct->Mode = SPI_MASTER_MODE;
igorsk 0:1063a091a062 288 }
igorsk 0:1063a091a062 289
igorsk 0:1063a091a062 290 /*********************************************************************//**
igorsk 0:1063a091a062 291 * @brief Transmit a single data through SPIx peripheral
igorsk 0:1063a091a062 292 * @param[in] SPIx SPI peripheral selected, should be SPI
igorsk 0:1063a091a062 293 * @param[in] Data Data to transmit (must be 16 or 8-bit long,
igorsk 0:1063a091a062 294 * this depend on SPI data bit number configured)
igorsk 0:1063a091a062 295 * @return none
igorsk 0:1063a091a062 296 **********************************************************************/
igorsk 0:1063a091a062 297 void SPI_SendData(LPC_SPI_TypeDef* SPIx, uint16_t Data)
igorsk 0:1063a091a062 298 {
igorsk 0:1063a091a062 299 CHECK_PARAM(PARAM_SPIx(SPIx));
igorsk 0:1063a091a062 300
igorsk 0:1063a091a062 301 SPIx->SPDR = Data & SPI_SPDR_BITMASK;
igorsk 0:1063a091a062 302 }
igorsk 0:1063a091a062 303
igorsk 0:1063a091a062 304
igorsk 0:1063a091a062 305
igorsk 0:1063a091a062 306 /*********************************************************************//**
igorsk 0:1063a091a062 307 * @brief Receive a single data from SPIx peripheral
igorsk 0:1063a091a062 308 * @param[in] SPIx SPI peripheral selected, should be SPI
igorsk 0:1063a091a062 309 * @return Data received (16-bit long)
igorsk 0:1063a091a062 310 **********************************************************************/
igorsk 0:1063a091a062 311 uint16_t SPI_ReceiveData(LPC_SPI_TypeDef* SPIx)
igorsk 0:1063a091a062 312 {
igorsk 0:1063a091a062 313 CHECK_PARAM(PARAM_SPIx(SPIx));
igorsk 0:1063a091a062 314
igorsk 0:1063a091a062 315 return ((uint16_t) (SPIx->SPDR & SPI_SPDR_BITMASK));
igorsk 0:1063a091a062 316 }
igorsk 0:1063a091a062 317
igorsk 0:1063a091a062 318 /*********************************************************************//**
igorsk 0:1063a091a062 319 * @brief SPI Read write data function
igorsk 0:1063a091a062 320 * @param[in] SPIx Pointer to SPI peripheral, should be SPI
igorsk 0:1063a091a062 321 * @param[in] dataCfg Pointer to a SPI_DATA_SETUP_Type structure that
igorsk 0:1063a091a062 322 * contains specified information about transmit
igorsk 0:1063a091a062 323 * data configuration.
igorsk 0:1063a091a062 324 * @param[in] xfType Transfer type, should be:
igorsk 0:1063a091a062 325 * - SPI_TRANSFER_POLLING: Polling mode
igorsk 0:1063a091a062 326 * - SPI_TRANSFER_INTERRUPT: Interrupt mode
igorsk 0:1063a091a062 327 * @return Actual Data length has been transferred in polling mode.
igorsk 0:1063a091a062 328 * In interrupt mode, always return (0)
igorsk 0:1063a091a062 329 * Return (-1) if error.
igorsk 0:1063a091a062 330 * Note: This function can be used in both master and slave mode.
igorsk 0:1063a091a062 331 ***********************************************************************/
igorsk 0:1063a091a062 332 int32_t SPI_ReadWrite (LPC_SPI_TypeDef *SPIx, SPI_DATA_SETUP_Type *dataCfg, \
igorsk 0:1063a091a062 333 SPI_TRANSFER_Type xfType)
igorsk 0:1063a091a062 334 {
igorsk 0:1063a091a062 335 uint8_t *rdata8 = NULL;
igorsk 0:1063a091a062 336 uint8_t *wdata8 = NULL;
igorsk 0:1063a091a062 337 uint16_t *rdata16 = NULL;
igorsk 0:1063a091a062 338 uint16_t *wdata16 = NULL;
igorsk 0:1063a091a062 339 uint32_t stat=0;
igorsk 0:1063a091a062 340 uint32_t temp;
igorsk 0:1063a091a062 341
igorsk 0:1063a091a062 342 //read for empty buffer
igorsk 0:1063a091a062 343 temp = SPIx->SPDR;
igorsk 0:1063a091a062 344 //dummy to clear status
igorsk 0:1063a091a062 345 temp = SPIx->SPSR;
igorsk 0:1063a091a062 346 dataCfg->counter = 0;
igorsk 0:1063a091a062 347 dataCfg->status = 0;
igorsk 0:1063a091a062 348
igorsk 0:1063a091a062 349 if (xfType == SPI_TRANSFER_POLLING){
igorsk 0:1063a091a062 350
igorsk 0:1063a091a062 351 if (spidat.dataword == 0){
igorsk 0:1063a091a062 352 rdata8 = (uint8_t *)dataCfg->rx_data;
igorsk 0:1063a091a062 353 wdata8 = (uint8_t *)dataCfg->tx_data;
igorsk 0:1063a091a062 354 } else {
igorsk 0:1063a091a062 355 rdata16 = (uint16_t *)dataCfg->rx_data;
igorsk 0:1063a091a062 356 wdata16 = (uint16_t *)dataCfg->tx_data;
igorsk 0:1063a091a062 357 }
igorsk 0:1063a091a062 358
igorsk 0:1063a091a062 359 while(dataCfg->counter < dataCfg->length)
igorsk 0:1063a091a062 360 {
igorsk 0:1063a091a062 361 // Write data to buffer
igorsk 0:1063a091a062 362 if(dataCfg->tx_data == NULL){
igorsk 0:1063a091a062 363 if (spidat.dataword == 0){
igorsk 0:1063a091a062 364 SPI_SendData(SPIx, 0xFF);
igorsk 0:1063a091a062 365 } else {
igorsk 0:1063a091a062 366 SPI_SendData(SPIx, 0xFFFF);
igorsk 0:1063a091a062 367 }
igorsk 0:1063a091a062 368 } else {
igorsk 0:1063a091a062 369 if (spidat.dataword == 0){
igorsk 0:1063a091a062 370 SPI_SendData(SPIx, *wdata8);
igorsk 0:1063a091a062 371 wdata8++;
igorsk 0:1063a091a062 372 } else {
igorsk 0:1063a091a062 373 SPI_SendData(SPIx, *wdata16);
igorsk 0:1063a091a062 374 wdata16++;
igorsk 0:1063a091a062 375 }
igorsk 0:1063a091a062 376 }
igorsk 0:1063a091a062 377 // Wait for transfer complete
igorsk 0:1063a091a062 378 while (!((stat = SPIx->SPSR) & SPI_SPSR_SPIF));
igorsk 0:1063a091a062 379 // Check for error
igorsk 0:1063a091a062 380 if (stat & (SPI_SPSR_ABRT | SPI_SPSR_MODF | SPI_SPSR_ROVR | SPI_SPSR_WCOL)){
igorsk 0:1063a091a062 381 // save status
igorsk 0:1063a091a062 382 dataCfg->status = stat | SPI_STAT_ERROR;
igorsk 0:1063a091a062 383 return (dataCfg->counter);
igorsk 0:1063a091a062 384 }
igorsk 0:1063a091a062 385 // Read data from SPI dat
igorsk 0:1063a091a062 386 temp = (uint32_t) SPI_ReceiveData(SPIx);
igorsk 0:1063a091a062 387
igorsk 0:1063a091a062 388 // Store data to destination
igorsk 0:1063a091a062 389 if (dataCfg->rx_data != NULL)
igorsk 0:1063a091a062 390 {
igorsk 0:1063a091a062 391 if (spidat.dataword == 0){
igorsk 0:1063a091a062 392 *(rdata8) = (uint8_t) temp;
igorsk 0:1063a091a062 393 rdata8++;
igorsk 0:1063a091a062 394 } else {
igorsk 0:1063a091a062 395 *(rdata16) = (uint16_t) temp;
igorsk 0:1063a091a062 396 rdata16++;
igorsk 0:1063a091a062 397 }
igorsk 0:1063a091a062 398 }
igorsk 0:1063a091a062 399 // Increase counter
igorsk 0:1063a091a062 400 if (spidat.dataword == 0){
igorsk 0:1063a091a062 401 dataCfg->counter++;
igorsk 0:1063a091a062 402 } else {
igorsk 0:1063a091a062 403 dataCfg->counter += 2;
igorsk 0:1063a091a062 404 }
igorsk 0:1063a091a062 405 }
igorsk 0:1063a091a062 406
igorsk 0:1063a091a062 407 // Return length of actual data transferred
igorsk 0:1063a091a062 408 // save status
igorsk 0:1063a091a062 409 dataCfg->status = stat | SPI_STAT_DONE;
igorsk 0:1063a091a062 410 return (dataCfg->counter);
igorsk 0:1063a091a062 411 }
igorsk 0:1063a091a062 412 // Interrupt mode
igorsk 0:1063a091a062 413 else {
igorsk 0:1063a091a062 414 spidat.txrx_setup = (uint32_t)dataCfg;
igorsk 0:1063a091a062 415 spidat.inthandler = SPI_IntHandler;
igorsk 0:1063a091a062 416
igorsk 0:1063a091a062 417 // Check if interrupt flag is already set
igorsk 0:1063a091a062 418 if(SPIx->SPINT & SPI_SPINT_INTFLAG){
igorsk 0:1063a091a062 419 SPIx->SPINT = SPI_SPINT_INTFLAG;
igorsk 0:1063a091a062 420 }
igorsk 0:1063a091a062 421 if (dataCfg->counter < dataCfg->length){
igorsk 0:1063a091a062 422 // Write data to buffer
igorsk 0:1063a091a062 423 if(dataCfg->tx_data == NULL){
igorsk 0:1063a091a062 424 if (spidat.dataword == 0){
igorsk 0:1063a091a062 425 SPI_SendData(SPIx, 0xFF);
igorsk 0:1063a091a062 426 } else {
igorsk 0:1063a091a062 427 SPI_SendData(SPIx, 0xFFFF);
igorsk 0:1063a091a062 428 }
igorsk 0:1063a091a062 429 } else {
igorsk 0:1063a091a062 430 if (spidat.dataword == 0){
igorsk 0:1063a091a062 431 SPI_SendData(SPIx, (*(uint8_t *)dataCfg->tx_data));
igorsk 0:1063a091a062 432 } else {
igorsk 0:1063a091a062 433 SPI_SendData(SPIx, (*(uint16_t *)dataCfg->tx_data));
igorsk 0:1063a091a062 434 }
igorsk 0:1063a091a062 435 }
igorsk 0:1063a091a062 436 SPI_IntCmd(SPIx, ENABLE);
igorsk 0:1063a091a062 437 } else {
igorsk 0:1063a091a062 438 // Save status
igorsk 0:1063a091a062 439 dataCfg->status = SPI_STAT_DONE;
igorsk 0:1063a091a062 440 }
igorsk 0:1063a091a062 441 return (0);
igorsk 0:1063a091a062 442 }
igorsk 0:1063a091a062 443 }
igorsk 0:1063a091a062 444
igorsk 0:1063a091a062 445
igorsk 0:1063a091a062 446 /********************************************************************//**
igorsk 0:1063a091a062 447 * @brief Enable or disable SPIx interrupt.
igorsk 0:1063a091a062 448 * @param[in] SPIx SPI peripheral selected, should be SPI
igorsk 0:1063a091a062 449 * @param[in] NewState New state of specified UART interrupt type,
igorsk 0:1063a091a062 450 * should be:
igorsk 0:1063a091a062 451 * - ENALBE: Enable this SPI interrupt.
igorsk 0:1063a091a062 452 * - DISALBE: Disable this SPI interrupt.
igorsk 0:1063a091a062 453 * @return None
igorsk 0:1063a091a062 454 *********************************************************************/
igorsk 0:1063a091a062 455 void SPI_IntCmd(LPC_SPI_TypeDef *SPIx, FunctionalState NewState)
igorsk 0:1063a091a062 456 {
igorsk 0:1063a091a062 457 CHECK_PARAM(PARAM_SPIx(SPIx));
igorsk 0:1063a091a062 458 CHECK_PARAM(PARAM_FUNCTIONALSTATE(NewState));
igorsk 0:1063a091a062 459
igorsk 0:1063a091a062 460 if (NewState == ENABLE)
igorsk 0:1063a091a062 461 {
igorsk 0:1063a091a062 462 SPIx->SPCR |= SPI_SPCR_SPIE;
igorsk 0:1063a091a062 463 }
igorsk 0:1063a091a062 464 else
igorsk 0:1063a091a062 465 {
igorsk 0:1063a091a062 466 SPIx->SPCR &= (~SPI_SPCR_SPIE) & SPI_SPCR_BITMASK;
igorsk 0:1063a091a062 467 }
igorsk 0:1063a091a062 468 }
igorsk 0:1063a091a062 469
igorsk 0:1063a091a062 470
igorsk 0:1063a091a062 471 /********************************************************************//**
igorsk 0:1063a091a062 472 * @brief Checks whether the SPI interrupt flag is set or not.
igorsk 0:1063a091a062 473 * @param[in] SPIx SPI peripheral selected, should be SPI
igorsk 0:1063a091a062 474 * @return The new state of SPI Interrupt Flag (SET or RESET)
igorsk 0:1063a091a062 475 *********************************************************************/
igorsk 0:1063a091a062 476 IntStatus SPI_GetIntStatus (LPC_SPI_TypeDef *SPIx)
igorsk 0:1063a091a062 477 {
igorsk 0:1063a091a062 478 CHECK_PARAM(PARAM_SPIx(SPIx));
igorsk 0:1063a091a062 479
igorsk 0:1063a091a062 480 return ((SPIx->SPINT & SPI_SPINT_INTFLAG) ? SET : RESET);
igorsk 0:1063a091a062 481 }
igorsk 0:1063a091a062 482
igorsk 0:1063a091a062 483
igorsk 0:1063a091a062 484 /********************************************************************//**
igorsk 0:1063a091a062 485 * @brief Clear SPI interrupt flag.
igorsk 0:1063a091a062 486 * @param[in] SPIx SPI peripheral selected, should be SPI
igorsk 0:1063a091a062 487 * @return None
igorsk 0:1063a091a062 488 *********************************************************************/
igorsk 0:1063a091a062 489 void SPI_ClearIntPending(LPC_SPI_TypeDef *SPIx)
igorsk 0:1063a091a062 490 {
igorsk 0:1063a091a062 491 CHECK_PARAM(PARAM_SPIx(SPIx));
igorsk 0:1063a091a062 492
igorsk 0:1063a091a062 493 SPIx->SPINT = SPI_SPINT_INTFLAG;
igorsk 0:1063a091a062 494 }
igorsk 0:1063a091a062 495
igorsk 0:1063a091a062 496
igorsk 0:1063a091a062 497 /********************************************************************//**
igorsk 0:1063a091a062 498 * @brief Get current value of SPI Status register in SPIx peripheral.
igorsk 0:1063a091a062 499 * @param[in] SPIx SPI peripheral selected, should be SPI
igorsk 0:1063a091a062 500 * @return Current value of SPI Status register in SPI peripheral.
igorsk 0:1063a091a062 501 * Note: The return value of this function must be used with
igorsk 0:1063a091a062 502 * SPI_CheckStatus() to determine current flag status
igorsk 0:1063a091a062 503 * corresponding to each SPI status type. Because some flags in
igorsk 0:1063a091a062 504 * SPI Status register will be cleared after reading, the next reading
igorsk 0:1063a091a062 505 * SPI Status register could not be correct. So this function used to
igorsk 0:1063a091a062 506 * read SPI status register in one time only, then the return value
igorsk 0:1063a091a062 507 * used to check all flags.
igorsk 0:1063a091a062 508 *********************************************************************/
igorsk 0:1063a091a062 509 uint32_t SPI_GetStatus(LPC_SPI_TypeDef* SPIx)
igorsk 0:1063a091a062 510 {
igorsk 0:1063a091a062 511 CHECK_PARAM(PARAM_SPIx(SPIx));
igorsk 0:1063a091a062 512
igorsk 0:1063a091a062 513 return (SPIx->SPSR & SPI_SPSR_BITMASK);
igorsk 0:1063a091a062 514 }
igorsk 0:1063a091a062 515
igorsk 0:1063a091a062 516
igorsk 0:1063a091a062 517
igorsk 0:1063a091a062 518 /********************************************************************//**
igorsk 0:1063a091a062 519 * @brief Checks whether the specified SPI Status flag is set or not
igorsk 0:1063a091a062 520 * via inputSPIStatus parameter.
igorsk 0:1063a091a062 521 * @param[in] inputSPIStatus Value to check status of each flag type.
igorsk 0:1063a091a062 522 * This value is the return value from SPI_GetStatus().
igorsk 0:1063a091a062 523 * @param[in] SPIStatus Specifies the SPI status flag to check,
igorsk 0:1063a091a062 524 * should be one of the following:
igorsk 0:1063a091a062 525 - SPI_STAT_ABRT: Slave abort.
igorsk 0:1063a091a062 526 - SPI_STAT_MODF: Mode fault.
igorsk 0:1063a091a062 527 - SPI_STAT_ROVR: Read overrun.
igorsk 0:1063a091a062 528 - SPI_STAT_WCOL: Write collision.
igorsk 0:1063a091a062 529 - SPI_STAT_SPIF: SPI transfer complete.
igorsk 0:1063a091a062 530 * @return The new state of SPIStatus (SET or RESET)
igorsk 0:1063a091a062 531 *********************************************************************/
igorsk 0:1063a091a062 532 FlagStatus SPI_CheckStatus (uint32_t inputSPIStatus, uint8_t SPIStatus)
igorsk 0:1063a091a062 533 {
igorsk 0:1063a091a062 534 CHECK_PARAM(PARAM_SPI_STAT(SPIStatus));
igorsk 0:1063a091a062 535
igorsk 0:1063a091a062 536 return ((inputSPIStatus & SPIStatus) ? SET : RESET);
igorsk 0:1063a091a062 537 }
igorsk 0:1063a091a062 538
igorsk 0:1063a091a062 539 /**
igorsk 0:1063a091a062 540 * @brief Standard SPI Interrupt handler
igorsk 0:1063a091a062 541 * @param[in] None
igorsk 0:1063a091a062 542 * @return None
igorsk 0:1063a091a062 543 */
igorsk 0:1063a091a062 544 void SPI_StdIntHandler(void)
igorsk 0:1063a091a062 545 {
igorsk 0:1063a091a062 546 // Call relevant handler
igorsk 0:1063a091a062 547 spidat.inthandler();
igorsk 0:1063a091a062 548 }
igorsk 0:1063a091a062 549
igorsk 0:1063a091a062 550
igorsk 0:1063a091a062 551 /**
igorsk 0:1063a091a062 552 * @}
igorsk 0:1063a091a062 553 */
igorsk 0:1063a091a062 554
igorsk 0:1063a091a062 555 #endif /* _SPI */
igorsk 0:1063a091a062 556
igorsk 0:1063a091a062 557 /**
igorsk 0:1063a091a062 558 * @}
igorsk 0:1063a091a062 559 */
igorsk 0:1063a091a062 560
igorsk 0:1063a091a062 561 /* --------------------------------- End Of File ------------------------------ */