added prescaler for 16 bit pwm in LPC1347 target

Fork of mbed-dev by mbed official

Committer:
<>
Date:
Fri Sep 02 15:07:44 2016 +0100
Revision:
144:ef7eb2e8f9f7
Parent:
119:3921aeca8633
This updates the lib to the mbed lib v125

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