added prescaler for 16 bit pwm in LPC1347 target

Fork of mbed-dev by mbed official

Committer:
JojoS
Date:
Sat Sep 10 15:32:04 2016 +0000
Revision:
147:ba84b7dc41a7
Parent:
144:ef7eb2e8f9f7
added prescaler for 16 bit timers (solution as in LPC11xx), default prescaler 31 for max 28 ms period time

Who changed what in which revision?

UserRevisionLine numberNew contents of line
<> 144:ef7eb2e8f9f7 1 /* mbed Microcontroller Library
<> 144:ef7eb2e8f9f7 2 * Copyright (c) 2006-2013 ARM Limited
<> 144:ef7eb2e8f9f7 3 *
<> 144:ef7eb2e8f9f7 4 * Licensed under the Apache License, Version 2.0 (the "License");
<> 144:ef7eb2e8f9f7 5 * you may not use this file except in compliance with the License.
<> 144:ef7eb2e8f9f7 6 * You may obtain a copy of the License at
<> 144:ef7eb2e8f9f7 7 *
<> 144:ef7eb2e8f9f7 8 * http://www.apache.org/licenses/LICENSE-2.0
<> 144:ef7eb2e8f9f7 9 *
<> 144:ef7eb2e8f9f7 10 * Unless required by applicable law or agreed to in writing, software
<> 144:ef7eb2e8f9f7 11 * distributed under the License is distributed on an "AS IS" BASIS,
<> 144:ef7eb2e8f9f7 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
<> 144:ef7eb2e8f9f7 13 * See the License for the specific language governing permissions and
<> 144:ef7eb2e8f9f7 14 * limitations under the License.
<> 144:ef7eb2e8f9f7 15 */
<> 144:ef7eb2e8f9f7 16 #include "mbed_assert.h"
<> 144:ef7eb2e8f9f7 17 #include <math.h>
<> 144:ef7eb2e8f9f7 18
<> 144:ef7eb2e8f9f7 19 #include "spi_api.h"
<> 144:ef7eb2e8f9f7 20 #include "cmsis.h"
<> 144:ef7eb2e8f9f7 21 #include "pinmap.h"
<> 144:ef7eb2e8f9f7 22 #include "mbed_error.h"
<> 144:ef7eb2e8f9f7 23 #include "RZ_A1_Init.h"
<> 144:ef7eb2e8f9f7 24
<> 144:ef7eb2e8f9f7 25 static const PinMap PinMap_SPI_SCLK[] = {
<> 144:ef7eb2e8f9f7 26 {P10_12, SPI_0, 4},
<> 144:ef7eb2e8f9f7 27 {P4_4 , SPI_1, 2},
<> 144:ef7eb2e8f9f7 28 {P6_4 , SPI_1, 7},
<> 144:ef7eb2e8f9f7 29 {P11_12, SPI_1, 2},
<> 144:ef7eb2e8f9f7 30 {P8_3 , SPI_2, 3},
<> 144:ef7eb2e8f9f7 31 {P5_0 , SPI_3, 8},
<> 144:ef7eb2e8f9f7 32 {NC , NC , 0}
<> 144:ef7eb2e8f9f7 33 };
<> 144:ef7eb2e8f9f7 34
<> 144:ef7eb2e8f9f7 35 static const PinMap PinMap_SPI_SSEL[] = {
<> 144:ef7eb2e8f9f7 36 {P10_13, SPI_0, 4},
<> 144:ef7eb2e8f9f7 37 {P4_5 , SPI_1, 2},
<> 144:ef7eb2e8f9f7 38 {P6_5 , SPI_1, 7},
<> 144:ef7eb2e8f9f7 39 {P11_13, SPI_1, 2},
<> 144:ef7eb2e8f9f7 40 {P8_4 , SPI_2, 3},
<> 144:ef7eb2e8f9f7 41 {P5_1 , SPI_3, 8},
<> 144:ef7eb2e8f9f7 42 {NC , NC , 0}
<> 144:ef7eb2e8f9f7 43 };
<> 144:ef7eb2e8f9f7 44
<> 144:ef7eb2e8f9f7 45 static const PinMap PinMap_SPI_MOSI[] = {
<> 144:ef7eb2e8f9f7 46 {P10_14, SPI_0, 4},
<> 144:ef7eb2e8f9f7 47 {P4_6 , SPI_1, 2},
<> 144:ef7eb2e8f9f7 48 {P6_6 , SPI_1, 7},
<> 144:ef7eb2e8f9f7 49 {P11_14, SPI_1, 2},
<> 144:ef7eb2e8f9f7 50 {P8_5 , SPI_2, 3},
<> 144:ef7eb2e8f9f7 51 {P5_2 , SPI_3, 8},
<> 144:ef7eb2e8f9f7 52 {NC , NC , 0}
<> 144:ef7eb2e8f9f7 53 };
<> 144:ef7eb2e8f9f7 54
<> 144:ef7eb2e8f9f7 55 static const PinMap PinMap_SPI_MISO[] = {
<> 144:ef7eb2e8f9f7 56 {P10_15, SPI_0, 4},
<> 144:ef7eb2e8f9f7 57 {P4_7 , SPI_1, 2},
<> 144:ef7eb2e8f9f7 58 {P6_7 , SPI_1, 7},
<> 144:ef7eb2e8f9f7 59 {P11_15, SPI_1, 2},
<> 144:ef7eb2e8f9f7 60 {P8_6 , SPI_2, 3},
<> 144:ef7eb2e8f9f7 61 {P5_3 , SPI_3, 8},
<> 144:ef7eb2e8f9f7 62 {NC , NC , 0}
<> 144:ef7eb2e8f9f7 63 };
<> 144:ef7eb2e8f9f7 64
<> 144:ef7eb2e8f9f7 65 static const struct st_rspi *RSPI[] = RSPI_ADDRESS_LIST;
<> 144:ef7eb2e8f9f7 66
<> 144:ef7eb2e8f9f7 67 static inline void spi_disable(spi_t *obj);
<> 144:ef7eb2e8f9f7 68 static inline void spi_enable(spi_t *obj);
<> 144:ef7eb2e8f9f7 69 static inline int spi_readable(spi_t *obj);
<> 144:ef7eb2e8f9f7 70 static inline void spi_write(spi_t *obj, int value);
<> 144:ef7eb2e8f9f7 71 static inline int spi_read(spi_t *obj);
<> 144:ef7eb2e8f9f7 72
<> 144:ef7eb2e8f9f7 73 void spi_init(spi_t *obj, PinName mosi, PinName miso, PinName sclk, PinName ssel) {
<> 144:ef7eb2e8f9f7 74 // determine the SPI to use
<> 144:ef7eb2e8f9f7 75 volatile uint8_t dummy;
<> 144:ef7eb2e8f9f7 76 uint32_t spi_mosi = pinmap_peripheral(mosi, PinMap_SPI_MOSI);
<> 144:ef7eb2e8f9f7 77 uint32_t spi_miso = pinmap_peripheral(miso, PinMap_SPI_MISO);
<> 144:ef7eb2e8f9f7 78 uint32_t spi_sclk = pinmap_peripheral(sclk, PinMap_SPI_SCLK);
<> 144:ef7eb2e8f9f7 79 uint32_t spi_ssel = pinmap_peripheral(ssel, PinMap_SPI_SSEL);
<> 144:ef7eb2e8f9f7 80 uint32_t spi_data = pinmap_merge(spi_mosi, spi_miso);
<> 144:ef7eb2e8f9f7 81 uint32_t spi_cntl = pinmap_merge(spi_sclk, spi_ssel);
<> 144:ef7eb2e8f9f7 82 uint32_t spi = pinmap_merge(spi_data, spi_cntl);
<> 144:ef7eb2e8f9f7 83
<> 144:ef7eb2e8f9f7 84 MBED_ASSERT((int)spi != NC);
<> 144:ef7eb2e8f9f7 85
<> 144:ef7eb2e8f9f7 86 obj->spi.spi = (struct st_rspi *)RSPI[spi];
<> 144:ef7eb2e8f9f7 87 obj->spi.index = spi;
<> 144:ef7eb2e8f9f7 88
<> 144:ef7eb2e8f9f7 89 // enable power and clocking
<> 144:ef7eb2e8f9f7 90 switch (spi) {
<> 144:ef7eb2e8f9f7 91 case SPI_0: CPGSTBCR10 &= ~(0x80); break;
<> 144:ef7eb2e8f9f7 92 case SPI_1: CPGSTBCR10 &= ~(0x40); break;
<> 144:ef7eb2e8f9f7 93 case SPI_2: CPGSTBCR10 &= ~(0x20); break;
<> 144:ef7eb2e8f9f7 94 case SPI_3: CPGSTBCR10 &= ~(0x10); break;
<> 144:ef7eb2e8f9f7 95 }
<> 144:ef7eb2e8f9f7 96 dummy = CPGSTBCR10;
<> 144:ef7eb2e8f9f7 97
<> 144:ef7eb2e8f9f7 98 obj->spi.spi->SPCR = 0x00; // CTRL to 0
<> 144:ef7eb2e8f9f7 99 obj->spi.spi->SPSCR = 0x00; // no sequential operation
<> 144:ef7eb2e8f9f7 100 obj->spi.spi->SSLP = 0x00; // SSL 'L' active
<> 144:ef7eb2e8f9f7 101 obj->spi.spi->SPDCR = 0x20; // byte access
<> 144:ef7eb2e8f9f7 102 obj->spi.spi->SPCKD = 0x00; // SSL -> enable CLK delay : 1RSPCK
<> 144:ef7eb2e8f9f7 103 obj->spi.spi->SSLND = 0x00; // CLK end -> SSL neg delay : 1RSPCK
<> 144:ef7eb2e8f9f7 104 obj->spi.spi->SPND = 0x00; // delay between CMD : 1RSPCK + 2P1CLK
<> 144:ef7eb2e8f9f7 105 obj->spi.spi->SPPCR = 0x20; // MOSI Idle fixed value equals 0
<> 144:ef7eb2e8f9f7 106 obj->spi.spi->SPBFCR = 0xf0; // and set trigger count: read 1, write 1
<> 144:ef7eb2e8f9f7 107 obj->spi.spi->SPBFCR = 0x30; // and reset buffer
<> 144:ef7eb2e8f9f7 108
<> 144:ef7eb2e8f9f7 109 // pin out the spi pins
<> 144:ef7eb2e8f9f7 110 pinmap_pinout(mosi, PinMap_SPI_MOSI);
<> 144:ef7eb2e8f9f7 111 pinmap_pinout(miso, PinMap_SPI_MISO);
<> 144:ef7eb2e8f9f7 112 pinmap_pinout(sclk, PinMap_SPI_SCLK);
<> 144:ef7eb2e8f9f7 113 if ((int)ssel != NC) {
<> 144:ef7eb2e8f9f7 114 pinmap_pinout(ssel, PinMap_SPI_SSEL);
<> 144:ef7eb2e8f9f7 115 }
<> 144:ef7eb2e8f9f7 116 }
<> 144:ef7eb2e8f9f7 117
<> 144:ef7eb2e8f9f7 118 void spi_free(spi_t *obj) {}
<> 144:ef7eb2e8f9f7 119
<> 144:ef7eb2e8f9f7 120 void spi_format(spi_t *obj, int bits, int mode, int slave) {
<> 144:ef7eb2e8f9f7 121 int DSS; // DSS (data select size)
<> 144:ef7eb2e8f9f7 122 int polarity = (mode & 0x2) ? 1 : 0;
<> 144:ef7eb2e8f9f7 123 int phase = (mode & 0x1) ? 1 : 0;
<> 144:ef7eb2e8f9f7 124 uint16_t tmp = 0;
<> 144:ef7eb2e8f9f7 125 uint16_t mask = 0xf03;
<> 144:ef7eb2e8f9f7 126 uint16_t wk_spcmd0;
<> 144:ef7eb2e8f9f7 127 uint8_t splw;
<> 144:ef7eb2e8f9f7 128
<> 144:ef7eb2e8f9f7 129 switch (mode) {
<> 144:ef7eb2e8f9f7 130 case 0:
<> 144:ef7eb2e8f9f7 131 case 1:
<> 144:ef7eb2e8f9f7 132 case 2:
<> 144:ef7eb2e8f9f7 133 case 3:
<> 144:ef7eb2e8f9f7 134 // Do Nothing
<> 144:ef7eb2e8f9f7 135 break;
<> 144:ef7eb2e8f9f7 136 default:
<> 144:ef7eb2e8f9f7 137 error("SPI format error");
<> 144:ef7eb2e8f9f7 138 return;
<> 144:ef7eb2e8f9f7 139 }
<> 144:ef7eb2e8f9f7 140
<> 144:ef7eb2e8f9f7 141 switch (bits) {
<> 144:ef7eb2e8f9f7 142 case 8:
<> 144:ef7eb2e8f9f7 143 DSS = 0x7;
<> 144:ef7eb2e8f9f7 144 splw = 0x20;
<> 144:ef7eb2e8f9f7 145 break;
<> 144:ef7eb2e8f9f7 146 case 16:
<> 144:ef7eb2e8f9f7 147 DSS = 0xf;
<> 144:ef7eb2e8f9f7 148 splw = 0x40;
<> 144:ef7eb2e8f9f7 149 break;
<> 144:ef7eb2e8f9f7 150 case 32:
<> 144:ef7eb2e8f9f7 151 DSS = 0x2;
<> 144:ef7eb2e8f9f7 152 splw = 0x60;
<> 144:ef7eb2e8f9f7 153 break;
<> 144:ef7eb2e8f9f7 154 default:
<> 144:ef7eb2e8f9f7 155 error("SPI module don't support other than 8/16/32bits");
<> 144:ef7eb2e8f9f7 156 return;
<> 144:ef7eb2e8f9f7 157 }
<> 144:ef7eb2e8f9f7 158 tmp |= phase;
<> 144:ef7eb2e8f9f7 159 tmp |= (polarity << 1);
<> 144:ef7eb2e8f9f7 160 tmp |= (DSS << 8);
<> 144:ef7eb2e8f9f7 161 obj->spi.bits = bits;
<> 144:ef7eb2e8f9f7 162
<> 144:ef7eb2e8f9f7 163 spi_disable(obj);
<> 144:ef7eb2e8f9f7 164 wk_spcmd0 = obj->spi.spi->SPCMD0;
<> 144:ef7eb2e8f9f7 165 wk_spcmd0 &= ~mask;
<> 144:ef7eb2e8f9f7 166 wk_spcmd0 |= (mask & tmp);
<> 144:ef7eb2e8f9f7 167 obj->spi.spi->SPCMD0 = wk_spcmd0;
<> 144:ef7eb2e8f9f7 168 obj->spi.spi->SPDCR = splw;
<> 144:ef7eb2e8f9f7 169 if (slave) {
<> 144:ef7eb2e8f9f7 170 obj->spi.spi->SPCR &=~(1 << 3); // MSTR to 0
<> 144:ef7eb2e8f9f7 171 } else {
<> 144:ef7eb2e8f9f7 172 obj->spi.spi->SPCR |= (1 << 3); // MSTR to 1
<> 144:ef7eb2e8f9f7 173 }
<> 144:ef7eb2e8f9f7 174 spi_enable(obj);
<> 144:ef7eb2e8f9f7 175 }
<> 144:ef7eb2e8f9f7 176
<> 144:ef7eb2e8f9f7 177 void spi_frequency(spi_t *obj, int hz) {
<> 144:ef7eb2e8f9f7 178 uint32_t pclk_base;
<> 144:ef7eb2e8f9f7 179 uint32_t div;
<> 144:ef7eb2e8f9f7 180 uint32_t brdv = 0;
<> 144:ef7eb2e8f9f7 181 uint32_t hz_max;
<> 144:ef7eb2e8f9f7 182 uint32_t hz_min;
<> 144:ef7eb2e8f9f7 183 uint16_t mask = 0x000c;
<> 144:ef7eb2e8f9f7 184 uint16_t wk_spcmd0;
<> 144:ef7eb2e8f9f7 185
<> 144:ef7eb2e8f9f7 186 /* set PCLK */
<> 144:ef7eb2e8f9f7 187 if (RZ_A1_IsClockMode0() == false) {
<> 144:ef7eb2e8f9f7 188 pclk_base = CM1_RENESAS_RZ_A1_P1_CLK;
<> 144:ef7eb2e8f9f7 189 } else {
<> 144:ef7eb2e8f9f7 190 pclk_base = CM0_RENESAS_RZ_A1_P1_CLK;
<> 144:ef7eb2e8f9f7 191 }
<> 144:ef7eb2e8f9f7 192
<> 144:ef7eb2e8f9f7 193 hz_min = pclk_base / 2 / 256 / 8;
<> 144:ef7eb2e8f9f7 194 hz_max = pclk_base / 2;
<> 144:ef7eb2e8f9f7 195 if ((hz < hz_min) || (hz > hz_max)) {
<> 144:ef7eb2e8f9f7 196 error("Couldn't setup requested SPI frequency");
<> 144:ef7eb2e8f9f7 197 return;
<> 144:ef7eb2e8f9f7 198 }
<> 144:ef7eb2e8f9f7 199
<> 144:ef7eb2e8f9f7 200 div = (pclk_base / hz / 2);
<> 144:ef7eb2e8f9f7 201 while (div > 256) {
<> 144:ef7eb2e8f9f7 202 div >>= 1;
<> 144:ef7eb2e8f9f7 203 brdv++;
<> 144:ef7eb2e8f9f7 204 }
<> 144:ef7eb2e8f9f7 205 div -= 1;
<> 144:ef7eb2e8f9f7 206 brdv = (brdv << 2);
<> 144:ef7eb2e8f9f7 207
<> 144:ef7eb2e8f9f7 208 spi_disable(obj);
<> 144:ef7eb2e8f9f7 209 obj->spi.spi->SPBR = div;
<> 144:ef7eb2e8f9f7 210 wk_spcmd0 = obj->spi.spi->SPCMD0;
<> 144:ef7eb2e8f9f7 211 wk_spcmd0 &= ~mask;
<> 144:ef7eb2e8f9f7 212 wk_spcmd0 |= (mask & brdv);
<> 144:ef7eb2e8f9f7 213 obj->spi.spi->SPCMD0 = wk_spcmd0;
<> 144:ef7eb2e8f9f7 214 spi_enable(obj);
<> 144:ef7eb2e8f9f7 215 }
<> 144:ef7eb2e8f9f7 216
<> 144:ef7eb2e8f9f7 217 static inline void spi_disable(spi_t *obj) {
<> 144:ef7eb2e8f9f7 218 obj->spi.spi->SPCR &= ~(1 << 6); // SPE to 0
<> 144:ef7eb2e8f9f7 219 }
<> 144:ef7eb2e8f9f7 220
<> 144:ef7eb2e8f9f7 221 static inline void spi_enable(spi_t *obj) {
<> 144:ef7eb2e8f9f7 222 obj->spi.spi->SPCR |= (1 << 6); // SPE to 1
<> 144:ef7eb2e8f9f7 223 }
<> 144:ef7eb2e8f9f7 224
<> 144:ef7eb2e8f9f7 225 static inline int spi_readable(spi_t *obj) {
<> 144:ef7eb2e8f9f7 226 return obj->spi.spi->SPSR & (1 << 7); // SPRF
<> 144:ef7eb2e8f9f7 227 }
<> 144:ef7eb2e8f9f7 228
<> 144:ef7eb2e8f9f7 229 static inline int spi_tend(spi_t *obj) {
<> 144:ef7eb2e8f9f7 230 return obj->spi.spi->SPSR & (1 << 6); // TEND
<> 144:ef7eb2e8f9f7 231 }
<> 144:ef7eb2e8f9f7 232
<> 144:ef7eb2e8f9f7 233 static inline void spi_write(spi_t *obj, int value) {
<> 144:ef7eb2e8f9f7 234 if (obj->spi.bits == 8) {
<> 144:ef7eb2e8f9f7 235 obj->spi.spi->SPDR.UINT8[0] = (uint8_t)value;
<> 144:ef7eb2e8f9f7 236 } else if (obj->spi.bits == 16) {
<> 144:ef7eb2e8f9f7 237 obj->spi.spi->SPDR.UINT16[0] = (uint16_t)value;
<> 144:ef7eb2e8f9f7 238 } else {
<> 144:ef7eb2e8f9f7 239 obj->spi.spi->SPDR.UINT32 = (uint32_t)value;
<> 144:ef7eb2e8f9f7 240 }
<> 144:ef7eb2e8f9f7 241 }
<> 144:ef7eb2e8f9f7 242
<> 144:ef7eb2e8f9f7 243 static inline int spi_read(spi_t *obj) {
<> 144:ef7eb2e8f9f7 244 int read_data;
<> 144:ef7eb2e8f9f7 245
<> 144:ef7eb2e8f9f7 246 if (obj->spi.bits == 8) {
<> 144:ef7eb2e8f9f7 247 read_data = obj->spi.spi->SPDR.UINT8[0];
<> 144:ef7eb2e8f9f7 248 } else if (obj->spi.bits == 16) {
<> 144:ef7eb2e8f9f7 249 read_data = obj->spi.spi->SPDR.UINT16[0];
<> 144:ef7eb2e8f9f7 250 } else {
<> 144:ef7eb2e8f9f7 251 read_data = obj->spi.spi->SPDR.UINT32;
<> 144:ef7eb2e8f9f7 252 }
<> 144:ef7eb2e8f9f7 253
<> 144:ef7eb2e8f9f7 254 return read_data;
<> 144:ef7eb2e8f9f7 255 }
<> 144:ef7eb2e8f9f7 256
<> 144:ef7eb2e8f9f7 257 int spi_master_write(spi_t *obj, int value) {
<> 144:ef7eb2e8f9f7 258 spi_write(obj, value);
<> 144:ef7eb2e8f9f7 259 while(!spi_tend(obj));
<> 144:ef7eb2e8f9f7 260 return spi_read(obj);
<> 144:ef7eb2e8f9f7 261 }
<> 144:ef7eb2e8f9f7 262
<> 144:ef7eb2e8f9f7 263 int spi_slave_receive(spi_t *obj) {
<> 144:ef7eb2e8f9f7 264 return (spi_readable(obj) && !spi_busy(obj)) ? (1) : (0);
<> 144:ef7eb2e8f9f7 265 }
<> 144:ef7eb2e8f9f7 266
<> 144:ef7eb2e8f9f7 267 int spi_slave_read(spi_t *obj) {
<> 144:ef7eb2e8f9f7 268 return spi_read(obj);
<> 144:ef7eb2e8f9f7 269 }
<> 144:ef7eb2e8f9f7 270
<> 144:ef7eb2e8f9f7 271 void spi_slave_write(spi_t *obj, int value) {
<> 144:ef7eb2e8f9f7 272 spi_write(obj, value);
<> 144:ef7eb2e8f9f7 273 }
<> 144:ef7eb2e8f9f7 274
<> 144:ef7eb2e8f9f7 275 int spi_busy(spi_t *obj) {
<> 144:ef7eb2e8f9f7 276 return 0;
<> 144:ef7eb2e8f9f7 277 }
<> 144:ef7eb2e8f9f7 278
<> 144:ef7eb2e8f9f7 279 #if DEVICE_SPI_ASYNCH
<> 144:ef7eb2e8f9f7 280
<> 144:ef7eb2e8f9f7 281 #define IRQ_NUM 2
<> 144:ef7eb2e8f9f7 282
<> 144:ef7eb2e8f9f7 283 static void spi_irqs_set(spi_t *obj, uint32_t enable);
<> 144:ef7eb2e8f9f7 284 static void spi_async_write(spi_t *obj);
<> 144:ef7eb2e8f9f7 285 static void spi_async_read(spi_t *obj);
<> 144:ef7eb2e8f9f7 286
<> 144:ef7eb2e8f9f7 287 static void spi0_rx_irq(void);
<> 144:ef7eb2e8f9f7 288 static void spi1_rx_irq(void);
<> 144:ef7eb2e8f9f7 289 static void spi2_rx_irq(void);
<> 144:ef7eb2e8f9f7 290 static void spi3_rx_irq(void);
<> 144:ef7eb2e8f9f7 291 static void spi4_rx_irq(void);
<> 144:ef7eb2e8f9f7 292 static void spi0_er_irq(void);
<> 144:ef7eb2e8f9f7 293 static void spi1_er_irq(void);
<> 144:ef7eb2e8f9f7 294 static void spi2_er_irq(void);
<> 144:ef7eb2e8f9f7 295 static void spi3_er_irq(void);
<> 144:ef7eb2e8f9f7 296 static void spi4_er_irq(void);
<> 144:ef7eb2e8f9f7 297
<> 144:ef7eb2e8f9f7 298 static const IRQn_Type irq_set_tbl[RSPI_COUNT][IRQ_NUM] = {
<> 144:ef7eb2e8f9f7 299 {RSPISPRI0_IRQn, RSPISPEI0_IRQn},
<> 144:ef7eb2e8f9f7 300 {RSPISPRI1_IRQn, RSPISPEI1_IRQn},
<> 144:ef7eb2e8f9f7 301 {RSPISPRI2_IRQn, RSPISPEI2_IRQn},
<> 144:ef7eb2e8f9f7 302 {RSPISPRI3_IRQn, RSPISPEI3_IRQn},
<> 144:ef7eb2e8f9f7 303 {RSPISPRI4_IRQn, RSPISPEI4_IRQn}
<> 144:ef7eb2e8f9f7 304 };
<> 144:ef7eb2e8f9f7 305
<> 144:ef7eb2e8f9f7 306 static const IRQHandler hander_set_tbl[RSPI_COUNT][IRQ_NUM] = {
<> 144:ef7eb2e8f9f7 307 {spi0_rx_irq, spi0_er_irq},
<> 144:ef7eb2e8f9f7 308 {spi1_rx_irq, spi1_er_irq},
<> 144:ef7eb2e8f9f7 309 {spi2_rx_irq, spi2_er_irq},
<> 144:ef7eb2e8f9f7 310 {spi3_rx_irq, spi3_er_irq},
<> 144:ef7eb2e8f9f7 311 {spi4_rx_irq, spi4_er_irq}
<> 144:ef7eb2e8f9f7 312 };
<> 144:ef7eb2e8f9f7 313
<> 144:ef7eb2e8f9f7 314 struct spi_global_data_s {
<> 144:ef7eb2e8f9f7 315 spi_t *async_obj;
<> 144:ef7eb2e8f9f7 316 uint32_t async_callback, event, wanted_events;
<> 144:ef7eb2e8f9f7 317 };
<> 144:ef7eb2e8f9f7 318
<> 144:ef7eb2e8f9f7 319 static struct spi_global_data_s spi_data[RSPI_COUNT];
<> 144:ef7eb2e8f9f7 320
<> 144:ef7eb2e8f9f7 321 static void spi_rx_irq(IRQn_Type irq_num, uint32_t index)
<> 144:ef7eb2e8f9f7 322 {
<> 144:ef7eb2e8f9f7 323 spi_t *obj = spi_data[index].async_obj;
<> 144:ef7eb2e8f9f7 324 if (obj->rx_buff.buffer && obj->rx_buff.pos < obj->rx_buff.length) {
<> 144:ef7eb2e8f9f7 325 spi_async_read(obj);
<> 144:ef7eb2e8f9f7 326 } else {
<> 144:ef7eb2e8f9f7 327 if (obj->rx_buff.buffer && obj->tx_buff.buffer && obj->tx_buff.pos < obj->tx_buff.length) {
<> 144:ef7eb2e8f9f7 328 spi_data[obj->spi.index].event = SPI_EVENT_INTERNAL_TRANSFER_COMPLETE;
<> 144:ef7eb2e8f9f7 329 if (spi_data[obj->spi.index].wanted_events & SPI_EVENT_COMPLETE) {
<> 144:ef7eb2e8f9f7 330 spi_data[obj->spi.index].event |= SPI_EVENT_COMPLETE;
<> 144:ef7eb2e8f9f7 331 }
<> 144:ef7eb2e8f9f7 332 spi_irqs_set(obj, 0);
<> 144:ef7eb2e8f9f7 333 spi_data[obj->spi.index].async_obj = NULL;
<> 144:ef7eb2e8f9f7 334 ((void (*)())spi_data[obj->spi.index].async_callback)();
<> 144:ef7eb2e8f9f7 335 return;
<> 144:ef7eb2e8f9f7 336 }
<> 144:ef7eb2e8f9f7 337 spi_read(obj);
<> 144:ef7eb2e8f9f7 338 }
<> 144:ef7eb2e8f9f7 339 if (obj->tx_buff.buffer) {
<> 144:ef7eb2e8f9f7 340 if (obj->tx_buff.pos == obj->tx_buff.length) {
<> 144:ef7eb2e8f9f7 341 spi_data[obj->spi.index].event = SPI_EVENT_INTERNAL_TRANSFER_COMPLETE;
<> 144:ef7eb2e8f9f7 342 if (spi_data[obj->spi.index].wanted_events & SPI_EVENT_COMPLETE) {
<> 144:ef7eb2e8f9f7 343 spi_data[obj->spi.index].event |= SPI_EVENT_COMPLETE;
<> 144:ef7eb2e8f9f7 344 }
<> 144:ef7eb2e8f9f7 345 spi_irqs_set(obj, 0);
<> 144:ef7eb2e8f9f7 346 spi_data[obj->spi.index].async_obj = NULL;
<> 144:ef7eb2e8f9f7 347 ((void (*)())spi_data[obj->spi.index].async_callback)();
<> 144:ef7eb2e8f9f7 348 } else {
<> 144:ef7eb2e8f9f7 349 spi_async_write(obj);
<> 144:ef7eb2e8f9f7 350 }
<> 144:ef7eb2e8f9f7 351 } else {
<> 144:ef7eb2e8f9f7 352 if (obj->rx_buff.pos == obj->rx_buff.length) {
<> 144:ef7eb2e8f9f7 353 spi_data[obj->spi.index].event = SPI_EVENT_INTERNAL_TRANSFER_COMPLETE;
<> 144:ef7eb2e8f9f7 354 if (spi_data[obj->spi.index].wanted_events & SPI_EVENT_COMPLETE) {
<> 144:ef7eb2e8f9f7 355 spi_data[obj->spi.index].event |= SPI_EVENT_COMPLETE;
<> 144:ef7eb2e8f9f7 356 }
<> 144:ef7eb2e8f9f7 357 spi_irqs_set(obj, 0);
<> 144:ef7eb2e8f9f7 358 spi_data[obj->spi.index].async_obj = NULL;
<> 144:ef7eb2e8f9f7 359 ((void (*)())spi_data[obj->spi.index].async_callback)();
<> 144:ef7eb2e8f9f7 360 } else {
<> 144:ef7eb2e8f9f7 361 spi_async_write(obj);
<> 144:ef7eb2e8f9f7 362 }
<> 144:ef7eb2e8f9f7 363 }
<> 144:ef7eb2e8f9f7 364 }
<> 144:ef7eb2e8f9f7 365
<> 144:ef7eb2e8f9f7 366 static void spi_err_irq(IRQn_Type irq_num, uint32_t index)
<> 144:ef7eb2e8f9f7 367 {
<> 144:ef7eb2e8f9f7 368 spi_t *obj = spi_data[index].async_obj;
<> 144:ef7eb2e8f9f7 369 spi_abort_asynch(obj);
<> 144:ef7eb2e8f9f7 370 spi_data[index].event = SPI_EVENT_ERROR;
<> 144:ef7eb2e8f9f7 371 if (spi_data[index].wanted_events & SPI_EVENT_ERROR) {
<> 144:ef7eb2e8f9f7 372 ((void (*)())spi_data[index].async_callback)();
<> 144:ef7eb2e8f9f7 373 }
<> 144:ef7eb2e8f9f7 374 }
<> 144:ef7eb2e8f9f7 375
<> 144:ef7eb2e8f9f7 376 static void spi0_rx_irq(void)
<> 144:ef7eb2e8f9f7 377 {
<> 144:ef7eb2e8f9f7 378 spi_rx_irq(RSPISPRI0_IRQn, 0);
<> 144:ef7eb2e8f9f7 379 }
<> 144:ef7eb2e8f9f7 380
<> 144:ef7eb2e8f9f7 381 static void spi1_rx_irq(void)
<> 144:ef7eb2e8f9f7 382 {
<> 144:ef7eb2e8f9f7 383 spi_rx_irq(RSPISPRI1_IRQn, 1);
<> 144:ef7eb2e8f9f7 384 }
<> 144:ef7eb2e8f9f7 385
<> 144:ef7eb2e8f9f7 386 static void spi2_rx_irq(void)
<> 144:ef7eb2e8f9f7 387 {
<> 144:ef7eb2e8f9f7 388 spi_rx_irq(RSPISPRI2_IRQn, 2);
<> 144:ef7eb2e8f9f7 389 }
<> 144:ef7eb2e8f9f7 390
<> 144:ef7eb2e8f9f7 391 static void spi3_rx_irq(void)
<> 144:ef7eb2e8f9f7 392 {
<> 144:ef7eb2e8f9f7 393 spi_rx_irq(RSPISPRI3_IRQn, 3);
<> 144:ef7eb2e8f9f7 394 }
<> 144:ef7eb2e8f9f7 395
<> 144:ef7eb2e8f9f7 396 static void spi4_rx_irq(void)
<> 144:ef7eb2e8f9f7 397 {
<> 144:ef7eb2e8f9f7 398 spi_rx_irq(RSPISPRI4_IRQn, 4);
<> 144:ef7eb2e8f9f7 399 }
<> 144:ef7eb2e8f9f7 400
<> 144:ef7eb2e8f9f7 401 static void spi0_er_irq(void)
<> 144:ef7eb2e8f9f7 402 {
<> 144:ef7eb2e8f9f7 403 spi_err_irq(RSPISPEI0_IRQn, 0);
<> 144:ef7eb2e8f9f7 404 }
<> 144:ef7eb2e8f9f7 405
<> 144:ef7eb2e8f9f7 406 static void spi1_er_irq(void)
<> 144:ef7eb2e8f9f7 407 {
<> 144:ef7eb2e8f9f7 408 spi_err_irq(RSPISPEI1_IRQn, 1);
<> 144:ef7eb2e8f9f7 409 }
<> 144:ef7eb2e8f9f7 410
<> 144:ef7eb2e8f9f7 411 static void spi2_er_irq(void)
<> 144:ef7eb2e8f9f7 412 {
<> 144:ef7eb2e8f9f7 413 spi_err_irq(RSPISPEI2_IRQn, 2);
<> 144:ef7eb2e8f9f7 414 }
<> 144:ef7eb2e8f9f7 415
<> 144:ef7eb2e8f9f7 416 static void spi3_er_irq(void)
<> 144:ef7eb2e8f9f7 417 {
<> 144:ef7eb2e8f9f7 418 spi_err_irq(RSPISPEI3_IRQn, 3);
<> 144:ef7eb2e8f9f7 419 }
<> 144:ef7eb2e8f9f7 420
<> 144:ef7eb2e8f9f7 421 static void spi4_er_irq(void)
<> 144:ef7eb2e8f9f7 422 {
<> 144:ef7eb2e8f9f7 423 spi_err_irq(RSPISPEI4_IRQn, 4);
<> 144:ef7eb2e8f9f7 424 }
<> 144:ef7eb2e8f9f7 425
<> 144:ef7eb2e8f9f7 426 static void spi_irqs_set(spi_t *obj, uint32_t enable)
<> 144:ef7eb2e8f9f7 427 {
<> 144:ef7eb2e8f9f7 428 int i;
<> 144:ef7eb2e8f9f7 429 const IRQn_Type *irqTable = irq_set_tbl[obj->spi.index];
<> 144:ef7eb2e8f9f7 430 const IRQHandler *handlerTable = hander_set_tbl[obj->spi.index];
<> 144:ef7eb2e8f9f7 431 for (i = 0; i < IRQ_NUM; ++i) {
<> 144:ef7eb2e8f9f7 432 if (enable) {
<> 144:ef7eb2e8f9f7 433 InterruptHandlerRegister(irqTable[i], handlerTable[i]);
<> 144:ef7eb2e8f9f7 434 GIC_SetPriority(irqTable[i], 5);
<> 144:ef7eb2e8f9f7 435 GIC_EnableIRQ(irqTable[i]);
<> 144:ef7eb2e8f9f7 436 } else {
<> 144:ef7eb2e8f9f7 437 GIC_DisableIRQ(irqTable[i]);
<> 144:ef7eb2e8f9f7 438 }
<> 144:ef7eb2e8f9f7 439 }
<> 144:ef7eb2e8f9f7 440 if (enable) {
<> 144:ef7eb2e8f9f7 441 obj->spi.spi->SPCR |= (1 << 4) | (1 << 7);
<> 144:ef7eb2e8f9f7 442 } else {
<> 144:ef7eb2e8f9f7 443 obj->spi.spi->SPCR &= ~((1 << 4) | (1 << 7));
<> 144:ef7eb2e8f9f7 444 }
<> 144:ef7eb2e8f9f7 445 }
<> 144:ef7eb2e8f9f7 446
<> 144:ef7eb2e8f9f7 447 static void spi_async_write(spi_t *obj)
<> 144:ef7eb2e8f9f7 448 {
<> 144:ef7eb2e8f9f7 449 uint8_t **width8;
<> 144:ef7eb2e8f9f7 450 uint16_t **width16;
<> 144:ef7eb2e8f9f7 451 uint32_t **width32;
<> 144:ef7eb2e8f9f7 452
<> 144:ef7eb2e8f9f7 453 if (obj->tx_buff.buffer) {
<> 144:ef7eb2e8f9f7 454 switch (obj->tx_buff.width) {
<> 144:ef7eb2e8f9f7 455 case 8:
<> 144:ef7eb2e8f9f7 456 width8 = (uint8_t **)&obj->tx_buff.buffer;
<> 144:ef7eb2e8f9f7 457 spi_write(obj, **width8);
<> 144:ef7eb2e8f9f7 458 ++*width8;
<> 144:ef7eb2e8f9f7 459 obj->tx_buff.pos += sizeof(uint8_t);
<> 144:ef7eb2e8f9f7 460 break;
<> 144:ef7eb2e8f9f7 461
<> 144:ef7eb2e8f9f7 462 case 16:
<> 144:ef7eb2e8f9f7 463 width16 = (uint16_t **)&obj->tx_buff.buffer;
<> 144:ef7eb2e8f9f7 464 spi_write(obj, **width16);
<> 144:ef7eb2e8f9f7 465 ++*width16;
<> 144:ef7eb2e8f9f7 466 obj->tx_buff.pos += sizeof(uint16_t);
<> 144:ef7eb2e8f9f7 467 break;
<> 144:ef7eb2e8f9f7 468
<> 144:ef7eb2e8f9f7 469 case 32:
<> 144:ef7eb2e8f9f7 470 width32 = (uint32_t **)&obj->tx_buff.buffer;
<> 144:ef7eb2e8f9f7 471 spi_write(obj, **width32);
<> 144:ef7eb2e8f9f7 472 ++*width32;
<> 144:ef7eb2e8f9f7 473 obj->tx_buff.pos += sizeof(uint32_t);
<> 144:ef7eb2e8f9f7 474 break;
<> 144:ef7eb2e8f9f7 475
<> 144:ef7eb2e8f9f7 476 default:
<> 144:ef7eb2e8f9f7 477 MBED_ASSERT(0);
<> 144:ef7eb2e8f9f7 478 break;
<> 144:ef7eb2e8f9f7 479 }
<> 144:ef7eb2e8f9f7 480 } else {
<> 144:ef7eb2e8f9f7 481 spi_write(obj, SPI_FILL_WORD);
<> 144:ef7eb2e8f9f7 482 }
<> 144:ef7eb2e8f9f7 483 }
<> 144:ef7eb2e8f9f7 484
<> 144:ef7eb2e8f9f7 485 static void spi_async_read(spi_t *obj)
<> 144:ef7eb2e8f9f7 486 {
<> 144:ef7eb2e8f9f7 487 uint8_t **width8;
<> 144:ef7eb2e8f9f7 488 uint16_t **width16;
<> 144:ef7eb2e8f9f7 489 uint32_t **width32;
<> 144:ef7eb2e8f9f7 490
<> 144:ef7eb2e8f9f7 491 switch (obj->rx_buff.width) {
<> 144:ef7eb2e8f9f7 492 case 8:
<> 144:ef7eb2e8f9f7 493 width8 = (uint8_t **)&obj->rx_buff.buffer;
<> 144:ef7eb2e8f9f7 494 **width8 = spi_read(obj);
<> 144:ef7eb2e8f9f7 495 ++*width8;
<> 144:ef7eb2e8f9f7 496 obj->rx_buff.pos += sizeof(uint8_t);
<> 144:ef7eb2e8f9f7 497 break;
<> 144:ef7eb2e8f9f7 498
<> 144:ef7eb2e8f9f7 499 case 16:
<> 144:ef7eb2e8f9f7 500 width16 = (uint16_t **)&obj->rx_buff.buffer;
<> 144:ef7eb2e8f9f7 501 **width16 = spi_read(obj);
<> 144:ef7eb2e8f9f7 502 ++*width16;
<> 144:ef7eb2e8f9f7 503 obj->rx_buff.pos += sizeof(uint16_t);
<> 144:ef7eb2e8f9f7 504 break;
<> 144:ef7eb2e8f9f7 505
<> 144:ef7eb2e8f9f7 506 case 32:
<> 144:ef7eb2e8f9f7 507 width32 = (uint32_t **)&obj->rx_buff.buffer;
<> 144:ef7eb2e8f9f7 508 **width32 = spi_read(obj);
<> 144:ef7eb2e8f9f7 509 ++*width32;
<> 144:ef7eb2e8f9f7 510 obj->rx_buff.pos += sizeof(uint32_t);
<> 144:ef7eb2e8f9f7 511 break;
<> 144:ef7eb2e8f9f7 512
<> 144:ef7eb2e8f9f7 513 default:
<> 144:ef7eb2e8f9f7 514 MBED_ASSERT(0);
<> 144:ef7eb2e8f9f7 515 break;
<> 144:ef7eb2e8f9f7 516 }
<> 144:ef7eb2e8f9f7 517 }
<> 144:ef7eb2e8f9f7 518
<> 144:ef7eb2e8f9f7 519 /******************************************************************************
<> 144:ef7eb2e8f9f7 520 * ASYNCHRONOUS HAL
<> 144:ef7eb2e8f9f7 521 ******************************************************************************/
<> 144:ef7eb2e8f9f7 522
<> 144:ef7eb2e8f9f7 523 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)
<> 144:ef7eb2e8f9f7 524 {
<> 144:ef7eb2e8f9f7 525 int i;
<> 144:ef7eb2e8f9f7 526 MBED_ASSERT(obj);
<> 144:ef7eb2e8f9f7 527 MBED_ASSERT(tx || rx);
<> 144:ef7eb2e8f9f7 528 MBED_ASSERT(tx && ! rx ? tx_length : 1);
<> 144:ef7eb2e8f9f7 529 MBED_ASSERT(rx && ! tx ? rx_length : 1);
<> 144:ef7eb2e8f9f7 530 MBED_ASSERT(obj->spi.spi->SPCR & (1 << 3)); /* Slave mode */
<> 144:ef7eb2e8f9f7 531 MBED_ASSERT(bit_width == 8 || bit_width == 16 || bit_width == 32);
<> 144:ef7eb2e8f9f7 532
<> 144:ef7eb2e8f9f7 533 if (tx_length) {
<> 144:ef7eb2e8f9f7 534 obj->tx_buff.buffer = (void *)tx;
<> 144:ef7eb2e8f9f7 535 } else {
<> 144:ef7eb2e8f9f7 536 obj->tx_buff.buffer = NULL;
<> 144:ef7eb2e8f9f7 537 }
<> 144:ef7eb2e8f9f7 538 obj->tx_buff.length = tx_length * bit_width / 8;
<> 144:ef7eb2e8f9f7 539 obj->tx_buff.pos = 0;
<> 144:ef7eb2e8f9f7 540 obj->tx_buff.width = bit_width;
<> 144:ef7eb2e8f9f7 541 if (rx_length) {
<> 144:ef7eb2e8f9f7 542 obj->rx_buff.buffer = rx;
<> 144:ef7eb2e8f9f7 543 } else {
<> 144:ef7eb2e8f9f7 544 obj->rx_buff.buffer = NULL;
<> 144:ef7eb2e8f9f7 545 }
<> 144:ef7eb2e8f9f7 546 obj->rx_buff.length = rx_length * bit_width / 8;
<> 144:ef7eb2e8f9f7 547 obj->rx_buff.pos = 0;
<> 144:ef7eb2e8f9f7 548 obj->rx_buff.width = bit_width;
<> 144:ef7eb2e8f9f7 549 for (i = 0; i < obj->rx_buff.length; i++) {
<> 144:ef7eb2e8f9f7 550 ((uint8_t *)obj->rx_buff.buffer)[i] = SPI_FILL_WORD;
<> 144:ef7eb2e8f9f7 551 }
<> 144:ef7eb2e8f9f7 552
<> 144:ef7eb2e8f9f7 553 spi_data[obj->spi.index].async_callback = handler;
<> 144:ef7eb2e8f9f7 554 spi_data[obj->spi.index].async_obj = obj;
<> 144:ef7eb2e8f9f7 555 spi_data[obj->spi.index].event = 0;
<> 144:ef7eb2e8f9f7 556 spi_data[obj->spi.index].wanted_events = event;
<> 144:ef7eb2e8f9f7 557
<> 144:ef7eb2e8f9f7 558 spi_irqs_set(obj, 1);
<> 144:ef7eb2e8f9f7 559
<> 144:ef7eb2e8f9f7 560 spi_async_write(obj);
<> 144:ef7eb2e8f9f7 561 }
<> 144:ef7eb2e8f9f7 562
<> 144:ef7eb2e8f9f7 563 uint32_t spi_irq_handler_asynch(spi_t *obj)
<> 144:ef7eb2e8f9f7 564 {
<> 144:ef7eb2e8f9f7 565 return spi_data[obj->spi.index].event;
<> 144:ef7eb2e8f9f7 566 }
<> 144:ef7eb2e8f9f7 567
<> 144:ef7eb2e8f9f7 568 uint8_t spi_active(spi_t *obj)
<> 144:ef7eb2e8f9f7 569 {
<> 144:ef7eb2e8f9f7 570 return spi_data[obj->spi.index].async_obj != NULL;
<> 144:ef7eb2e8f9f7 571 }
<> 144:ef7eb2e8f9f7 572
<> 144:ef7eb2e8f9f7 573 void spi_abort_asynch(spi_t *obj)
<> 144:ef7eb2e8f9f7 574 {
<> 144:ef7eb2e8f9f7 575 spi_disable(obj);
<> 144:ef7eb2e8f9f7 576 spi_irqs_set(obj, 0);
<> 144:ef7eb2e8f9f7 577 spi_data[obj->spi.index].async_obj = NULL;
<> 144:ef7eb2e8f9f7 578 spi_enable(obj);
<> 144:ef7eb2e8f9f7 579 }
<> 144:ef7eb2e8f9f7 580
<> 144:ef7eb2e8f9f7 581 #endif