mbed library sources

Dependents:   Encrypted my_mbed lklk CyaSSL_DTLS_Cellular ... more

Superseded

This library was superseded by mbed-dev - https://os.mbed.com/users/mbed_official/code/mbed-dev/.

Development branch of the mbed library sources. This library is kept in synch with the latest changes from the mbed SDK and it is not guaranteed to work.

If you are looking for a stable and tested release, please import one of the official mbed library releases:

Import librarymbed

The official Mbed 2 C/C++ SDK provides the software platform and libraries to build your applications.

Committer:
mbed_official
Date:
Wed Jun 10 10:00:08 2015 +0100
Revision:
563:536c9fb088a0
Parent:
549:99e4f6522a2d
Child:
564:24a7119bd73a
Synchronized with git revision 4778e33fa11602202ae3a57ced5d026e8053cedf

Full URL: https://github.com/mbedmicro/mbed/commit/4778e33fa11602202ae3a57ced5d026e8053cedf/

Fix asynch methods constness

Who changed what in which revision?

UserRevisionLine numberNew contents of line
mbed_official 525:c320967f86b9 1 /* mbed Microcontroller Library
mbed_official 525:c320967f86b9 2 * Copyright (c) 2006-2013 ARM Limited
mbed_official 525:c320967f86b9 3 *
mbed_official 525:c320967f86b9 4 * Licensed under the Apache License, Version 2.0 (the "License");
mbed_official 525:c320967f86b9 5 * you may not use this file except in compliance with the License.
mbed_official 525:c320967f86b9 6 * You may obtain a copy of the License at
mbed_official 525:c320967f86b9 7 *
mbed_official 525:c320967f86b9 8 * http://www.apache.org/licenses/LICENSE-2.0
mbed_official 525:c320967f86b9 9 *
mbed_official 525:c320967f86b9 10 * Unless required by applicable law or agreed to in writing, software
mbed_official 525:c320967f86b9 11 * distributed under the License is distributed on an "AS IS" BASIS,
mbed_official 525:c320967f86b9 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
mbed_official 525:c320967f86b9 13 * See the License for the specific language governing permissions and
mbed_official 525:c320967f86b9 14 * limitations under the License.
mbed_official 525:c320967f86b9 15 */
mbed_official 525:c320967f86b9 16 #include "device.h"
mbed_official 525:c320967f86b9 17 #include "clocking.h"
mbed_official 525:c320967f86b9 18 #if DEVICE_SPI
mbed_official 525:c320967f86b9 19
mbed_official 525:c320967f86b9 20 #include "mbed_assert.h"
mbed_official 525:c320967f86b9 21 #include "PeripheralPins.h"
mbed_official 525:c320967f86b9 22 #include "pinmap.h"
mbed_official 525:c320967f86b9 23 #include "pinmap_function.h"
mbed_official 525:c320967f86b9 24 #include "error.h"
mbed_official 525:c320967f86b9 25
mbed_official 525:c320967f86b9 26 #include "dma_api.h"
mbed_official 525:c320967f86b9 27 #include "dma_api_HAL.h"
mbed_official 525:c320967f86b9 28 #include "spi_api.h"
mbed_official 525:c320967f86b9 29 #include "em_usart.h"
mbed_official 525:c320967f86b9 30 #include "em_cmu.h"
mbed_official 525:c320967f86b9 31 #include "em_dma.h"
mbed_official 525:c320967f86b9 32 #include "sleep_api.h"
mbed_official 526:7c4bdfe6a168 33 #include "sleepmodes.h"
mbed_official 525:c320967f86b9 34
mbed_official 525:c320967f86b9 35 static uint16_t fill_word = SPI_FILL_WORD;
mbed_official 525:c320967f86b9 36 #define SPI_LEAST_ACTIVE_SLEEPMODE EM1
mbed_official 525:c320967f86b9 37
mbed_official 548:1abac31e188e 38 inline CMU_Clock_TypeDef spi_get_clock_tree(spi_t *obj)
mbed_official 548:1abac31e188e 39 {
mbed_official 525:c320967f86b9 40 switch ((int)obj->spi.spi) {
mbed_official 525:c320967f86b9 41 #ifdef USART0
mbed_official 525:c320967f86b9 42 case SPI_0:
mbed_official 525:c320967f86b9 43 return cmuClock_USART0;
mbed_official 525:c320967f86b9 44 #endif
mbed_official 525:c320967f86b9 45 #ifdef USART1
mbed_official 525:c320967f86b9 46 case SPI_1:
mbed_official 525:c320967f86b9 47 return cmuClock_USART1;
mbed_official 525:c320967f86b9 48 #endif
mbed_official 525:c320967f86b9 49 #ifdef USART2
mbed_official 525:c320967f86b9 50 case SPI_2:
mbed_official 525:c320967f86b9 51 return cmuClock_USART2;
mbed_official 525:c320967f86b9 52 #endif
mbed_official 525:c320967f86b9 53 default:
mbed_official 525:c320967f86b9 54 error("Spi module not available.. Out of bound access.");
mbed_official 525:c320967f86b9 55 return cmuClock_HFPER;
mbed_official 525:c320967f86b9 56 }
mbed_official 525:c320967f86b9 57 }
mbed_official 525:c320967f86b9 58
mbed_official 525:c320967f86b9 59 inline uint8_t spi_get_index(spi_t *obj)
mbed_official 525:c320967f86b9 60 {
mbed_official 525:c320967f86b9 61 uint8_t index = 0;
mbed_official 525:c320967f86b9 62 switch ((int)obj->spi.spi) {
mbed_official 525:c320967f86b9 63 #ifdef USART0
mbed_official 525:c320967f86b9 64 case SPI_0:
mbed_official 525:c320967f86b9 65 index = 0;
mbed_official 525:c320967f86b9 66 break;
mbed_official 525:c320967f86b9 67 #endif
mbed_official 525:c320967f86b9 68 #ifdef USART1
mbed_official 525:c320967f86b9 69 case SPI_1:
mbed_official 525:c320967f86b9 70 index = 1;
mbed_official 525:c320967f86b9 71 break;
mbed_official 525:c320967f86b9 72 #endif
mbed_official 525:c320967f86b9 73 #ifdef USART2
mbed_official 525:c320967f86b9 74 case SPI_2:
mbed_official 525:c320967f86b9 75 index = 2;
mbed_official 525:c320967f86b9 76 break;
mbed_official 525:c320967f86b9 77 #endif
mbed_official 525:c320967f86b9 78 default:
mbed_official 525:c320967f86b9 79 error("Spi module not available.. Out of bound access.");
mbed_official 525:c320967f86b9 80 break;
mbed_official 525:c320967f86b9 81 }
mbed_official 525:c320967f86b9 82 return index;
mbed_official 525:c320967f86b9 83 }
mbed_official 525:c320967f86b9 84
mbed_official 548:1abac31e188e 85 uint8_t spi_get_module(spi_t *obj)
mbed_official 548:1abac31e188e 86 {
mbed_official 525:c320967f86b9 87 return spi_get_index(obj);
mbed_official 525:c320967f86b9 88 }
mbed_official 525:c320967f86b9 89
mbed_official 525:c320967f86b9 90 static void usart_init(spi_t *obj, uint32_t baudrate, USART_Databits_TypeDef databits, bool master, USART_ClockMode_TypeDef clockMode )
mbed_official 525:c320967f86b9 91 {
mbed_official 525:c320967f86b9 92 USART_InitSync_TypeDef init = USART_INITSYNC_DEFAULT;
mbed_official 525:c320967f86b9 93 init.enable = usartDisable;
mbed_official 525:c320967f86b9 94 init.baudrate = baudrate;
mbed_official 525:c320967f86b9 95 init.databits = databits;
mbed_official 525:c320967f86b9 96 init.master = master;
mbed_official 525:c320967f86b9 97 init.msbf = 1;
mbed_official 525:c320967f86b9 98 init.clockMode = clockMode;
mbed_official 525:c320967f86b9 99
mbed_official 525:c320967f86b9 100 /* Determine the reference clock, because the correct clock is not set up at init time */
mbed_official 525:c320967f86b9 101 init.refFreq = REFERENCE_FREQUENCY;
mbed_official 525:c320967f86b9 102
mbed_official 525:c320967f86b9 103 USART_InitSync(obj->spi.spi, &init);
mbed_official 525:c320967f86b9 104 }
mbed_official 525:c320967f86b9 105
mbed_official 525:c320967f86b9 106 void spi_preinit(spi_t *obj, PinName mosi, PinName miso, PinName clk, PinName cs)
mbed_official 525:c320967f86b9 107 {
mbed_official 525:c320967f86b9 108 SPIName spi_mosi = (SPIName) pinmap_peripheral(mosi, PinMap_SPI_MOSI);
mbed_official 525:c320967f86b9 109 SPIName spi_miso = (SPIName) pinmap_peripheral(miso, PinMap_SPI_MISO);
mbed_official 525:c320967f86b9 110 SPIName spi_clk = (SPIName) pinmap_peripheral(clk, PinMap_SPI_CLK);
mbed_official 525:c320967f86b9 111 SPIName spi_cs = (SPIName) pinmap_peripheral(cs, PinMap_SPI_CS);
mbed_official 525:c320967f86b9 112 SPIName spi_data = (SPIName) pinmap_merge(spi_mosi, spi_miso);
mbed_official 525:c320967f86b9 113 SPIName spi_ctrl = (SPIName) pinmap_merge(spi_clk, spi_cs);
mbed_official 525:c320967f86b9 114
mbed_official 525:c320967f86b9 115 obj->spi.spi = (USART_TypeDef *) pinmap_merge(spi_data, spi_ctrl);
mbed_official 525:c320967f86b9 116 MBED_ASSERT((int) obj->spi.spi != NC);
mbed_official 525:c320967f86b9 117
mbed_official 525:c320967f86b9 118 if (cs != NC) { /* Slave mode */
mbed_official 525:c320967f86b9 119 obj->spi.master = false;
mbed_official 525:c320967f86b9 120 } else {
mbed_official 525:c320967f86b9 121 obj->spi.master = true;
mbed_official 525:c320967f86b9 122 }
mbed_official 525:c320967f86b9 123
mbed_official 525:c320967f86b9 124 uint32_t loc_mosi = pin_location(mosi, PinMap_SPI_MOSI);
mbed_official 525:c320967f86b9 125 uint32_t loc_miso = pin_location(miso, PinMap_SPI_MISO);
mbed_official 525:c320967f86b9 126 uint32_t loc_clk = pin_location(clk, PinMap_SPI_CLK);
mbed_official 525:c320967f86b9 127 uint32_t loc_cs = pin_location(cs, PinMap_SPI_CS);
mbed_official 525:c320967f86b9 128 uint32_t loc_data = pinmap_merge(loc_mosi, loc_miso);
mbed_official 525:c320967f86b9 129 uint32_t loc_ctrl = pinmap_merge(loc_clk, loc_cs);
mbed_official 525:c320967f86b9 130 obj->spi.location = pinmap_merge(loc_data, loc_ctrl);
mbed_official 525:c320967f86b9 131 MBED_ASSERT(obj->spi.location != NC);
mbed_official 525:c320967f86b9 132
mbed_official 525:c320967f86b9 133 obj->spi.dmaOptionsTX.dmaUsageState = DMA_USAGE_OPPORTUNISTIC;
mbed_official 525:c320967f86b9 134 }
mbed_official 525:c320967f86b9 135
mbed_official 525:c320967f86b9 136 void spi_enable_pins(spi_t *obj, uint8_t enable, PinName mosi, PinName miso, PinName clk, PinName cs)
mbed_official 525:c320967f86b9 137 {
mbed_official 525:c320967f86b9 138 if (enable) {
mbed_official 525:c320967f86b9 139 if (obj->spi.master) { /* Master mode */
mbed_official 525:c320967f86b9 140 /* Either mosi or miso can be NC */
mbed_official 525:c320967f86b9 141 if (mosi != NC) {
mbed_official 525:c320967f86b9 142 pin_mode(mosi, PushPull);
mbed_official 525:c320967f86b9 143 }
mbed_official 525:c320967f86b9 144 if (miso != NC) {
mbed_official 525:c320967f86b9 145 pin_mode(miso, Input);
mbed_official 525:c320967f86b9 146 }
mbed_official 525:c320967f86b9 147 pin_mode(clk, PushPull);
mbed_official 525:c320967f86b9 148 /* Don't set cs pin, since we toggle it manually */
mbed_official 525:c320967f86b9 149 } else { /* Slave mode */
mbed_official 525:c320967f86b9 150 if (mosi != NC) {
mbed_official 525:c320967f86b9 151 pin_mode(mosi, Input);
mbed_official 525:c320967f86b9 152 }
mbed_official 525:c320967f86b9 153 if (miso != NC) {
mbed_official 525:c320967f86b9 154 pin_mode(miso, PushPull);
mbed_official 525:c320967f86b9 155 }
mbed_official 525:c320967f86b9 156 pin_mode(clk, Input);
mbed_official 525:c320967f86b9 157 pin_mode(cs, Input);
mbed_official 525:c320967f86b9 158 }
mbed_official 525:c320967f86b9 159 } else {
mbed_official 525:c320967f86b9 160 // TODO_LP return PinMode to the previous state
mbed_official 525:c320967f86b9 161 if (obj->spi.master) { /* Master mode */
mbed_official 525:c320967f86b9 162 /* Either mosi or miso can be NC */
mbed_official 525:c320967f86b9 163 if (mosi != NC) {
mbed_official 525:c320967f86b9 164 pin_mode(mosi, Disabled);
mbed_official 525:c320967f86b9 165 }
mbed_official 525:c320967f86b9 166 if (miso != NC) {
mbed_official 525:c320967f86b9 167 pin_mode(miso, Disabled);
mbed_official 525:c320967f86b9 168 }
mbed_official 525:c320967f86b9 169 pin_mode(clk, Disabled);
mbed_official 525:c320967f86b9 170 /* Don't set cs pin, since we toggle it manually */
mbed_official 525:c320967f86b9 171 } else { /* Slave mode */
mbed_official 525:c320967f86b9 172 if (mosi != NC) {
mbed_official 525:c320967f86b9 173 pin_mode(mosi, Disabled);
mbed_official 525:c320967f86b9 174 }
mbed_official 525:c320967f86b9 175 if (miso != NC) {
mbed_official 525:c320967f86b9 176 pin_mode(miso, Disabled);
mbed_official 525:c320967f86b9 177 }
mbed_official 525:c320967f86b9 178 pin_mode(clk, Disabled);
mbed_official 525:c320967f86b9 179 pin_mode(cs, Disabled);
mbed_official 525:c320967f86b9 180 }
mbed_official 525:c320967f86b9 181 }
mbed_official 525:c320967f86b9 182
mbed_official 525:c320967f86b9 183 /* Enabling pins and setting location */
mbed_official 525:c320967f86b9 184 uint32_t route = USART_ROUTE_CLKPEN | (obj->spi.location << _USART_ROUTE_LOCATION_SHIFT);
mbed_official 525:c320967f86b9 185
mbed_official 525:c320967f86b9 186 if (mosi != NC) {
mbed_official 525:c320967f86b9 187 route |= USART_ROUTE_TXPEN;
mbed_official 525:c320967f86b9 188 }
mbed_official 525:c320967f86b9 189 if (miso != NC) {
mbed_official 525:c320967f86b9 190 route |= USART_ROUTE_RXPEN;
mbed_official 525:c320967f86b9 191 }
mbed_official 525:c320967f86b9 192 if (!obj->spi.master) {
mbed_official 525:c320967f86b9 193 route |= USART_ROUTE_CSPEN;
mbed_official 525:c320967f86b9 194 }
mbed_official 525:c320967f86b9 195 obj->spi.spi->ROUTE = route;
mbed_official 525:c320967f86b9 196 }
mbed_official 525:c320967f86b9 197
mbed_official 525:c320967f86b9 198 void spi_enable(spi_t *obj, uint8_t enable)
mbed_official 525:c320967f86b9 199 {
mbed_official 525:c320967f86b9 200 USART_Enable(obj->spi.spi, (enable ? usartEnable : usartDisable));
mbed_official 525:c320967f86b9 201 }
mbed_official 525:c320967f86b9 202
mbed_official 525:c320967f86b9 203 void spi_init(spi_t *obj, PinName mosi, PinName miso, PinName clk, PinName cs)
mbed_official 525:c320967f86b9 204 {
mbed_official 548:1abac31e188e 205 CMU_ClockEnable(cmuClock_HFPER, true);
mbed_official 548:1abac31e188e 206 spi_preinit(obj, mosi, miso, clk, cs);
mbed_official 548:1abac31e188e 207 CMU_ClockEnable(spi_get_clock_tree(obj), true);
mbed_official 548:1abac31e188e 208 usart_init(obj, 100000, usartDatabits8, true, usartClockMode0);
mbed_official 525:c320967f86b9 209
mbed_official 548:1abac31e188e 210 spi_enable_pins(obj, true, mosi, miso, clk, cs);
mbed_official 525:c320967f86b9 211 spi_enable(obj, true);
mbed_official 525:c320967f86b9 212 }
mbed_official 525:c320967f86b9 213
mbed_official 525:c320967f86b9 214 void spi_enable_event(spi_t *obj, uint32_t event, uint8_t enable)
mbed_official 525:c320967f86b9 215 {
mbed_official 525:c320967f86b9 216 if(enable) obj->spi.event |= event;
mbed_official 525:c320967f86b9 217 else obj->spi.event &= ~event;
mbed_official 525:c320967f86b9 218 }
mbed_official 525:c320967f86b9 219
mbed_official 525:c320967f86b9 220 /****************************************************************************
mbed_official 525:c320967f86b9 221 * void spi_enable_interrupt(spi_t *obj, uint32_t handler, uint8_t enable)
mbed_official 525:c320967f86b9 222 *
mbed_official 525:c320967f86b9 223 * This will enable the interrupt in NVIC for the associated USART RX channel
mbed_official 525:c320967f86b9 224 *
mbed_official 525:c320967f86b9 225 * * obj: pointer to spi object
mbed_official 525:c320967f86b9 226 * * handler: pointer to interrupt handler for this channel
mbed_official 525:c320967f86b9 227 * * enable: Whether to enable (true) or disable (false) the interrupt
mbed_official 525:c320967f86b9 228 *
mbed_official 525:c320967f86b9 229 ****************************************************************************/
mbed_official 525:c320967f86b9 230 void spi_enable_interrupt(spi_t *obj, uint32_t handler, uint8_t enable)
mbed_official 525:c320967f86b9 231 {
mbed_official 525:c320967f86b9 232 IRQn_Type IRQvector;
mbed_official 525:c320967f86b9 233
mbed_official 525:c320967f86b9 234 switch ((uint32_t)obj->spi.spi) {
mbed_official 525:c320967f86b9 235 #ifdef USART0
mbed_official 525:c320967f86b9 236 case USART_0:
mbed_official 525:c320967f86b9 237 IRQvector = USART0_RX_IRQn;
mbed_official 525:c320967f86b9 238 break;
mbed_official 525:c320967f86b9 239 #endif
mbed_official 525:c320967f86b9 240 #ifdef USART1
mbed_official 525:c320967f86b9 241 case USART_1:
mbed_official 525:c320967f86b9 242 IRQvector = USART1_RX_IRQn;
mbed_official 525:c320967f86b9 243 break;
mbed_official 525:c320967f86b9 244 #endif
mbed_official 525:c320967f86b9 245 #ifdef USART2
mbed_official 525:c320967f86b9 246 case USART_2:
mbed_official 525:c320967f86b9 247 IRQvector = USART2_RX_IRQn;
mbed_official 525:c320967f86b9 248 break;
mbed_official 525:c320967f86b9 249 #endif
mbed_official 525:c320967f86b9 250 default:
mbed_official 525:c320967f86b9 251 error("Undefined SPI peripheral");
mbed_official 525:c320967f86b9 252 return;
mbed_official 525:c320967f86b9 253 }
mbed_official 525:c320967f86b9 254
mbed_official 525:c320967f86b9 255 if (enable == true) {
mbed_official 525:c320967f86b9 256 NVIC_SetVector(IRQvector, handler);
mbed_official 525:c320967f86b9 257 USART_IntEnable(obj->spi.spi, USART_IEN_RXDATAV);
mbed_official 525:c320967f86b9 258 NVIC_EnableIRQ(IRQvector);
mbed_official 548:1abac31e188e 259 } else {
mbed_official 525:c320967f86b9 260 NVIC_SetVector(IRQvector, handler);
mbed_official 525:c320967f86b9 261 USART_IntDisable(obj->spi.spi, USART_IEN_RXDATAV);
mbed_official 525:c320967f86b9 262 NVIC_DisableIRQ(IRQvector);
mbed_official 525:c320967f86b9 263 }
mbed_official 525:c320967f86b9 264 }
mbed_official 525:c320967f86b9 265
mbed_official 525:c320967f86b9 266 void spi_format(spi_t *obj, int bits, int mode, int slave)
mbed_official 525:c320967f86b9 267 {
mbed_official 525:c320967f86b9 268 /* Bits: values between 4 and 16 are valid */
mbed_official 525:c320967f86b9 269 MBED_ASSERT(bits >= 4 && bits <= 16);
mbed_official 525:c320967f86b9 270 obj->spi.bits = bits;
mbed_official 525:c320967f86b9 271 /* 0x01 = usartDatabits4, etc, up to 0x0D = usartDatabits16 */
mbed_official 525:c320967f86b9 272 USART_Databits_TypeDef databits = (USART_Databits_TypeDef) (bits - 3);
mbed_official 525:c320967f86b9 273
mbed_official 525:c320967f86b9 274 USART_ClockMode_TypeDef clockMode;
mbed_official 525:c320967f86b9 275 MBED_ASSERT(mode >= 0 && mode <= 3);
mbed_official 525:c320967f86b9 276 switch (mode) {
mbed_official 525:c320967f86b9 277 case 0:
mbed_official 525:c320967f86b9 278 clockMode = usartClockMode0;
mbed_official 525:c320967f86b9 279 break;
mbed_official 525:c320967f86b9 280 case 1:
mbed_official 525:c320967f86b9 281 clockMode = usartClockMode1;
mbed_official 525:c320967f86b9 282 break;
mbed_official 525:c320967f86b9 283 case 2:
mbed_official 525:c320967f86b9 284 clockMode = usartClockMode2;
mbed_official 525:c320967f86b9 285 break;
mbed_official 525:c320967f86b9 286 case 3:
mbed_official 525:c320967f86b9 287 clockMode = usartClockMode3;
mbed_official 525:c320967f86b9 288 break;
mbed_official 525:c320967f86b9 289 default:
mbed_official 525:c320967f86b9 290 clockMode = usartClockMode0;
mbed_official 525:c320967f86b9 291 }
mbed_official 525:c320967f86b9 292
mbed_official 525:c320967f86b9 293 //save state
mbed_official 525:c320967f86b9 294 uint32_t route = obj->spi.spi->ROUTE;
mbed_official 525:c320967f86b9 295 uint32_t iflags = obj->spi.spi->IEN;
mbed_official 525:c320967f86b9 296 bool enabled = (obj->spi.spi->STATUS & (USART_STATUS_RXENS | USART_STATUS_TXENS)) != 0;
mbed_official 525:c320967f86b9 297
mbed_official 525:c320967f86b9 298 usart_init(obj, 100000, databits, (slave ? false : true), clockMode);
mbed_official 525:c320967f86b9 299
mbed_official 525:c320967f86b9 300 //restore state
mbed_official 525:c320967f86b9 301 obj->spi.spi->ROUTE = route;
mbed_official 525:c320967f86b9 302 obj->spi.spi->IEN = iflags;
mbed_official 525:c320967f86b9 303
mbed_official 525:c320967f86b9 304 if(enabled) spi_enable(obj, enabled);
mbed_official 525:c320967f86b9 305 }
mbed_official 525:c320967f86b9 306
mbed_official 525:c320967f86b9 307 void spi_frequency(spi_t *obj, int hz)
mbed_official 525:c320967f86b9 308 {
mbed_official 525:c320967f86b9 309 USART_BaudrateSyncSet(obj->spi.spi, REFERENCE_FREQUENCY, hz);
mbed_official 525:c320967f86b9 310 }
mbed_official 525:c320967f86b9 311
mbed_official 525:c320967f86b9 312 /* Read/Write */
mbed_official 525:c320967f86b9 313
mbed_official 525:c320967f86b9 314 void spi_write(spi_t *obj, int value)
mbed_official 525:c320967f86b9 315 {
mbed_official 525:c320967f86b9 316 if (obj->spi.bits <= 8) {
mbed_official 525:c320967f86b9 317 USART_Tx(obj->spi.spi, (uint8_t) value);
mbed_official 525:c320967f86b9 318 } else if (obj->spi.bits == 9) {
mbed_official 525:c320967f86b9 319 USART_TxExt(obj->spi.spi, (uint16_t) value & 0x1FF);
mbed_official 525:c320967f86b9 320 } else {
mbed_official 525:c320967f86b9 321 USART_TxDouble(obj->spi.spi, (uint16_t) value);
mbed_official 525:c320967f86b9 322 }
mbed_official 525:c320967f86b9 323 }
mbed_official 525:c320967f86b9 324
mbed_official 525:c320967f86b9 325 int spi_read(spi_t *obj)
mbed_official 525:c320967f86b9 326 {
mbed_official 525:c320967f86b9 327 if (obj->spi.bits <= 8) {
mbed_official 525:c320967f86b9 328 return (int) obj->spi.spi->RXDATA;
mbed_official 525:c320967f86b9 329 } else if (obj->spi.bits == 9) {
mbed_official 525:c320967f86b9 330 return (int) obj->spi.spi->RXDATAX & 0x1FF;
mbed_official 525:c320967f86b9 331 } else {
mbed_official 525:c320967f86b9 332 return (int) obj->spi.spi->RXDOUBLE;
mbed_official 525:c320967f86b9 333 }
mbed_official 525:c320967f86b9 334 }
mbed_official 525:c320967f86b9 335
mbed_official 525:c320967f86b9 336 int spi_read_asynch(spi_t *obj)
mbed_official 525:c320967f86b9 337 {
mbed_official 525:c320967f86b9 338 return spi_read(obj);
mbed_official 525:c320967f86b9 339 }
mbed_official 525:c320967f86b9 340
mbed_official 525:c320967f86b9 341 int spi_master_write(spi_t *obj, int value)
mbed_official 525:c320967f86b9 342 {
mbed_official 525:c320967f86b9 343 spi_write(obj, value);
mbed_official 525:c320967f86b9 344
mbed_official 525:c320967f86b9 345 /* Wait for transmission of last byte */
mbed_official 525:c320967f86b9 346 while (!(obj->spi.spi->STATUS & USART_STATUS_TXC)) {
mbed_official 525:c320967f86b9 347 sleep(); // TODO_LP this might break other code, write should be separate from read?
mbed_official 525:c320967f86b9 348 }
mbed_official 525:c320967f86b9 349
mbed_official 525:c320967f86b9 350 return spi_read(obj);
mbed_official 525:c320967f86b9 351 }
mbed_official 525:c320967f86b9 352
mbed_official 525:c320967f86b9 353 inline uint8_t spi_master_tx_ready(spi_t *obj)
mbed_official 525:c320967f86b9 354 {
mbed_official 525:c320967f86b9 355 return (obj->spi.spi->STATUS & USART_STATUS_TXBL) ? true : false;
mbed_official 525:c320967f86b9 356 }
mbed_official 525:c320967f86b9 357
mbed_official 525:c320967f86b9 358 uint8_t spi_master_rx_ready(spi_t *obj)
mbed_official 525:c320967f86b9 359 {
mbed_official 525:c320967f86b9 360 return (obj->spi.spi->STATUS & USART_STATUS_RXDATAV) ? true : false;
mbed_official 525:c320967f86b9 361 }
mbed_official 525:c320967f86b9 362
mbed_official 525:c320967f86b9 363 uint8_t spi_master_tx_int_flag(spi_t *obj)
mbed_official 525:c320967f86b9 364 {
mbed_official 525:c320967f86b9 365 return (obj->spi.spi->IF & USART_IF_TXBL) ? true : false;
mbed_official 525:c320967f86b9 366 }
mbed_official 525:c320967f86b9 367
mbed_official 525:c320967f86b9 368 uint8_t spi_master_rx_int_flag(spi_t *obj)
mbed_official 525:c320967f86b9 369 {
mbed_official 525:c320967f86b9 370 return (obj->spi.spi->IF & (USART_IF_RXDATAV | USART_IF_RXFULL)) ? true : false;
mbed_official 525:c320967f86b9 371 }
mbed_official 525:c320967f86b9 372
mbed_official 525:c320967f86b9 373 void spi_master_read_asynch_complete(spi_t *obj)
mbed_official 525:c320967f86b9 374 {
mbed_official 525:c320967f86b9 375 obj->spi.spi->IFC = USART_IFC_RXFULL; // in case it got full
mbed_official 525:c320967f86b9 376 }
mbed_official 525:c320967f86b9 377
mbed_official 525:c320967f86b9 378 void spi_master_write_asynch_complete(spi_t *obj)
mbed_official 525:c320967f86b9 379 {
mbed_official 525:c320967f86b9 380 obj->spi.spi->IFC = USART_IFC_TXC;
mbed_official 525:c320967f86b9 381 }
mbed_official 525:c320967f86b9 382
mbed_official 525:c320967f86b9 383 void spi_irq_handler(spi_t *obj)
mbed_official 525:c320967f86b9 384 {
mbed_official 525:c320967f86b9 385 spi_read(obj); //TODO_LP store data to the object?
mbed_official 525:c320967f86b9 386 }
mbed_official 525:c320967f86b9 387
mbed_official 525:c320967f86b9 388 uint8_t spi_active(spi_t *obj)
mbed_official 525:c320967f86b9 389 {
mbed_official 525:c320967f86b9 390 switch(obj->spi.dmaOptionsTX.dmaUsageState) {
mbed_official 525:c320967f86b9 391 case DMA_USAGE_TEMPORARY_ALLOCATED:
mbed_official 525:c320967f86b9 392 return true;
mbed_official 525:c320967f86b9 393 case DMA_USAGE_ALLOCATED:
mbed_official 525:c320967f86b9 394 /* Check whether the allocated DMA channel is active */
mbed_official 525:c320967f86b9 395 return(DMA_ChannelEnabled(obj->spi.dmaOptionsTX.dmaChannel) || DMA_ChannelEnabled(obj->spi.dmaOptionsRX.dmaChannel));
mbed_official 525:c320967f86b9 396 default:
mbed_official 525:c320967f86b9 397 /* Check whether interrupt for spi is enabled */
mbed_official 525:c320967f86b9 398 return (obj->spi.spi->IEN & (USART_IEN_RXDATAV | USART_IEN_TXBL)) ? true : false;
mbed_official 525:c320967f86b9 399 }
mbed_official 525:c320967f86b9 400 }
mbed_official 525:c320967f86b9 401
mbed_official 563:536c9fb088a0 402 void spi_buffer_set(spi_t *obj, const void *tx, uint32_t tx_length, void *rx, uint32_t rx_length, uint8_t bit_width)
mbed_official 525:c320967f86b9 403 {
mbed_official 548:1abac31e188e 404 uint32_t i;
mbed_official 548:1abac31e188e 405 uint16_t *tx_ptr = (uint16_t *) tx;
mbed_official 525:c320967f86b9 406
mbed_official 548:1abac31e188e 407 tx_length *= (bit_width >> 3);
mbed_official 548:1abac31e188e 408 rx_length *= (bit_width >> 3);
mbed_official 525:c320967f86b9 409
mbed_official 563:536c9fb088a0 410 obj->tx_buff.buffer = (void *)tx;
mbed_official 525:c320967f86b9 411 obj->rx_buff.buffer = rx;
mbed_official 525:c320967f86b9 412 obj->tx_buff.length = tx_length;
mbed_official 525:c320967f86b9 413 obj->rx_buff.length = rx_length;
mbed_official 525:c320967f86b9 414 obj->tx_buff.pos = 0;
mbed_official 525:c320967f86b9 415 obj->rx_buff.pos = 0;
mbed_official 525:c320967f86b9 416 obj->tx_buff.width = bit_width;
mbed_official 525:c320967f86b9 417 obj->rx_buff.width = bit_width;
mbed_official 525:c320967f86b9 418
mbed_official 525:c320967f86b9 419 if((obj->spi.bits == 9) && (tx != 0)) {
mbed_official 548:1abac31e188e 420 // Make sure we don't have inadvertent non-zero bits outside 9-bit frames which could trigger unwanted operation
mbed_official 548:1abac31e188e 421 for(i = 0; i < (tx_length / 2); i++) {
mbed_official 548:1abac31e188e 422 tx_ptr[i] &= 0x1FF;
mbed_official 548:1abac31e188e 423 }
mbed_official 525:c320967f86b9 424 }
mbed_official 525:c320967f86b9 425 }
mbed_official 525:c320967f86b9 426
mbed_official 525:c320967f86b9 427 static void spi_buffer_tx_write(spi_t *obj)
mbed_official 525:c320967f86b9 428 {
mbed_official 548:1abac31e188e 429 uint32_t data;
mbed_official 548:1abac31e188e 430 // This routine gets triggered on TXBL (= buffer empty), so check to see if we can write a double value
mbed_official 548:1abac31e188e 431 if (obj->spi.bits % 9 != 0) {
mbed_official 548:1abac31e188e 432 // No special 9-bit scenario
mbed_official 548:1abac31e188e 433 if((obj->tx_buff.pos < obj->tx_buff.length - 1) && ((obj->tx_buff.pos & 0x1) == 0)) {
mbed_official 548:1abac31e188e 434 // write double frame
mbed_official 548:1abac31e188e 435 if (obj->tx_buff.buffer == (void *)0) {
mbed_official 548:1abac31e188e 436 data = SPI_FILL_WORD;
mbed_official 548:1abac31e188e 437 } else {
mbed_official 548:1abac31e188e 438 uint16_t *tx = (uint16_t *)(obj->tx_buff.buffer);
mbed_official 548:1abac31e188e 439 data = tx[obj->tx_buff.pos / 2] & 0xFFFF;
mbed_official 548:1abac31e188e 440 }
mbed_official 548:1abac31e188e 441 obj->tx_buff.pos += 2;
mbed_official 548:1abac31e188e 442 obj->spi.spi->TXDOUBLE = data;
mbed_official 548:1abac31e188e 443 } else if (obj->tx_buff.pos < obj->tx_buff.length) {
mbed_official 548:1abac31e188e 444 // write single frame
mbed_official 548:1abac31e188e 445 if (obj->tx_buff.buffer == (void *)0) {
mbed_official 548:1abac31e188e 446 data = SPI_FILL_WORD & 0xFF;
mbed_official 548:1abac31e188e 447 } else {
mbed_official 548:1abac31e188e 448 uint8_t *tx = (uint8_t *)(obj->tx_buff.buffer);
mbed_official 548:1abac31e188e 449 data = tx[obj->tx_buff.pos] & 0xFF;
mbed_official 548:1abac31e188e 450 }
mbed_official 548:1abac31e188e 451 obj->tx_buff.pos++;
mbed_official 548:1abac31e188e 452 obj->spi.spi->TXDATA = data;
mbed_official 548:1abac31e188e 453 }
mbed_official 548:1abac31e188e 454 } else {
mbed_official 548:1abac31e188e 455 // 9-bit frame
mbed_official 548:1abac31e188e 456 if(obj->tx_buff.pos < obj->tx_buff.length - 3) {
mbed_official 548:1abac31e188e 457 // write double frame
mbed_official 548:1abac31e188e 458 if (obj->tx_buff.buffer == (void *)0) {
mbed_official 548:1abac31e188e 459 data = ((SPI_FILL_WORD & 0x01FF) << 16) | (SPI_FILL_WORD & 0x1FF);
mbed_official 548:1abac31e188e 460 } else {
mbed_official 548:1abac31e188e 461 uint32_t *tx = (uint32_t *)(obj->tx_buff.buffer);
mbed_official 548:1abac31e188e 462 data = tx[obj->tx_buff.pos / 4] & 0x01FF01FF;
mbed_official 548:1abac31e188e 463 }
mbed_official 548:1abac31e188e 464 obj->tx_buff.pos += 4;
mbed_official 548:1abac31e188e 465 obj->spi.spi->TXDOUBLEX = data;
mbed_official 548:1abac31e188e 466 } else if (obj->tx_buff.pos < obj->tx_buff.length - 1) {
mbed_official 548:1abac31e188e 467 // write single frame
mbed_official 548:1abac31e188e 468 if (obj->tx_buff.buffer == (void *)0) {
mbed_official 548:1abac31e188e 469 data = SPI_FILL_WORD & 0x01FF;
mbed_official 548:1abac31e188e 470 } else {
mbed_official 548:1abac31e188e 471 uint16_t *tx = (uint16_t *)(obj->tx_buff.buffer);
mbed_official 548:1abac31e188e 472 data = tx[obj->tx_buff.pos / 2] & 0x01FF;
mbed_official 548:1abac31e188e 473 }
mbed_official 548:1abac31e188e 474 obj->tx_buff.pos += 2;
mbed_official 548:1abac31e188e 475 obj->spi.spi->TXDATAX = data;
mbed_official 548:1abac31e188e 476 }
mbed_official 548:1abac31e188e 477 }
mbed_official 525:c320967f86b9 478 }
mbed_official 525:c320967f86b9 479
mbed_official 525:c320967f86b9 480 static void spi_buffer_rx_read(spi_t *obj)
mbed_official 525:c320967f86b9 481 {
mbed_official 548:1abac31e188e 482 if (obj->spi.bits % 9 != 0) {
mbed_official 548:1abac31e188e 483 if ((obj->spi.spi->STATUS & USART_STATUS_RXFULL) && (obj->rx_buff.pos < obj->rx_buff.length - 1) && ((obj->rx_buff.pos % 2) == 0)) {
mbed_official 548:1abac31e188e 484 // Read max 16 bits from buffer to speed things up
mbed_official 548:1abac31e188e 485 uint32_t data = (uint32_t)obj->spi.spi->RXDOUBLE; //read the data but store only if rx is set and not full
mbed_official 548:1abac31e188e 486 if (obj->rx_buff.buffer) {
mbed_official 548:1abac31e188e 487 uint16_t *rx = (uint16_t *)(obj->rx_buff.buffer);
mbed_official 548:1abac31e188e 488 rx[obj->rx_buff.pos / 2] = data & 0xFFFF;
mbed_official 548:1abac31e188e 489 obj->rx_buff.pos += 2;
mbed_official 548:1abac31e188e 490 }
mbed_official 548:1abac31e188e 491 } else if ((obj->spi.spi->STATUS & (USART_STATUS_RXDATAV | USART_STATUS_RXFULL)) && (obj->rx_buff.pos < obj->rx_buff.length)) {
mbed_official 548:1abac31e188e 492 // Read 8 bits from buffer
mbed_official 548:1abac31e188e 493 while((obj->spi.spi->STATUS & (USART_STATUS_RXDATAV | USART_STATUS_RXFULL)) && (obj->rx_buff.pos < obj->rx_buff.length)) {
mbed_official 548:1abac31e188e 494 uint32_t data = (uint32_t)obj->spi.spi->RXDATA; //read the data but store only if rx is set and not full
mbed_official 548:1abac31e188e 495 if (obj->rx_buff.buffer) {
mbed_official 548:1abac31e188e 496 uint8_t *rx = (uint8_t *)(obj->rx_buff.buffer);
mbed_official 548:1abac31e188e 497 rx[obj->rx_buff.pos] = data & 0xFF;
mbed_official 548:1abac31e188e 498 obj->rx_buff.pos++;
mbed_official 548:1abac31e188e 499 }
mbed_official 548:1abac31e188e 500 }
mbed_official 548:1abac31e188e 501 } else if (obj->spi.spi->STATUS & USART_STATUS_RXFULL) {
mbed_official 548:1abac31e188e 502 // Read from the buffer to lower the interrupt flag
mbed_official 548:1abac31e188e 503 volatile uint32_t data = (uint32_t)obj->spi.spi->RXDOUBLE;
mbed_official 548:1abac31e188e 504 } else if (obj->spi.spi->STATUS & USART_STATUS_RXDATAV) {
mbed_official 548:1abac31e188e 505 // Read from the buffer to lower the interrupt flag
mbed_official 548:1abac31e188e 506 volatile uint32_t data = (uint32_t)obj->spi.spi->RXDATA;
mbed_official 548:1abac31e188e 507 }
mbed_official 548:1abac31e188e 508 } else {
mbed_official 548:1abac31e188e 509 // Data bits is multiple of 9, so use the extended registers
mbed_official 548:1abac31e188e 510 if ((obj->spi.spi->STATUS & USART_STATUS_RXFULL) && (obj->rx_buff.pos < obj->rx_buff.length - 3) && ((obj->rx_buff.pos % 4) == 0)) {
mbed_official 548:1abac31e188e 511 // Read max 18 bits from buffer to speed things up
mbed_official 548:1abac31e188e 512 uint32_t data = (uint32_t)obj->spi.spi->RXDOUBLEX; //read the data but store only if rx is set and will not overflow
mbed_official 548:1abac31e188e 513 if (obj->rx_buff.buffer) {
mbed_official 548:1abac31e188e 514 uint16_t *rx = (uint16_t *)(obj->rx_buff.buffer);
mbed_official 548:1abac31e188e 515 rx[obj->rx_buff.pos / 2] = data & 0x000001FF;
mbed_official 548:1abac31e188e 516 rx[(obj->rx_buff.pos / 2) + 1] = (data & 0x01FF0000) >> 16;
mbed_official 548:1abac31e188e 517 obj->rx_buff.pos += 4;
mbed_official 548:1abac31e188e 518 }
mbed_official 548:1abac31e188e 519 } else if ((obj->spi.spi->STATUS & (USART_STATUS_RXDATAV | USART_STATUS_RXFULL)) && (obj->rx_buff.pos < obj->rx_buff.length - 1)) {
mbed_official 548:1abac31e188e 520 // Read 9 bits from buffer
mbed_official 548:1abac31e188e 521 while((obj->spi.spi->STATUS & (USART_STATUS_RXDATAV | USART_STATUS_RXFULL)) && (obj->rx_buff.pos < obj->rx_buff.length - 1)) {
mbed_official 548:1abac31e188e 522 uint32_t data = (uint32_t)obj->spi.spi->RXDATAX; //read the data but store only if rx is set and not full
mbed_official 548:1abac31e188e 523 if (obj->rx_buff.buffer) {
mbed_official 548:1abac31e188e 524 uint16_t *rx = (uint16_t *)(obj->rx_buff.buffer);
mbed_official 548:1abac31e188e 525 rx[obj->rx_buff.pos / 2] = data & 0x01FF;
mbed_official 548:1abac31e188e 526 obj->rx_buff.pos += 2;
mbed_official 548:1abac31e188e 527 }
mbed_official 548:1abac31e188e 528 }
mbed_official 548:1abac31e188e 529 } else if (obj->spi.spi->STATUS & USART_STATUS_RXFULL) {
mbed_official 548:1abac31e188e 530 // Read from the buffer to lower the interrupt flag
mbed_official 548:1abac31e188e 531 volatile uint32_t data = (uint32_t)obj->spi.spi->RXDOUBLEX;
mbed_official 548:1abac31e188e 532 } else if (obj->spi.spi->STATUS & USART_STATUS_RXDATAV) {
mbed_official 548:1abac31e188e 533 // Read from the buffer to lower the interrupt flag
mbed_official 548:1abac31e188e 534 volatile uint32_t data = (uint32_t)obj->spi.spi->RXDATAX;
mbed_official 548:1abac31e188e 535 }
mbed_official 548:1abac31e188e 536 }
mbed_official 525:c320967f86b9 537 }
mbed_official 525:c320967f86b9 538
mbed_official 525:c320967f86b9 539 int spi_master_write_asynch(spi_t *obj)
mbed_official 525:c320967f86b9 540 {
mbed_official 525:c320967f86b9 541 int ndata = 0;
mbed_official 525:c320967f86b9 542 while ((obj->tx_buff.pos < obj->tx_buff.length) && (obj->spi.spi->STATUS & USART_STATUS_TXBL)) {
mbed_official 525:c320967f86b9 543 spi_buffer_tx_write(obj);
mbed_official 525:c320967f86b9 544 ndata++;
mbed_official 525:c320967f86b9 545 }
mbed_official 525:c320967f86b9 546 return ndata;
mbed_official 525:c320967f86b9 547 }
mbed_official 525:c320967f86b9 548
mbed_official 525:c320967f86b9 549 int spi_master_read_asynch(spi_t *obj)
mbed_official 525:c320967f86b9 550 {
mbed_official 525:c320967f86b9 551 int ndata = 0;
mbed_official 525:c320967f86b9 552 while ((obj->rx_buff.pos < obj->rx_buff.length) && (obj->spi.spi->STATUS & (USART_STATUS_RXDATAV | USART_STATUS_RXFULL))) {
mbed_official 525:c320967f86b9 553 spi_buffer_rx_read(obj);
mbed_official 525:c320967f86b9 554 ndata++;
mbed_official 525:c320967f86b9 555 }
mbed_official 525:c320967f86b9 556 // all sent but still more to receive? need to align tx buffer
mbed_official 525:c320967f86b9 557 if ((obj->tx_buff.pos >= obj->tx_buff.length) && (obj->rx_buff.pos < obj->rx_buff.length)) {
mbed_official 525:c320967f86b9 558 obj->tx_buff.buffer = (void *)0;
mbed_official 525:c320967f86b9 559 obj->tx_buff.length = obj->rx_buff.length;
mbed_official 525:c320967f86b9 560 }
mbed_official 525:c320967f86b9 561
mbed_official 525:c320967f86b9 562 return ndata;
mbed_official 525:c320967f86b9 563 }
mbed_official 525:c320967f86b9 564
mbed_official 525:c320967f86b9 565 uint8_t spi_buffer_rx_empty(spi_t *obj)
mbed_official 525:c320967f86b9 566 {
mbed_official 525:c320967f86b9 567 return (obj->rx_buff.pos >= obj->rx_buff.length ? true : false );
mbed_official 525:c320967f86b9 568 }
mbed_official 525:c320967f86b9 569
mbed_official 525:c320967f86b9 570 uint8_t spi_buffer_tx_empty(spi_t *obj)
mbed_official 525:c320967f86b9 571 {
mbed_official 525:c320967f86b9 572 return (obj->tx_buff.pos >= obj->tx_buff.length ? true : false );
mbed_official 525:c320967f86b9 573 }
mbed_official 525:c320967f86b9 574
mbed_official 525:c320967f86b9 575 //TODO_LP implement slave
mbed_official 525:c320967f86b9 576
mbed_official 525:c320967f86b9 577 int spi_slave_receive(spi_t *obj)
mbed_official 525:c320967f86b9 578 {
mbed_official 525:c320967f86b9 579 if (obj->spi.bits <= 9) {
mbed_official 525:c320967f86b9 580 return (obj->spi.spi->STATUS & USART_STATUS_RXDATAV) ? 1 : 0;
mbed_official 525:c320967f86b9 581 } else {
mbed_official 525:c320967f86b9 582 return (obj->spi.spi->STATUS & USART_STATUS_RXFULL) ? 1 : 0;
mbed_official 525:c320967f86b9 583 }
mbed_official 525:c320967f86b9 584 }
mbed_official 525:c320967f86b9 585
mbed_official 525:c320967f86b9 586 int spi_slave_read(spi_t *obj)
mbed_official 525:c320967f86b9 587 {
mbed_official 525:c320967f86b9 588 return spi_read(obj);
mbed_official 525:c320967f86b9 589 }
mbed_official 525:c320967f86b9 590
mbed_official 525:c320967f86b9 591 void spi_slave_write(spi_t *obj, int value)
mbed_official 525:c320967f86b9 592 {
mbed_official 525:c320967f86b9 593 spi_write(obj, value);
mbed_official 525:c320967f86b9 594 }
mbed_official 525:c320967f86b9 595
mbed_official 525:c320967f86b9 596 uint32_t spi_event_check(spi_t *obj)
mbed_official 525:c320967f86b9 597 {
mbed_official 525:c320967f86b9 598 uint32_t requestedEvent = obj->spi.event;
mbed_official 525:c320967f86b9 599 uint32_t event = 0;
mbed_official 525:c320967f86b9 600 uint8_t quit = spi_buffer_rx_empty(obj) & spi_buffer_tx_empty(obj);
mbed_official 525:c320967f86b9 601 if (((requestedEvent & SPI_EVENT_COMPLETE) != 0) && (quit == true)) {
mbed_official 525:c320967f86b9 602 event |= SPI_EVENT_COMPLETE;
mbed_official 525:c320967f86b9 603 }
mbed_official 525:c320967f86b9 604
mbed_official 525:c320967f86b9 605 if(quit == true) {
mbed_official 548:1abac31e188e 606 event |= SPI_EVENT_INTERNAL_TRANSFER_COMPLETE;
mbed_official 525:c320967f86b9 607 }
mbed_official 525:c320967f86b9 608
mbed_official 525:c320967f86b9 609 return event;
mbed_official 525:c320967f86b9 610 }
mbed_official 525:c320967f86b9 611 /******************************************
mbed_official 525:c320967f86b9 612 * void transferComplete(uint channel, bool primary, void* user)
mbed_official 525:c320967f86b9 613 *
mbed_official 525:c320967f86b9 614 * Callback function which gets called upon DMA transfer completion
mbed_official 525:c320967f86b9 615 * the user-defined pointer is pointing to the CPP-land thunk
mbed_official 525:c320967f86b9 616 ******************************************/
mbed_official 525:c320967f86b9 617 void transferComplete(unsigned int channel, bool primary, void *user)
mbed_official 525:c320967f86b9 618 {
mbed_official 525:c320967f86b9 619 (void) channel;
mbed_official 525:c320967f86b9 620 (void) primary;
mbed_official 525:c320967f86b9 621
mbed_official 525:c320967f86b9 622 /* User pointer should be a thunk to CPP land */
mbed_official 525:c320967f86b9 623 if (user != NULL) {
mbed_official 525:c320967f86b9 624 ((DMACallback)user)();
mbed_official 525:c320967f86b9 625 }
mbed_official 525:c320967f86b9 626 }
mbed_official 525:c320967f86b9 627
mbed_official 525:c320967f86b9 628 /******************************************
mbed_official 525:c320967f86b9 629 * bool spi_allocate_dma(spi_t *obj);
mbed_official 525:c320967f86b9 630 * (helper function for spi_enable_dma)
mbed_official 525:c320967f86b9 631 *
mbed_official 525:c320967f86b9 632 * This function will request two DMA channels from the DMA API if needed
mbed_official 525:c320967f86b9 633 * by the hint provided. They will be allocated to the SPI object pointed to.
mbed_official 525:c320967f86b9 634 *
mbed_official 525:c320967f86b9 635 * return value: whether the channels were acquired successfully (true) or not.
mbed_official 525:c320967f86b9 636 ******************************************/
mbed_official 548:1abac31e188e 637 bool spi_allocate_dma(spi_t *obj)
mbed_official 548:1abac31e188e 638 {
mbed_official 525:c320967f86b9 639 int dmaChannelIn, dmaChannelOut;
mbed_official 525:c320967f86b9 640 dmaChannelIn = dma_channel_allocate(DMA_CAP_NONE);
mbed_official 525:c320967f86b9 641 if (dmaChannelIn == DMA_ERROR_OUT_OF_CHANNELS) {
mbed_official 525:c320967f86b9 642 return false;
mbed_official 525:c320967f86b9 643 }
mbed_official 525:c320967f86b9 644 dmaChannelOut = dma_channel_allocate(DMA_CAP_NONE);
mbed_official 525:c320967f86b9 645 if (dmaChannelOut == DMA_ERROR_OUT_OF_CHANNELS) {
mbed_official 525:c320967f86b9 646 dma_channel_free(dmaChannelIn);
mbed_official 525:c320967f86b9 647 return false;
mbed_official 525:c320967f86b9 648 }
mbed_official 525:c320967f86b9 649
mbed_official 525:c320967f86b9 650 obj->spi.dmaOptionsTX.dmaChannel = dmaChannelOut;
mbed_official 525:c320967f86b9 651 obj->spi.dmaOptionsRX.dmaChannel = dmaChannelIn;
mbed_official 525:c320967f86b9 652 return true;
mbed_official 525:c320967f86b9 653 }
mbed_official 525:c320967f86b9 654
mbed_official 525:c320967f86b9 655 /******************************************
mbed_official 525:c320967f86b9 656 * void spi_enable_dma(spi_t *obj, DMAUsage state)
mbed_official 525:c320967f86b9 657 *
mbed_official 525:c320967f86b9 658 * This function tries to allocate DMA as indicated by the hint (state).
mbed_official 525:c320967f86b9 659 * There are three possibilities:
mbed_official 525:c320967f86b9 660 * * state = NEVER:
mbed_official 525:c320967f86b9 661 * if there were channels allocated by state = ALWAYS, they will be released
mbed_official 525:c320967f86b9 662 * * state = OPPORTUNITIC:
mbed_official 525:c320967f86b9 663 * if there are channels available, they will get used, but freed upon transfer completion
mbed_official 525:c320967f86b9 664 * * state = ALWAYS
mbed_official 525:c320967f86b9 665 * if there are channels available, they will get allocated and not be freed until state changes
mbed_official 525:c320967f86b9 666 ******************************************/
mbed_official 525:c320967f86b9 667 void spi_enable_dma(spi_t *obj, DMAUsage state)
mbed_official 525:c320967f86b9 668 {
mbed_official 525:c320967f86b9 669 if (state == DMA_USAGE_ALWAYS && obj->spi.dmaOptionsTX.dmaUsageState != DMA_USAGE_ALLOCATED) {
mbed_official 525:c320967f86b9 670 /* Try to allocate channels */
mbed_official 525:c320967f86b9 671 if (spi_allocate_dma(obj)) {
mbed_official 525:c320967f86b9 672 obj->spi.dmaOptionsTX.dmaUsageState = DMA_USAGE_ALLOCATED;
mbed_official 525:c320967f86b9 673 } else {
mbed_official 525:c320967f86b9 674 obj->spi.dmaOptionsTX.dmaUsageState = state;
mbed_official 525:c320967f86b9 675 }
mbed_official 525:c320967f86b9 676 } else if (state == DMA_USAGE_OPPORTUNISTIC) {
mbed_official 525:c320967f86b9 677 if (obj->spi.dmaOptionsTX.dmaUsageState == DMA_USAGE_ALLOCATED) {
mbed_official 525:c320967f86b9 678 /* Channels have already been allocated previously by an ALWAYS state, so after this transfer, we will release them */
mbed_official 525:c320967f86b9 679 obj->spi.dmaOptionsTX.dmaUsageState = DMA_USAGE_TEMPORARY_ALLOCATED;
mbed_official 525:c320967f86b9 680 } else {
mbed_official 525:c320967f86b9 681 /* Try to allocate channels */
mbed_official 525:c320967f86b9 682 if (spi_allocate_dma(obj)) {
mbed_official 525:c320967f86b9 683 obj->spi.dmaOptionsTX.dmaUsageState = DMA_USAGE_TEMPORARY_ALLOCATED;
mbed_official 525:c320967f86b9 684 } else {
mbed_official 525:c320967f86b9 685 obj->spi.dmaOptionsTX.dmaUsageState = state;
mbed_official 525:c320967f86b9 686 }
mbed_official 525:c320967f86b9 687 }
mbed_official 525:c320967f86b9 688 } else if (state == DMA_USAGE_NEVER) {
mbed_official 525:c320967f86b9 689 /* If channels are allocated, get rid of them */
mbed_official 525:c320967f86b9 690 if (obj->spi.dmaOptionsTX.dmaUsageState == DMA_USAGE_ALLOCATED) {
mbed_official 525:c320967f86b9 691 dma_channel_free(obj->spi.dmaOptionsTX.dmaChannel);
mbed_official 525:c320967f86b9 692 dma_channel_free(obj->spi.dmaOptionsRX.dmaChannel);
mbed_official 525:c320967f86b9 693 }
mbed_official 525:c320967f86b9 694 obj->spi.dmaOptionsTX.dmaUsageState = DMA_USAGE_NEVER;
mbed_official 525:c320967f86b9 695 }
mbed_official 525:c320967f86b9 696 }
mbed_official 525:c320967f86b9 697
mbed_official 525:c320967f86b9 698 /******************************************
mbed_official 525:c320967f86b9 699 * void spi_master_dma_channel_setup(spi_t *obj)
mbed_official 525:c320967f86b9 700 *
mbed_official 525:c320967f86b9 701 * This function will setup the DMA configuration for SPI transfers
mbed_official 525:c320967f86b9 702 *
mbed_official 525:c320967f86b9 703 * The channel numbers are fetched from the SPI instance, so this function
mbed_official 525:c320967f86b9 704 * should only be called when those channels have actually been allocated.
mbed_official 525:c320967f86b9 705 ******************************************/
mbed_official 525:c320967f86b9 706 static void spi_master_dma_channel_setup(spi_t *obj, void* callback)
mbed_official 525:c320967f86b9 707 {
mbed_official 525:c320967f86b9 708 DMA_CfgChannel_TypeDef rxChnlCfg;
mbed_official 525:c320967f86b9 709 DMA_CfgChannel_TypeDef txChnlCfg;
mbed_official 525:c320967f86b9 710
mbed_official 525:c320967f86b9 711 /* Setting up channel for rx. */
mbed_official 525:c320967f86b9 712 obj->spi.dmaOptionsRX.dmaCallback.cbFunc = transferComplete;
mbed_official 525:c320967f86b9 713 obj->spi.dmaOptionsRX.dmaCallback.userPtr = callback;
mbed_official 525:c320967f86b9 714
mbed_official 525:c320967f86b9 715 rxChnlCfg.highPri = false;
mbed_official 525:c320967f86b9 716 rxChnlCfg.enableInt = true;
mbed_official 525:c320967f86b9 717 rxChnlCfg.cb = &(obj->spi.dmaOptionsRX.dmaCallback);
mbed_official 525:c320967f86b9 718
mbed_official 525:c320967f86b9 719 /* Setting up channel for tx. */
mbed_official 525:c320967f86b9 720 obj->spi.dmaOptionsTX.dmaCallback.cbFunc = transferComplete;
mbed_official 525:c320967f86b9 721 obj->spi.dmaOptionsTX.dmaCallback.userPtr = callback;
mbed_official 525:c320967f86b9 722
mbed_official 525:c320967f86b9 723 txChnlCfg.highPri = false;
mbed_official 525:c320967f86b9 724 txChnlCfg.enableInt = true;
mbed_official 525:c320967f86b9 725 txChnlCfg.cb = &(obj->spi.dmaOptionsTX.dmaCallback);
mbed_official 525:c320967f86b9 726
mbed_official 548:1abac31e188e 727 switch ((int)obj->spi.spi) {
mbed_official 525:c320967f86b9 728 #ifdef USART0
mbed_official 525:c320967f86b9 729 case SPI_0:
mbed_official 525:c320967f86b9 730 rxChnlCfg.select = DMAREQ_USART0_RXDATAV;
mbed_official 525:c320967f86b9 731 txChnlCfg.select = DMAREQ_USART0_TXEMPTY;
mbed_official 525:c320967f86b9 732 break;
mbed_official 525:c320967f86b9 733 #endif
mbed_official 525:c320967f86b9 734 #ifdef USART1
mbed_official 525:c320967f86b9 735 case SPI_1:
mbed_official 525:c320967f86b9 736 rxChnlCfg.select = DMAREQ_USART1_RXDATAV;
mbed_official 525:c320967f86b9 737 txChnlCfg.select = DMAREQ_USART1_TXEMPTY;
mbed_official 525:c320967f86b9 738 break;
mbed_official 525:c320967f86b9 739 #endif
mbed_official 525:c320967f86b9 740 #ifdef USART2
mbed_official 525:c320967f86b9 741 case SPI_2:
mbed_official 525:c320967f86b9 742 rxChnlCfg.select = DMAREQ_USART2_RXDATAV;
mbed_official 525:c320967f86b9 743 txChnlCfg.select = DMAREQ_USART2_TXEMPTY;
mbed_official 525:c320967f86b9 744 break;
mbed_official 525:c320967f86b9 745 #endif
mbed_official 525:c320967f86b9 746 default:
mbed_official 525:c320967f86b9 747 error("Spi module not available.. Out of bound access.");
mbed_official 525:c320967f86b9 748 break;
mbed_official 525:c320967f86b9 749 }
mbed_official 525:c320967f86b9 750 DMA_CfgChannel(obj->spi.dmaOptionsRX.dmaChannel, &rxChnlCfg);
mbed_official 525:c320967f86b9 751 DMA_CfgChannel(obj->spi.dmaOptionsTX.dmaChannel, &txChnlCfg);
mbed_official 525:c320967f86b9 752 }
mbed_official 525:c320967f86b9 753
mbed_official 525:c320967f86b9 754 /******************************************
mbed_official 525:c320967f86b9 755 * void spi_activate_dma(spi_t *obj, void* rxdata, void* txdata, int length)
mbed_official 525:c320967f86b9 756 *
mbed_official 525:c320967f86b9 757 * This function will start the DMA engine for SPI transfers
mbed_official 525:c320967f86b9 758 *
mbed_official 525:c320967f86b9 759 * * rxdata: pointer to RX buffer, if needed.
mbed_official 525:c320967f86b9 760 * * txdata: pointer to TX buffer, if needed. Else FF's.
mbed_official 525:c320967f86b9 761 * * tx_length: how many bytes will get sent.
mbed_official 525:c320967f86b9 762 * * rx_length: how many bytes will get received. If > tx_length, TX will get padded with n lower bits of SPI_FILL_WORD.
mbed_official 525:c320967f86b9 763 ******************************************/
mbed_official 563:536c9fb088a0 764 static void spi_activate_dma(spi_t *obj, void* rxdata, const void* txdata, int tx_length, int rx_length)
mbed_official 548:1abac31e188e 765 {
mbed_official 525:c320967f86b9 766 /* DMA descriptors */
mbed_official 525:c320967f86b9 767 DMA_CfgDescr_TypeDef rxDescrCfg;
mbed_official 525:c320967f86b9 768 DMA_CfgDescr_TypeDef txDescrCfg;
mbed_official 525:c320967f86b9 769
mbed_official 549:99e4f6522a2d 770 /* Split up transfers if the tx length is larger than what the DMA supports. */
mbed_official 549:99e4f6522a2d 771 const int DMA_MAX_TRANSFER = (_DMA_CTRL_N_MINUS_1_MASK >> _DMA_CTRL_N_MINUS_1_SHIFT);
mbed_official 549:99e4f6522a2d 772
mbed_official 549:99e4f6522a2d 773 if (tx_length > DMA_MAX_TRANSFER) {
mbed_official 549:99e4f6522a2d 774 uint32_t max_length = DMA_MAX_TRANSFER;
mbed_official 549:99e4f6522a2d 775
mbed_official 549:99e4f6522a2d 776 /* Make sure only an even amount of bytes are transferred
mbed_official 549:99e4f6522a2d 777 if the width is larger than 8 bits. */
mbed_official 549:99e4f6522a2d 778 if (obj->spi.bits > 8) {
mbed_official 549:99e4f6522a2d 779 max_length = DMA_MAX_TRANSFER - (DMA_MAX_TRANSFER & 0x01);
mbed_official 549:99e4f6522a2d 780 }
mbed_official 549:99e4f6522a2d 781
mbed_official 549:99e4f6522a2d 782 /* Update length for current transfer. */
mbed_official 549:99e4f6522a2d 783 tx_length = max_length;
mbed_official 549:99e4f6522a2d 784 }
mbed_official 549:99e4f6522a2d 785
mbed_official 525:c320967f86b9 786 /* Save amount of TX done by DMA */
mbed_official 549:99e4f6522a2d 787 obj->tx_buff.pos += tx_length;
mbed_official 525:c320967f86b9 788
mbed_official 525:c320967f86b9 789 if(obj->spi.bits != 9) {
mbed_official 548:1abac31e188e 790 /* Only activate RX DMA if a receive buffer is specified */
mbed_official 548:1abac31e188e 791 if (rxdata != NULL) {
mbed_official 548:1abac31e188e 792 // Setting up channel descriptor
mbed_official 548:1abac31e188e 793 rxDescrCfg.dstInc = dmaDataInc1;
mbed_official 548:1abac31e188e 794 rxDescrCfg.srcInc = dmaDataIncNone;
mbed_official 548:1abac31e188e 795 rxDescrCfg.size = dmaDataSize1;
mbed_official 548:1abac31e188e 796 rxDescrCfg.arbRate = dmaArbitrate1;
mbed_official 548:1abac31e188e 797 rxDescrCfg.hprot = 0;
mbed_official 548:1abac31e188e 798 DMA_CfgDescr(obj->spi.dmaOptionsRX.dmaChannel, true, &rxDescrCfg);
mbed_official 525:c320967f86b9 799
mbed_official 548:1abac31e188e 800 // Clear RX registers - Useful if previous command transfered don't
mbed_official 548:1abac31e188e 801 obj->spi.spi->CMD = USART_CMD_CLEARRX;
mbed_official 525:c320967f86b9 802
mbed_official 548:1abac31e188e 803 /* Activate RX channel */
mbed_official 548:1abac31e188e 804 DMA_ActivateBasic(obj->spi.dmaOptionsRX.dmaChannel, true, false, rxdata, (void *)&(obj->spi.spi->RXDATA),
mbed_official 548:1abac31e188e 805 rx_length - 1);
mbed_official 548:1abac31e188e 806 }
mbed_official 525:c320967f86b9 807
mbed_official 548:1abac31e188e 808 // buffer with all FFs.
mbed_official 548:1abac31e188e 809 /* Setting up channel descriptor */
mbed_official 548:1abac31e188e 810 txDescrCfg.dstInc = dmaDataIncNone;
mbed_official 548:1abac31e188e 811 txDescrCfg.srcInc = (txdata == 0 ? dmaDataIncNone : (obj->spi.bits <= 8 ? dmaDataInc1 : dmaDataInc2)); //Do not increment source pointer when there is no transmit buffer
mbed_official 548:1abac31e188e 812 txDescrCfg.size = (obj->spi.bits <= 8 ? dmaDataSize1 : dmaDataSize2); //When frame size > 9, we can use TXDOUBLE to save bandwidth
mbed_official 548:1abac31e188e 813 txDescrCfg.arbRate = dmaArbitrate1;
mbed_official 548:1abac31e188e 814 txDescrCfg.hprot = 0;
mbed_official 548:1abac31e188e 815 DMA_CfgDescr(obj->spi.dmaOptionsTX.dmaChannel, true, &txDescrCfg);
mbed_official 525:c320967f86b9 816
mbed_official 548:1abac31e188e 817 /* Clear TX registers */
mbed_official 548:1abac31e188e 818 obj->spi.spi->CMD = USART_CMD_CLEARTX;
mbed_official 525:c320967f86b9 819
mbed_official 548:1abac31e188e 820 /* Activate TX channel */
mbed_official 548:1abac31e188e 821 DMA_ActivateBasic( obj->spi.dmaOptionsTX.dmaChannel,
mbed_official 548:1abac31e188e 822 true,
mbed_official 548:1abac31e188e 823 false,
mbed_official 548:1abac31e188e 824 (obj->spi.bits <= 8 ? (void *)&(obj->spi.spi->TXDATA) : (void *)&(obj->spi.spi->TXDOUBLE)), //When frame size > 9, point to TXDOUBLE
mbed_official 563:536c9fb088a0 825 (txdata == 0 ? &fill_word : (void *)txdata), // When there is nothing to transmit, point to static fill word
mbed_official 548:1abac31e188e 826 (obj->spi.bits <= 8 ? tx_length - 1 : (tx_length / 2) - 1)); // When using TXDOUBLE, recalculate transfer length
mbed_official 525:c320967f86b9 827 } else {
mbed_official 548:1abac31e188e 828 /* Frame size == 9 */
mbed_official 548:1abac31e188e 829 /* Only activate RX DMA if a receive buffer is specified */
mbed_official 548:1abac31e188e 830 if (rxdata != NULL) {
mbed_official 548:1abac31e188e 831 // Setting up channel descriptor
mbed_official 548:1abac31e188e 832 rxDescrCfg.dstInc = dmaDataInc2;
mbed_official 548:1abac31e188e 833 rxDescrCfg.srcInc = dmaDataIncNone;
mbed_official 548:1abac31e188e 834 rxDescrCfg.size = dmaDataSize2;
mbed_official 548:1abac31e188e 835 rxDescrCfg.arbRate = dmaArbitrate1;
mbed_official 548:1abac31e188e 836 rxDescrCfg.hprot = 0;
mbed_official 548:1abac31e188e 837 DMA_CfgDescr(obj->spi.dmaOptionsRX.dmaChannel, true, &rxDescrCfg);
mbed_official 525:c320967f86b9 838
mbed_official 548:1abac31e188e 839 // Clear RX registers - Useful if previous command transfered don't
mbed_official 548:1abac31e188e 840 obj->spi.spi->CMD = USART_CMD_CLEARRX;
mbed_official 525:c320967f86b9 841
mbed_official 548:1abac31e188e 842 /* Activate RX channel */
mbed_official 548:1abac31e188e 843 DMA_ActivateBasic(obj->spi.dmaOptionsRX.dmaChannel, true, false, rxdata, (void *)&(obj->spi.spi->RXDATAX),
mbed_official 548:1abac31e188e 844 (rx_length / 2) - 1);
mbed_official 548:1abac31e188e 845 }
mbed_official 525:c320967f86b9 846
mbed_official 548:1abac31e188e 847 /* Setting up channel descriptor */
mbed_official 548:1abac31e188e 848 txDescrCfg.dstInc = dmaDataIncNone;
mbed_official 548:1abac31e188e 849 txDescrCfg.srcInc = (txdata == 0 ? dmaDataIncNone : dmaDataInc2); //Do not increment source pointer when there is no transmit buffer
mbed_official 548:1abac31e188e 850 txDescrCfg.size = dmaDataSize2; //When frame size > 9, we can use TXDOUBLE to save bandwidth
mbed_official 548:1abac31e188e 851 txDescrCfg.arbRate = dmaArbitrate1;
mbed_official 548:1abac31e188e 852 txDescrCfg.hprot = 0;
mbed_official 548:1abac31e188e 853 DMA_CfgDescr(obj->spi.dmaOptionsTX.dmaChannel, true, &txDescrCfg);
mbed_official 525:c320967f86b9 854
mbed_official 548:1abac31e188e 855 /* Clear TX registers */
mbed_official 548:1abac31e188e 856 obj->spi.spi->CMD = USART_CMD_CLEARTX;
mbed_official 525:c320967f86b9 857
mbed_official 548:1abac31e188e 858 /* Activate TX channel */
mbed_official 548:1abac31e188e 859 DMA_ActivateBasic( obj->spi.dmaOptionsTX.dmaChannel,
mbed_official 548:1abac31e188e 860 true,
mbed_official 548:1abac31e188e 861 false,
mbed_official 548:1abac31e188e 862 (void *)&(obj->spi.spi->TXDATAX), //When frame size > 9, point to TXDOUBLE
mbed_official 563:536c9fb088a0 863 (txdata == 0 ? &fill_word : (void *)txdata), // When there is nothing to transmit, point to static fill word
mbed_official 548:1abac31e188e 864 (tx_length / 2) - 1); // When using TXDOUBLE, recalculate transfer length
mbed_official 525:c320967f86b9 865 }
mbed_official 525:c320967f86b9 866 }
mbed_official 525:c320967f86b9 867
mbed_official 525:c320967f86b9 868 /********************************************************************
mbed_official 525:c320967f86b9 869 * spi_master_transfer_dma(spi_t *obj, void *rxdata, void *txdata, int length, DMACallback cb, DMAUsage hint)
mbed_official 525:c320967f86b9 870 *
mbed_official 525:c320967f86b9 871 * Start an SPI transfer by using DMA and the supplied hint for DMA useage
mbed_official 525:c320967f86b9 872 *
mbed_official 525:c320967f86b9 873 * * obj: pointer to specific SPI instance
mbed_official 525:c320967f86b9 874 * * rxdata: pointer to rx buffer. If null, we will assume only TX is relevant, and RX will be ignored.
mbed_official 525:c320967f86b9 875 * * txdata: pointer to TX buffer. If null, we will assume only the read is relevant, and will send FF's for reading back.
mbed_official 525:c320967f86b9 876 * * length: How many bytes should be written/read.
mbed_official 525:c320967f86b9 877 * * cb: thunk pointer into CPP-land to get the spi object
mbed_official 525:c320967f86b9 878 * * hint: hint for the requested DMA useage.
mbed_official 525:c320967f86b9 879 * * NEVER: do not use DMA, but use IRQ instead
mbed_official 525:c320967f86b9 880 * * OPPORTUNISTIC: use DMA if there are channels available, but return them after the transfer.
mbed_official 525:c320967f86b9 881 * * ALWAYS: use DMA if channels are available, and hold on to the channels after the transfer.
mbed_official 525:c320967f86b9 882 * If the previous transfer has kept the channel, that channel will continue to get used.
mbed_official 525:c320967f86b9 883 *
mbed_official 525:c320967f86b9 884 ********************************************************************/
mbed_official 563:536c9fb088a0 885 void spi_master_transfer_dma(spi_t *obj, const void *txdata, void *rxdata, int tx_length, int rx_length, void* cb, DMAUsage hint)
mbed_official 548:1abac31e188e 886 {
mbed_official 548:1abac31e188e 887 /* Init DMA here to include it in the power figure */
mbed_official 548:1abac31e188e 888 dma_init();
mbed_official 525:c320967f86b9 889 /* If the DMA channels are already allocated, we can assume they have been setup already */
mbed_official 525:c320967f86b9 890 if (hint != DMA_USAGE_NEVER && obj->spi.dmaOptionsTX.dmaUsageState == DMA_USAGE_ALLOCATED) {
mbed_official 525:c320967f86b9 891 /* setup has already been done, so just activate the transfer */
mbed_official 525:c320967f86b9 892 spi_activate_dma(obj, rxdata, txdata, tx_length, rx_length);
mbed_official 525:c320967f86b9 893 } else if (hint == DMA_USAGE_NEVER) {
mbed_official 525:c320967f86b9 894 /* use IRQ */
mbed_official 525:c320967f86b9 895 obj->spi.spi->IFC = 0xFFFFFFFF;
mbed_official 525:c320967f86b9 896 spi_master_write_asynch(obj);
mbed_official 525:c320967f86b9 897 spi_enable_interrupt(obj, (uint32_t)cb, true);
mbed_official 525:c320967f86b9 898 } else {
mbed_official 525:c320967f86b9 899 /* try to acquire channels */
mbed_official 525:c320967f86b9 900 dma_init();
mbed_official 525:c320967f86b9 901 spi_enable_dma(obj, hint);
mbed_official 525:c320967f86b9 902
mbed_official 525:c320967f86b9 903 /* decide between DMA and IRQ */
mbed_official 525:c320967f86b9 904 if (obj->spi.dmaOptionsTX.dmaUsageState == DMA_USAGE_ALLOCATED || obj->spi.dmaOptionsTX.dmaUsageState == DMA_USAGE_TEMPORARY_ALLOCATED) {
mbed_official 525:c320967f86b9 905 /* disable the interrupts that may have been left open previously */
mbed_official 525:c320967f86b9 906 spi_enable_interrupt(obj, (uint32_t)cb, false);
mbed_official 525:c320967f86b9 907
mbed_official 525:c320967f86b9 908 /* DMA channels are allocated, so do their setup */
mbed_official 525:c320967f86b9 909 spi_master_dma_channel_setup(obj, cb);
mbed_official 525:c320967f86b9 910 /* and activate the transfer */
mbed_official 525:c320967f86b9 911 spi_activate_dma(obj, rxdata, txdata, tx_length, rx_length);
mbed_official 525:c320967f86b9 912 } else {
mbed_official 525:c320967f86b9 913 /* DMA is unavailable, so fall back to IRQ */
mbed_official 525:c320967f86b9 914 obj->spi.spi->IFC = 0xFFFFFFFF;
mbed_official 525:c320967f86b9 915 spi_master_write_asynch(obj);
mbed_official 525:c320967f86b9 916 spi_enable_interrupt(obj, (uint32_t)cb, true);
mbed_official 525:c320967f86b9 917 }
mbed_official 525:c320967f86b9 918 }
mbed_official 525:c320967f86b9 919 }
mbed_official 525:c320967f86b9 920
mbed_official 525:c320967f86b9 921 /** Begin the SPI transfer. Buffer pointers and lengths are specified in tx_buff and rx_buff
mbed_official 525:c320967f86b9 922 *
mbed_official 525:c320967f86b9 923 * @param[in] obj The SPI object which holds the transfer information
mbed_official 525:c320967f86b9 924 * @param[in] tx The buffer to send
mbed_official 525:c320967f86b9 925 * @param[in] tx_length The number of words to transmit
mbed_official 525:c320967f86b9 926 * @param[in] rx The buffer to receive
mbed_official 525:c320967f86b9 927 * @param[in] rx_length The number of words to receive
mbed_official 525:c320967f86b9 928 * @param[in] bit_width The bit width of buffer words
mbed_official 525:c320967f86b9 929 * @param[in] event The logical OR of events to be registered
mbed_official 525:c320967f86b9 930 * @param[in] handler SPI interrupt handler
mbed_official 525:c320967f86b9 931 * @param[in] hint A suggestion for how to use DMA with this transfer
mbed_official 525:c320967f86b9 932 */
mbed_official 563:536c9fb088a0 933 void spi_master_transfer(spi_t *obj, const void *tx, size_t tx_length, void *rx, size_t rx_length, uint8_t bit_width, uint32_t handler, uint32_t event, DMAUsage hint)
mbed_official 548:1abac31e188e 934 {
mbed_official 548:1abac31e188e 935 if( spi_active(obj) ) return;
mbed_official 525:c320967f86b9 936
mbed_official 548:1abac31e188e 937 /* update fill word if on 9-bit frame size */
mbed_official 548:1abac31e188e 938 if(obj->spi.bits == 9) fill_word = SPI_FILL_WORD & 0x1FF;
mbed_official 548:1abac31e188e 939 else fill_word = SPI_FILL_WORD;
mbed_official 525:c320967f86b9 940
mbed_official 548:1abac31e188e 941 /* check corner case */
mbed_official 548:1abac31e188e 942 if(tx_length == 0) {
mbed_official 548:1abac31e188e 943 tx_length = rx_length;
mbed_official 548:1abac31e188e 944 tx = (void*) 0;
mbed_official 548:1abac31e188e 945 }
mbed_official 525:c320967f86b9 946
mbed_official 548:1abac31e188e 947 /* First, set the buffer */
mbed_official 548:1abac31e188e 948 spi_buffer_set(obj, tx, tx_length, rx, rx_length, bit_width);
mbed_official 525:c320967f86b9 949
mbed_official 548:1abac31e188e 950 /* Then, enable the events */
mbed_official 548:1abac31e188e 951 spi_enable_event(obj, SPI_EVENT_ALL, false);
mbed_official 548:1abac31e188e 952 spi_enable_event(obj, event, true);
mbed_official 525:c320967f86b9 953
mbed_official 548:1abac31e188e 954 /* Be tricky on how we handle increased bit widths in the buffer... Handling on byte-basis */
mbed_official 548:1abac31e188e 955 // div 8 = shift right 3
mbed_official 548:1abac31e188e 956 tx_length = tx_length * (bit_width >> 3);
mbed_official 548:1abac31e188e 957 rx_length = rx_length * (bit_width >> 3);
mbed_official 525:c320967f86b9 958
mbed_official 548:1abac31e188e 959 // Set the sleep mode
mbed_official 548:1abac31e188e 960 blockSleepMode(SPI_LEAST_ACTIVE_SLEEPMODE);
mbed_official 525:c320967f86b9 961
mbed_official 548:1abac31e188e 962 /* And kick off the transfer */
mbed_official 548:1abac31e188e 963 spi_master_transfer_dma(obj, tx, rx, tx_length, rx_length, (void*)handler, hint);
mbed_official 525:c320967f86b9 964 }
mbed_official 525:c320967f86b9 965
mbed_official 525:c320967f86b9 966
mbed_official 525:c320967f86b9 967 /********************************************************************
mbed_official 525:c320967f86b9 968 * uint32_t spi_irq_handler_generic(spi_t* obj)
mbed_official 525:c320967f86b9 969 *
mbed_official 525:c320967f86b9 970 * handler which should get called by CPP-land when either a DMA or SPI IRQ gets fired for a SPI transaction.
mbed_official 525:c320967f86b9 971 *
mbed_official 525:c320967f86b9 972 * * obj: pointer to the specific SPI instance
mbed_official 525:c320967f86b9 973 *
mbed_official 525:c320967f86b9 974 * return: event mask. Currently only 0 or SPI_EVENT_COMPLETE upon transfer completion.
mbed_official 525:c320967f86b9 975 *
mbed_official 525:c320967f86b9 976 ********************************************************************/
mbed_official 548:1abac31e188e 977 uint32_t spi_irq_handler_asynch(spi_t* obj)
mbed_official 548:1abac31e188e 978 {
mbed_official 525:c320967f86b9 979
mbed_official 525:c320967f86b9 980 /* Determine whether the current scenario is DMA or IRQ, and act accordingly */
mbed_official 525:c320967f86b9 981
mbed_official 525:c320967f86b9 982 if (obj->spi.dmaOptionsTX.dmaUsageState == DMA_USAGE_ALLOCATED || obj->spi.dmaOptionsTX.dmaUsageState == DMA_USAGE_TEMPORARY_ALLOCATED) {
mbed_official 525:c320967f86b9 983 /* DMA implementation */
mbed_official 525:c320967f86b9 984
mbed_official 549:99e4f6522a2d 985 /* If there is still data in the TX buffer, setup a new transfer. */
mbed_official 549:99e4f6522a2d 986 if (obj->tx_buff.pos < obj->tx_buff.length) {
mbed_official 549:99e4f6522a2d 987 /* Find position and remaining length without modifying tx_buff. */
mbed_official 549:99e4f6522a2d 988 void* tx_pointer = obj->tx_buff.buffer + obj->tx_buff.pos;
mbed_official 549:99e4f6522a2d 989 uint32_t tx_length = obj->tx_buff.length - obj->tx_buff.pos;
mbed_official 549:99e4f6522a2d 990
mbed_official 549:99e4f6522a2d 991 /* Begin transfer. Rely on spi_activate_dma to split up the transfer further. */
mbed_official 549:99e4f6522a2d 992 spi_activate_dma(obj, obj->rx_buff.buffer, tx_pointer, tx_length, obj->rx_buff.length);
mbed_official 549:99e4f6522a2d 993
mbed_official 549:99e4f6522a2d 994 return 0;
mbed_official 549:99e4f6522a2d 995 }
mbed_official 549:99e4f6522a2d 996
mbed_official 525:c320967f86b9 997 /* If there is an RX transfer ongoing, wait for it to finish */
mbed_official 525:c320967f86b9 998 if (DMA_ChannelEnabled(obj->spi.dmaOptionsRX.dmaChannel)) {
mbed_official 548:1abac31e188e 999 /* Check if we need to kick off TX transfer again to force more incoming data. */
mbed_official 548:1abac31e188e 1000 if (!DMA_ChannelEnabled(obj->spi.dmaOptionsTX.dmaChannel) && (obj->tx_buff.pos < obj->rx_buff.length)) {
mbed_official 548:1abac31e188e 1001 //Save state of TX transfer amount
mbed_official 548:1abac31e188e 1002 int length_diff = obj->rx_buff.length - obj->tx_buff.pos;
mbed_official 548:1abac31e188e 1003 obj->tx_buff.pos = obj->rx_buff.length;
mbed_official 525:c320967f86b9 1004
mbed_official 548:1abac31e188e 1005 //Kick off a new DMA transfer
mbed_official 548:1abac31e188e 1006 DMA_CfgDescr_TypeDef txDescrCfg;
mbed_official 525:c320967f86b9 1007
mbed_official 548:1abac31e188e 1008 if(obj->spi.bits != 9) {
mbed_official 548:1abac31e188e 1009 fill_word = SPI_FILL_WORD;
mbed_official 548:1abac31e188e 1010 /* Setting up channel descriptor */
mbed_official 548:1abac31e188e 1011 txDescrCfg.dstInc = dmaDataIncNone;
mbed_official 548:1abac31e188e 1012 txDescrCfg.srcInc = dmaDataIncNone; //Do not increment source pointer when there is no transmit buffer
mbed_official 548:1abac31e188e 1013 txDescrCfg.size = (obj->spi.bits <= 8 ? dmaDataSize1 : dmaDataSize2); //When frame size > 9, we can use TXDOUBLE to save bandwidth
mbed_official 548:1abac31e188e 1014 txDescrCfg.arbRate = dmaArbitrate1;
mbed_official 548:1abac31e188e 1015 txDescrCfg.hprot = 0;
mbed_official 548:1abac31e188e 1016 DMA_CfgDescr(obj->spi.dmaOptionsTX.dmaChannel, true, &txDescrCfg);
mbed_official 525:c320967f86b9 1017
mbed_official 548:1abac31e188e 1018 /* Activate TX channel */
mbed_official 548:1abac31e188e 1019 DMA_ActivateBasic( obj->spi.dmaOptionsTX.dmaChannel,
mbed_official 548:1abac31e188e 1020 true,
mbed_official 548:1abac31e188e 1021 false,
mbed_official 548:1abac31e188e 1022 (obj->spi.bits <= 8 ? (void *)&(obj->spi.spi->TXDATA) : (void *)&(obj->spi.spi->TXDOUBLE)), //When frame size > 9, point to TXDOUBLE
mbed_official 548:1abac31e188e 1023 &fill_word, // When there is nothing to transmit, point to static fill word
mbed_official 548:1abac31e188e 1024 (obj->spi.bits <= 8 ? length_diff - 1 : (length_diff / 2) - 1)); // When using TXDOUBLE, recalculate transfer length
mbed_official 548:1abac31e188e 1025 } else {
mbed_official 548:1abac31e188e 1026 /* Setting up channel descriptor */
mbed_official 548:1abac31e188e 1027 fill_word = SPI_FILL_WORD & 0x1FF;
mbed_official 548:1abac31e188e 1028 txDescrCfg.dstInc = dmaDataIncNone;
mbed_official 548:1abac31e188e 1029 txDescrCfg.srcInc = dmaDataIncNone; //Do not increment source pointer when there is no transmit buffer
mbed_official 548:1abac31e188e 1030 txDescrCfg.size = dmaDataSize2; //When frame size > 9, we can use TXDOUBLE to save bandwidth
mbed_official 548:1abac31e188e 1031 txDescrCfg.arbRate = dmaArbitrate1;
mbed_official 548:1abac31e188e 1032 txDescrCfg.hprot = 0;
mbed_official 548:1abac31e188e 1033 DMA_CfgDescr(obj->spi.dmaOptionsTX.dmaChannel, true, &txDescrCfg);
mbed_official 525:c320967f86b9 1034
mbed_official 548:1abac31e188e 1035 DMA_ActivateBasic( obj->spi.dmaOptionsTX.dmaChannel,
mbed_official 548:1abac31e188e 1036 true,
mbed_official 548:1abac31e188e 1037 false,
mbed_official 548:1abac31e188e 1038 (void *)&(obj->spi.spi->TXDATAX), //When frame size > 9, point to TXDOUBLE
mbed_official 548:1abac31e188e 1039 &fill_word, // When there is nothing to transmit, point to static fill word
mbed_official 548:1abac31e188e 1040 (length_diff / 2) - 1);
mbed_official 548:1abac31e188e 1041 }
mbed_official 548:1abac31e188e 1042 } else return 0;
mbed_official 525:c320967f86b9 1043 }
mbed_official 525:c320967f86b9 1044
mbed_official 525:c320967f86b9 1045 /* If there is still a TX transfer ongoing (tx_length > rx_length), wait for it to finish */
mbed_official 525:c320967f86b9 1046 if (DMA_ChannelEnabled(obj->spi.dmaOptionsTX.dmaChannel)) {
mbed_official 548:1abac31e188e 1047 return 0;
mbed_official 525:c320967f86b9 1048 }
mbed_official 525:c320967f86b9 1049
mbed_official 525:c320967f86b9 1050 /* Release the dma channels if they were opportunistically allocated */
mbed_official 525:c320967f86b9 1051 if (obj->spi.dmaOptionsTX.dmaUsageState == DMA_USAGE_TEMPORARY_ALLOCATED) {
mbed_official 525:c320967f86b9 1052 dma_channel_free(obj->spi.dmaOptionsTX.dmaChannel);
mbed_official 525:c320967f86b9 1053 dma_channel_free(obj->spi.dmaOptionsRX.dmaChannel);
mbed_official 525:c320967f86b9 1054 obj->spi.dmaOptionsTX.dmaUsageState = DMA_USAGE_OPPORTUNISTIC;
mbed_official 525:c320967f86b9 1055 }
mbed_official 525:c320967f86b9 1056
mbed_official 525:c320967f86b9 1057 unblockSleepMode(SPI_LEAST_ACTIVE_SLEEPMODE);
mbed_official 525:c320967f86b9 1058
mbed_official 525:c320967f86b9 1059 /* return to CPP land to say we're finished */
mbed_official 525:c320967f86b9 1060 return SPI_EVENT_COMPLETE;
mbed_official 525:c320967f86b9 1061 } else {
mbed_official 525:c320967f86b9 1062 /* IRQ implementation */
mbed_official 525:c320967f86b9 1063 if (spi_master_rx_int_flag(obj)) {
mbed_official 525:c320967f86b9 1064 spi_master_read_asynch(obj);
mbed_official 525:c320967f86b9 1065 }
mbed_official 525:c320967f86b9 1066
mbed_official 525:c320967f86b9 1067 if (spi_master_tx_int_flag(obj)) {
mbed_official 525:c320967f86b9 1068 spi_master_write_asynch(obj);
mbed_official 525:c320967f86b9 1069 }
mbed_official 525:c320967f86b9 1070
mbed_official 525:c320967f86b9 1071 uint32_t event = spi_event_check(obj);
mbed_official 525:c320967f86b9 1072 if (event & SPI_EVENT_INTERNAL_TRANSFER_COMPLETE) {
mbed_official 525:c320967f86b9 1073 /* disable interrupts */
mbed_official 525:c320967f86b9 1074 spi_enable_interrupt(obj, (uint32_t)NULL, false);
mbed_official 525:c320967f86b9 1075
mbed_official 525:c320967f86b9 1076 unblockSleepMode(SPI_LEAST_ACTIVE_SLEEPMODE);
mbed_official 525:c320967f86b9 1077
mbed_official 525:c320967f86b9 1078 /* Return the event back to userland */
mbed_official 525:c320967f86b9 1079 return event;
mbed_official 525:c320967f86b9 1080 }
mbed_official 525:c320967f86b9 1081
mbed_official 525:c320967f86b9 1082 return 0;
mbed_official 525:c320967f86b9 1083 }
mbed_official 525:c320967f86b9 1084 }
mbed_official 525:c320967f86b9 1085
mbed_official 525:c320967f86b9 1086 /** Abort an SPI transfer
mbed_official 525:c320967f86b9 1087 *
mbed_official 525:c320967f86b9 1088 * @param obj The SPI peripheral to stop
mbed_official 525:c320967f86b9 1089 */
mbed_official 548:1abac31e188e 1090 void spi_abort_asynch(spi_t *obj)
mbed_official 548:1abac31e188e 1091 {
mbed_official 525:c320967f86b9 1092 // If we're not currently transferring, then there's nothing to do here
mbed_official 525:c320967f86b9 1093 if(spi_active(obj) != 0) return;
mbed_official 548:1abac31e188e 1094
mbed_official 525:c320967f86b9 1095 // Determine whether we're running DMA or interrupt
mbed_official 525:c320967f86b9 1096 if (obj->spi.dmaOptionsTX.dmaUsageState == DMA_USAGE_ALLOCATED || obj->spi.dmaOptionsTX.dmaUsageState == DMA_USAGE_TEMPORARY_ALLOCATED) {
mbed_official 525:c320967f86b9 1097 // Cancel the DMA transfers
mbed_official 525:c320967f86b9 1098 DMA_ChannelEnable(obj->spi.dmaOptionsTX.dmaChannel, false);
mbed_official 525:c320967f86b9 1099 DMA_ChannelEnable(obj->spi.dmaOptionsRX.dmaChannel, false);
mbed_official 548:1abac31e188e 1100
mbed_official 525:c320967f86b9 1101 /* Release the dma channels if they were opportunistically allocated */
mbed_official 525:c320967f86b9 1102 if (obj->spi.dmaOptionsTX.dmaUsageState == DMA_USAGE_TEMPORARY_ALLOCATED) {
mbed_official 525:c320967f86b9 1103 dma_channel_free(obj->spi.dmaOptionsTX.dmaChannel);
mbed_official 525:c320967f86b9 1104 dma_channel_free(obj->spi.dmaOptionsRX.dmaChannel);
mbed_official 525:c320967f86b9 1105 obj->spi.dmaOptionsTX.dmaUsageState = DMA_USAGE_OPPORTUNISTIC;
mbed_official 525:c320967f86b9 1106 }
mbed_official 548:1abac31e188e 1107
mbed_official 525:c320967f86b9 1108 } else {
mbed_official 525:c320967f86b9 1109 // Interrupt implementation: switch off interrupts
mbed_official 525:c320967f86b9 1110 spi_enable_interrupt(obj, (uint32_t)NULL, false);
mbed_official 525:c320967f86b9 1111 }
mbed_official 548:1abac31e188e 1112
mbed_official 525:c320967f86b9 1113 // Release sleep mode block
mbed_official 525:c320967f86b9 1114 unblockSleepMode(SPI_LEAST_ACTIVE_SLEEPMODE);
mbed_official 525:c320967f86b9 1115 }
mbed_official 525:c320967f86b9 1116
mbed_official 525:c320967f86b9 1117 #endif