[11U68]fix P0_11 to use GPIO

Fork of mbed-src by mbed official

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