|
@@ -111,6 +111,9 @@
|
111
|
111
|
#define DELAY_NS(x) DELAY_CYCLES( (x) * (F_CPU/1000000) / 1000)
|
112
|
112
|
|
113
|
113
|
typedef uint8_t (*pfnSpiTransfer) (uint8_t b);
|
|
114
|
+ typedef void (*pfnSpiRxBlock)(uint8_t* buf, uint32_t nbyte);
|
|
115
|
+ typedef void (*pfnSpiTxBlock)(const uint8_t* buf, uint32_t nbyte);
|
|
116
|
+
|
114
|
117
|
|
115
|
118
|
/* ---------------- Macros to be able to access definitions from asm */
|
116
|
119
|
|
|
@@ -183,26 +186,32 @@
|
183
|
186
|
/* Bit 0 */
|
184
|
187
|
" str %[mosi_mask],[%[mosi_port], %[idx],LSL #2]" "\n\t" /* Access the proper SODR or CODR registers based on that bit */
|
185
|
188
|
" str %[sck_mask],[%[sck_port]]" "\n\t" /* SODR */
|
186
|
|
- " nop" "\n\t"
|
|
189
|
+ " nop" "\n\t" /* Result will be 0 */
|
187
|
190
|
" str %[sck_mask],[%[sck_port],#0x4]" "\n\t" /* CODR */
|
188
|
191
|
|
189
|
|
- : [mosi_mask]"+r"( MOSI_MASK ),
|
190
|
|
- [mosi_port]"+r"( MOSI_PORT_PLUS30 ),
|
191
|
|
- [sck_mask]"+r"( SCK_MASK ),
|
192
|
|
- [sck_port]"+r"( SCK_PORT_PLUS30 ),
|
193
|
|
- [idx]"+r"( idx ),
|
194
|
|
- [txval]"+r"( bout )
|
195
|
|
- :
|
|
192
|
+ : [idx]"+r"( idx )
|
|
193
|
+ : [txval]"r"( bout ) ,
|
|
194
|
+ [mosi_mask]"r"( MOSI_MASK ),
|
|
195
|
+ [mosi_port]"r"( MOSI_PORT_PLUS30 ),
|
|
196
|
+ [sck_mask]"r"( SCK_MASK ),
|
|
197
|
+ [sck_port]"r"( SCK_PORT_PLUS30 )
|
196
|
198
|
: "cc"
|
197
|
199
|
);
|
198
|
200
|
|
199
|
201
|
return 0;
|
200
|
202
|
}
|
201
|
203
|
|
|
204
|
+ // Calculates the bit band alias address and returns a pointer address to word.
|
|
205
|
+ // addr: The byte address of bitbanding bit.
|
|
206
|
+ // bit: The bit position of bitbanding bit.
|
|
207
|
+#define BITBAND_ADDRESS(addr, bit) \
|
|
208
|
+ (((uint32_t)(addr) & 0xF0000000) + 0x02000000 + ((uint32_t)(addr)&0xFFFFF)*32 + (bit)*4)
|
|
209
|
+
|
202
|
210
|
// run at ~8 .. ~10Mhz - Rx version (Tx line not altered)
|
203
|
211
|
static uint8_t spiTransferRx0(uint8_t bout) { // using Mode 0
|
204
|
|
- int bin = 0, work = 0;
|
205
|
|
- register uint32_t MISO_PORT_PLUS3C = ((uint32_t) PORT(MISO_PIN)) + 0x3C; /* PDSR of port */
|
|
212
|
+ register uint32_t bin;
|
|
213
|
+ register uint32_t work;
|
|
214
|
+ register uint32_t BITBAND_MISO_PORT = BITBAND_ADDRESS( ((uint32_t)PORT(MISO_PIN))+0x3C, PIN_SHIFT(MISO_PIN)); /* PDSR of port in bitband area */
|
206
|
215
|
register uint32_t SCK_PORT_PLUS30 = ((uint32_t) PORT(SCK_PIN)) + 0x30; /* SODR of port */
|
207
|
216
|
register uint32_t SCK_MASK = PIN_MASK(SCK_PIN);
|
208
|
217
|
UNUSED(bout);
|
|
@@ -213,70 +222,61 @@
|
213
|
222
|
|
214
|
223
|
/* bit 7 */
|
215
|
224
|
" str %[sck_mask],[%[sck_port]]" "\n\t" /* SODR */
|
216
|
|
- " ldr %[work],[%[miso_port]]" "\n\t" /* PDSR */
|
|
225
|
+ " ldr %[work],[%[bitband_miso_port]]" "\n\t" /* PDSR on bitband area for required bit: work will be 1 or 0 based on port */
|
217
|
226
|
" str %[sck_mask],[%[sck_port],#0x4]" "\n\t" /* CODR */
|
218
|
|
- " lsrs %[work],%[work],%[miso_shift]" "\n\t" /* Isolate input into carry */
|
219
|
|
- " adc %[bin],%[bin],%[bin]" "\n\t" /* Shift left result and add the carry */
|
|
227
|
+ " bfi %[bin],%[work],#7,#1" "\n\t" /* Store read bit as the bit 7 */
|
220
|
228
|
|
221
|
229
|
/* bit 6 */
|
222
|
230
|
" str %[sck_mask],[%[sck_port]]" "\n\t" /* SODR */
|
223
|
|
- " ldr %[work],[%[miso_port]]" "\n\t" /* PDSR */
|
|
231
|
+ " ldr %[work],[%[bitband_miso_port]]" "\n\t" /* PDSR on bitband area for required bit: work will be 1 or 0 based on port */
|
224
|
232
|
" str %[sck_mask],[%[sck_port],#0x4]" "\n\t" /* CODR */
|
225
|
|
- " lsrs %[work],%[work],%[miso_shift]" "\n\t" /* Isolate input into carry */
|
226
|
|
- " adc %[bin],%[bin],%[bin]" "\n\t" /* Shift left result and add the carry */
|
|
233
|
+ " bfi %[bin],%[work],#6,#1" "\n\t" /* Store read bit as the bit 6 */
|
227
|
234
|
|
228
|
235
|
/* bit 5 */
|
229
|
236
|
" str %[sck_mask],[%[sck_port]]" "\n\t" /* SODR */
|
230
|
|
- " ldr %[work],[%[miso_port]]" "\n\t" /* PDSR */
|
|
237
|
+ " ldr %[work],[%[bitband_miso_port]]" "\n\t" /* PDSR on bitband area for required bit: work will be 1 or 0 based on port */
|
231
|
238
|
" str %[sck_mask],[%[sck_port],#0x4]" "\n\t" /* CODR */
|
232
|
|
- " lsrs %[work],%[work],%[miso_shift]" "\n\t" /* Isolate input into carry */
|
233
|
|
- " adc %[bin],%[bin],%[bin]" "\n\t" /* Shift left result and add the carry */
|
|
239
|
+ " bfi %[bin],%[work],#5,#1" "\n\t" /* Store read bit as the bit 5 */
|
234
|
240
|
|
235
|
241
|
/* bit 4 */
|
236
|
242
|
" str %[sck_mask],[%[sck_port]]" "\n\t" /* SODR */
|
237
|
|
- " ldr %[work],[%[miso_port]]" "\n\t" /* PDSR */
|
|
243
|
+ " ldr %[work],[%[bitband_miso_port]]" "\n\t" /* PDSR on bitband area for required bit: work will be 1 or 0 based on port */
|
238
|
244
|
" str %[sck_mask],[%[sck_port],#0x4]" "\n\t" /* CODR */
|
239
|
|
- " lsrs %[work],%[work],%[miso_shift]" "\n\t" /* Isolate input into carry */
|
240
|
|
- " adc %[bin],%[bin],%[bin]" "\n\t" /* Shift left result and add the carry */
|
|
245
|
+ " bfi %[bin],%[work],#4,#1" "\n\t" /* Store read bit as the bit 4 */
|
241
|
246
|
|
242
|
247
|
/* bit 3 */
|
243
|
248
|
" str %[sck_mask],[%[sck_port]]" "\n\t" /* SODR */
|
244
|
|
- " ldr %[work],[%[miso_port]]" "\n\t" /* PDSR */
|
|
249
|
+ " ldr %[work],[%[bitband_miso_port]]" "\n\t" /* PDSR on bitband area for required bit: work will be 1 or 0 based on port */
|
245
|
250
|
" str %[sck_mask],[%[sck_port],#0x4]" "\n\t" /* CODR */
|
246
|
|
- " lsrs %[work],%[work],%[miso_shift]" "\n\t" /* Isolate input into carry */
|
247
|
|
- " adc %[bin],%[bin],%[bin]" "\n\t" /* Shift left result and add the carry */
|
|
251
|
+ " bfi %[bin],%[work],#3,#1" "\n\t" /* Store read bit as the bit 3 */
|
248
|
252
|
|
249
|
253
|
/* bit 2 */
|
250
|
254
|
" str %[sck_mask],[%[sck_port]]" "\n\t" /* SODR */
|
251
|
|
- " ldr %[work],[%[miso_port]]" "\n\t" /* PDSR */
|
|
255
|
+ " ldr %[work],[%[bitband_miso_port]]" "\n\t" /* PDSR on bitband area for required bit: work will be 1 or 0 based on port */
|
252
|
256
|
" str %[sck_mask],[%[sck_port],#0x4]" "\n\t" /* CODR */
|
253
|
|
- " lsrs %[work],%[work],%[miso_shift]" "\n\t" /* Isolate input into carry */
|
254
|
|
- " adc %[bin],%[bin],%[bin]" "\n\t" /* Shift left result and add the carry */
|
|
257
|
+ " bfi %[bin],%[work],#2,#1" "\n\t" /* Store read bit as the bit 2 */
|
255
|
258
|
|
256
|
259
|
/* bit 1 */
|
257
|
260
|
" str %[sck_mask],[%[sck_port]]" "\n\t" /* SODR */
|
258
|
|
- " ldr %[work],[%[miso_port]]" "\n\t" /* PDSR */
|
|
261
|
+ " ldr %[work],[%[bitband_miso_port]]" "\n\t" /* PDSR on bitband area for required bit: work will be 1 or 0 based on port */
|
259
|
262
|
" str %[sck_mask],[%[sck_port],#0x4]" "\n\t" /* CODR */
|
260
|
|
- " lsrs %[work],%[work],%[miso_shift]" "\n\t" /* Isolate input into carry */
|
261
|
|
- " adc %[bin],%[bin],%[bin]" "\n\t" /* Shift left result and add the carry */
|
|
263
|
+ " bfi %[bin],%[work],#1,#1" "\n\t" /* Store read bit as the bit 1 */
|
262
|
264
|
|
263
|
265
|
/* bit 0 */
|
264
|
266
|
" str %[sck_mask],[%[sck_port]]" "\n\t" /* SODR */
|
265
|
|
- " ldr %[work],[%[miso_port]]" "\n\t" /* PDSR */
|
|
267
|
+ " ldr %[work],[%[bitband_miso_port]]" "\n\t" /* PDSR on bitband area for required bit: work will be 1 or 0 based on port */
|
266
|
268
|
" str %[sck_mask],[%[sck_port],#0x4]" "\n\t" /* CODR */
|
267
|
|
- " lsrs %[work],%[work],%[miso_shift]" "\n\t" /* Isolate input into carry */
|
268
|
|
- " adc %[bin],%[bin],%[bin]" "\n\t" /* Shift left result and add the carry */
|
|
269
|
+ " bfi %[bin],%[work],#0,#1" "\n\t" /* Store read bit as the bit 0 */
|
269
|
270
|
|
270
|
|
- : [miso_port]"+r"( MISO_PORT_PLUS3C ),
|
271
|
|
- [sck_mask]"+r"( SCK_MASK ),
|
272
|
|
- [sck_port]"+r"( SCK_PORT_PLUS30 ),
|
273
|
|
- [bin]"+r"(bin),
|
|
271
|
+ : [bin]"+r"(bin),
|
274
|
272
|
[work]"+r"(work)
|
275
|
|
- : [miso_shift]"M"( PIN_SHIFT(MISO_PIN) + 1 ) /* So we move to the carry */
|
|
273
|
+ : [bitband_miso_port]"r"( BITBAND_MISO_PORT ),
|
|
274
|
+ [sck_mask]"r"( SCK_MASK ),
|
|
275
|
+ [sck_port]"r"( SCK_PORT_PLUS30 )
|
276
|
276
|
: "cc"
|
277
|
277
|
);
|
278
|
278
|
|
279
|
|
- return (uint8_t)bin;
|
|
279
|
+ return bin;
|
280
|
280
|
}
|
281
|
281
|
|
282
|
282
|
// run at ~4Mhz
|
|
@@ -317,10 +317,182 @@
|
317
|
317
|
return b;
|
318
|
318
|
}
|
319
|
319
|
|
320
|
|
- // Pointers to generic functions
|
|
320
|
+ // Pointers to generic functions for byte transfers
|
321
|
321
|
static pfnSpiTransfer spiTransferTx = spiTransferX;
|
322
|
322
|
static pfnSpiTransfer spiTransferRx = spiTransferX;
|
323
|
323
|
|
|
324
|
+ // Block transfers run at ~8 .. ~10Mhz - Tx version (Rx data discarded)
|
|
325
|
+ static void spiTxBlock0(const uint8_t* ptr, uint32_t todo) {
|
|
326
|
+ register uint32_t MOSI_PORT_PLUS30 = ((uint32_t) PORT(MOSI_PIN)) + 0x30; /* SODR of port */
|
|
327
|
+ register uint32_t MOSI_MASK = PIN_MASK(MOSI_PIN);
|
|
328
|
+ register uint32_t SCK_PORT_PLUS30 = ((uint32_t) PORT(SCK_PIN)) + 0x30; /* SODR of port */
|
|
329
|
+ register uint32_t SCK_MASK = PIN_MASK(SCK_PIN);
|
|
330
|
+ register uint32_t work;
|
|
331
|
+ register uint32_t txval;
|
|
332
|
+
|
|
333
|
+ /* The software SPI routine */
|
|
334
|
+ __asm__ __volatile__(
|
|
335
|
+ ".syntax unified" "\n\t" // is to prevent CM0,CM1 non-unified syntax
|
|
336
|
+
|
|
337
|
+ " loop%=:" "\n\t"
|
|
338
|
+ " ldrb.w %[txval], [%[ptr]], #1" "\n\t" /* Load value to send, increment buffer */
|
|
339
|
+ " mvn %[txval],%[txval]" "\n\t" /* Negate value */
|
|
340
|
+
|
|
341
|
+ /* Bit 7 */
|
|
342
|
+ " ubfx %[work],%[txval],#7,#1" "\n\t" /* Place bit 7 in bit 0 of work*/
|
|
343
|
+
|
|
344
|
+ " str %[mosi_mask],[%[mosi_port], %[work],LSL #2]" "\n\t" /* Access the proper SODR or CODR registers based on that bit */
|
|
345
|
+ " str %[sck_mask],[%[sck_port]]" "\n\t" /* SODR */
|
|
346
|
+ " ubfx %[work],%[txval],#6,#1" "\n\t" /* Place bit 6 in bit 0 of work*/
|
|
347
|
+ " str %[sck_mask],[%[sck_port],#0x4]" "\n\t" /* CODR */
|
|
348
|
+
|
|
349
|
+ /* Bit 6 */
|
|
350
|
+ " str %[mosi_mask],[%[mosi_port], %[work],LSL #2]" "\n\t" /* Access the proper SODR or CODR registers based on that bit */
|
|
351
|
+ " str %[sck_mask],[%[sck_port]]" "\n\t" /* SODR */
|
|
352
|
+ " ubfx %[work],%[txval],#5,#1" "\n\t" /* Place bit 5 in bit 0 of work*/
|
|
353
|
+ " str %[sck_mask],[%[sck_port],#0x4]" "\n\t" /* CODR */
|
|
354
|
+
|
|
355
|
+ /* Bit 5 */
|
|
356
|
+ " str %[mosi_mask],[%[mosi_port], %[work],LSL #2]" "\n\t" /* Access the proper SODR or CODR registers based on that bit */
|
|
357
|
+ " str %[sck_mask],[%[sck_port]]" "\n\t" /* SODR */
|
|
358
|
+ " ubfx %[work],%[txval],#4,#1" "\n\t" /* Place bit 4 in bit 0 of work*/
|
|
359
|
+ " str %[sck_mask],[%[sck_port],#0x4]" "\n\t" /* CODR */
|
|
360
|
+
|
|
361
|
+ /* Bit 4 */
|
|
362
|
+ " str %[mosi_mask],[%[mosi_port], %[work],LSL #2]" "\n\t" /* Access the proper SODR or CODR registers based on that bit */
|
|
363
|
+ " str %[sck_mask],[%[sck_port]]" "\n\t" /* SODR */
|
|
364
|
+ " ubfx %[work],%[txval],#3,#1" "\n\t" /* Place bit 3 in bit 0 of work*/
|
|
365
|
+ " str %[sck_mask],[%[sck_port],#0x4]" "\n\t" /* CODR */
|
|
366
|
+
|
|
367
|
+ /* Bit 3 */
|
|
368
|
+ " str %[mosi_mask],[%[mosi_port], %[work],LSL #2]" "\n\t" /* Access the proper SODR or CODR registers based on that bit */
|
|
369
|
+ " str %[sck_mask],[%[sck_port]]" "\n\t" /* SODR */
|
|
370
|
+ " ubfx %[work],%[txval],#2,#1" "\n\t" /* Place bit 2 in bit 0 of work*/
|
|
371
|
+ " str %[sck_mask],[%[sck_port],#0x4]" "\n\t" /* CODR */
|
|
372
|
+
|
|
373
|
+ /* Bit 2 */
|
|
374
|
+ " str %[mosi_mask],[%[mosi_port], %[work],LSL #2]" "\n\t" /* Access the proper SODR or CODR registers based on that bit */
|
|
375
|
+ " str %[sck_mask],[%[sck_port]]" "\n\t" /* SODR */
|
|
376
|
+ " ubfx %[work],%[txval],#1,#1" "\n\t" /* Place bit 1 in bit 0 of work*/
|
|
377
|
+ " str %[sck_mask],[%[sck_port],#0x4]" "\n\t" /* CODR */
|
|
378
|
+
|
|
379
|
+ /* Bit 1 */
|
|
380
|
+ " str %[mosi_mask],[%[mosi_port], %[work],LSL #2]" "\n\t" /* Access the proper SODR or CODR registers based on that bit */
|
|
381
|
+ " str %[sck_mask],[%[sck_port]]" "\n\t" /* SODR */
|
|
382
|
+ " ubfx %[work],%[txval],#0,#1" "\n\t" /* Place bit 0 in bit 0 of work*/
|
|
383
|
+ " str %[sck_mask],[%[sck_port],#0x4]" "\n\t" /* CODR */
|
|
384
|
+
|
|
385
|
+ /* Bit 0 */
|
|
386
|
+ " str %[mosi_mask],[%[mosi_port], %[work],LSL #2]" "\n\t" /* Access the proper SODR or CODR registers based on that bit */
|
|
387
|
+ " str %[sck_mask],[%[sck_port]]" "\n\t" /* SODR */
|
|
388
|
+ " subs %[todo],#1" "\n\t" /* Decrement count of pending words to send, update status */
|
|
389
|
+ " str %[sck_mask],[%[sck_port],#0x4]" "\n\t" /* CODR */
|
|
390
|
+ " bne.n loop%=" "\n\t" /* Repeat until done */
|
|
391
|
+
|
|
392
|
+ : [ptr]"+r" ( ptr ) ,
|
|
393
|
+ [todo]"+r" ( todo ) ,
|
|
394
|
+ [work]"+r"( work ) ,
|
|
395
|
+ [txval]"+r"( txval )
|
|
396
|
+ : [mosi_mask]"r"( MOSI_MASK ),
|
|
397
|
+ [mosi_port]"r"( MOSI_PORT_PLUS30 ),
|
|
398
|
+ [sck_mask]"r"( SCK_MASK ),
|
|
399
|
+ [sck_port]"r"( SCK_PORT_PLUS30 )
|
|
400
|
+ : "cc"
|
|
401
|
+ );
|
|
402
|
+ }
|
|
403
|
+
|
|
404
|
+ static void spiRxBlock0(uint8_t* ptr, uint32_t todo) {
|
|
405
|
+ register uint32_t bin;
|
|
406
|
+ register uint32_t work;
|
|
407
|
+ register uint32_t BITBAND_MISO_PORT = BITBAND_ADDRESS( ((uint32_t)PORT(MISO_PIN))+0x3C, PIN_SHIFT(MISO_PIN)); /* PDSR of port in bitband area */
|
|
408
|
+ register uint32_t SCK_PORT_PLUS30 = ((uint32_t) PORT(SCK_PIN)) + 0x30; /* SODR of port */
|
|
409
|
+ register uint32_t SCK_MASK = PIN_MASK(SCK_PIN);
|
|
410
|
+
|
|
411
|
+ /* The software SPI routine */
|
|
412
|
+ __asm__ __volatile__(
|
|
413
|
+ ".syntax unified" "\n\t" // is to prevent CM0,CM1 non-unified syntax
|
|
414
|
+
|
|
415
|
+ " loop%=:" "\n\t"
|
|
416
|
+
|
|
417
|
+ /* bit 7 */
|
|
418
|
+ " str %[sck_mask],[%[sck_port]]" "\n\t" /* SODR */
|
|
419
|
+ " ldr %[work],[%[bitband_miso_port]]" "\n\t" /* PDSR on bitband area for required bit: work will be 1 or 0 based on port */
|
|
420
|
+ " str %[sck_mask],[%[sck_port],#0x4]" "\n\t" /* CODR */
|
|
421
|
+ " bfi %[bin],%[work],#7,#1" "\n\t" /* Store read bit as the bit 7 */
|
|
422
|
+
|
|
423
|
+ /* bit 6 */
|
|
424
|
+ " str %[sck_mask],[%[sck_port]]" "\n\t" /* SODR */
|
|
425
|
+ " ldr %[work],[%[bitband_miso_port]]" "\n\t" /* PDSR on bitband area for required bit: work will be 1 or 0 based on port */
|
|
426
|
+ " str %[sck_mask],[%[sck_port],#0x4]" "\n\t" /* CODR */
|
|
427
|
+ " bfi %[bin],%[work],#6,#1" "\n\t" /* Store read bit as the bit 6 */
|
|
428
|
+
|
|
429
|
+ /* bit 5 */
|
|
430
|
+ " str %[sck_mask],[%[sck_port]]" "\n\t" /* SODR */
|
|
431
|
+ " ldr %[work],[%[bitband_miso_port]]" "\n\t" /* PDSR on bitband area for required bit: work will be 1 or 0 based on port */
|
|
432
|
+ " str %[sck_mask],[%[sck_port],#0x4]" "\n\t" /* CODR */
|
|
433
|
+ " bfi %[bin],%[work],#5,#1" "\n\t" /* Store read bit as the bit 5 */
|
|
434
|
+
|
|
435
|
+ /* bit 4 */
|
|
436
|
+ " str %[sck_mask],[%[sck_port]]" "\n\t" /* SODR */
|
|
437
|
+ " ldr %[work],[%[bitband_miso_port]]" "\n\t" /* PDSR on bitband area for required bit: work will be 1 or 0 based on port */
|
|
438
|
+ " str %[sck_mask],[%[sck_port],#0x4]" "\n\t" /* CODR */
|
|
439
|
+ " bfi %[bin],%[work],#4,#1" "\n\t" /* Store read bit as the bit 4 */
|
|
440
|
+
|
|
441
|
+ /* bit 3 */
|
|
442
|
+ " str %[sck_mask],[%[sck_port]]" "\n\t" /* SODR */
|
|
443
|
+ " ldr %[work],[%[bitband_miso_port]]" "\n\t" /* PDSR on bitband area for required bit: work will be 1 or 0 based on port */
|
|
444
|
+ " str %[sck_mask],[%[sck_port],#0x4]" "\n\t" /* CODR */
|
|
445
|
+ " bfi %[bin],%[work],#3,#1" "\n\t" /* Store read bit as the bit 3 */
|
|
446
|
+
|
|
447
|
+ /* bit 2 */
|
|
448
|
+ " str %[sck_mask],[%[sck_port]]" "\n\t" /* SODR */
|
|
449
|
+ " ldr %[work],[%[bitband_miso_port]]" "\n\t" /* PDSR on bitband area for required bit: work will be 1 or 0 based on port */
|
|
450
|
+ " str %[sck_mask],[%[sck_port],#0x4]" "\n\t" /* CODR */
|
|
451
|
+ " bfi %[bin],%[work],#2,#1" "\n\t" /* Store read bit as the bit 2 */
|
|
452
|
+
|
|
453
|
+ /* bit 1 */
|
|
454
|
+ " str %[sck_mask],[%[sck_port]]" "\n\t" /* SODR */
|
|
455
|
+ " ldr %[work],[%[bitband_miso_port]]" "\n\t" /* PDSR on bitband area for required bit: work will be 1 or 0 based on port */
|
|
456
|
+ " str %[sck_mask],[%[sck_port],#0x4]" "\n\t" /* CODR */
|
|
457
|
+ " bfi %[bin],%[work],#1,#1" "\n\t" /* Store read bit as the bit 1 */
|
|
458
|
+
|
|
459
|
+ /* bit 0 */
|
|
460
|
+ " str %[sck_mask],[%[sck_port]]" "\n\t" /* SODR */
|
|
461
|
+ " ldr %[work],[%[bitband_miso_port]]" "\n\t" /* PDSR on bitband area for required bit: work will be 1 or 0 based on port */
|
|
462
|
+ " str %[sck_mask],[%[sck_port],#0x4]" "\n\t" /* CODR */
|
|
463
|
+ " bfi %[bin],%[work],#0,#1" "\n\t" /* Store read bit as the bit 0 */
|
|
464
|
+
|
|
465
|
+ " subs %[todo],#1" "\n\t" /* Decrement count of pending words to send, update status */
|
|
466
|
+ " strb.w %[bin], [%[ptr]], #1" "\n\t" /* Store read value into buffer, increment buffer pointer */
|
|
467
|
+ " bne.n loop%=" "\n\t" /* Repeat until done */
|
|
468
|
+
|
|
469
|
+ : [ptr]"+r"(ptr),
|
|
470
|
+ [todo]"+r"(todo),
|
|
471
|
+ [bin]"+r"(bin),
|
|
472
|
+ [work]"+r"(work)
|
|
473
|
+ : [bitband_miso_port]"r"( BITBAND_MISO_PORT ),
|
|
474
|
+ [sck_mask]"r"( SCK_MASK ),
|
|
475
|
+ [sck_port]"r"( SCK_PORT_PLUS30 )
|
|
476
|
+ : "cc"
|
|
477
|
+ );
|
|
478
|
+ }
|
|
479
|
+
|
|
480
|
+ static void spiTxBlockX(const uint8_t* buf, uint32_t todo) {
|
|
481
|
+ do {
|
|
482
|
+ (void) spiTransferTx(*buf++);
|
|
483
|
+ } while (--todo);
|
|
484
|
+ }
|
|
485
|
+
|
|
486
|
+ static void spiRxBlockX(uint8_t* buf, uint32_t todo) {
|
|
487
|
+ do {
|
|
488
|
+ *buf++ = spiTransferRx(0xff);
|
|
489
|
+ } while (--todo);
|
|
490
|
+ }
|
|
491
|
+
|
|
492
|
+ // Pointers to generic functions for block tranfers
|
|
493
|
+ static pfnSpiTxBlock spiTxBlock = spiTxBlockX;
|
|
494
|
+ static pfnSpiRxBlock spiRxBlock = spiRxBlockX;
|
|
495
|
+
|
324
|
496
|
void spiBegin() {
|
325
|
497
|
SET_OUTPUT(SS_PIN);
|
326
|
498
|
WRITE(SS_PIN, HIGH);
|
|
@@ -329,6 +501,38 @@
|
329
|
501
|
SET_OUTPUT(MOSI_PIN);
|
330
|
502
|
}
|
331
|
503
|
|
|
504
|
+ uint8_t spiRec() {
|
|
505
|
+ WRITE(SS_PIN, LOW);
|
|
506
|
+ WRITE(MOSI_PIN, 1); /* Output 1s 1*/
|
|
507
|
+ uint8_t b = spiTransferRx(0xFF);
|
|
508
|
+ WRITE(SS_PIN, HIGH);
|
|
509
|
+ return b;
|
|
510
|
+ }
|
|
511
|
+
|
|
512
|
+ void spiRead(uint8_t* buf, uint16_t nbyte) {
|
|
513
|
+ uint32_t todo = nbyte;
|
|
514
|
+ if (todo == 0) return;
|
|
515
|
+
|
|
516
|
+ WRITE(SS_PIN, LOW);
|
|
517
|
+ WRITE(MOSI_PIN, 1); /* Output 1s 1*/
|
|
518
|
+ spiRxBlock(buf,nbyte);
|
|
519
|
+ WRITE(SS_PIN, HIGH);
|
|
520
|
+ }
|
|
521
|
+
|
|
522
|
+ void spiSend(uint8_t b) {
|
|
523
|
+ WRITE(SS_PIN, LOW);
|
|
524
|
+ (void) spiTransferTx(b);
|
|
525
|
+ WRITE(SS_PIN, HIGH);
|
|
526
|
+ }
|
|
527
|
+
|
|
528
|
+ void spiSendBlock(uint8_t token, const uint8_t* buf) {
|
|
529
|
+
|
|
530
|
+ WRITE(SS_PIN, LOW);
|
|
531
|
+ (void) spiTransferTx(token);
|
|
532
|
+ spiTxBlock(buf,512);
|
|
533
|
+ WRITE(SS_PIN, HIGH);
|
|
534
|
+ }
|
|
535
|
+
|
332
|
536
|
/**
|
333
|
537
|
* spiRate should be
|
334
|
538
|
* 0 : 8 - 10 MHz
|
|
@@ -344,15 +548,21 @@
|
344
|
548
|
case 0:
|
345
|
549
|
spiTransferTx = spiTransferTx0;
|
346
|
550
|
spiTransferRx = spiTransferRx0;
|
|
551
|
+ spiTxBlock = spiTxBlock0;
|
|
552
|
+ spiRxBlock = spiRxBlock0;
|
347
|
553
|
break;
|
348
|
554
|
case 1:
|
349
|
555
|
spiTransferTx = spiTransfer1;
|
350
|
556
|
spiTransferRx = spiTransfer1;
|
|
557
|
+ spiTxBlock = spiTxBlockX;
|
|
558
|
+ spiRxBlock = spiRxBlockX;
|
351
|
559
|
break;
|
352
|
560
|
default:
|
353
|
561
|
spiDelayCyclesX4 = (F_CPU/1000000) >> (6 - spiRate);
|
354
|
562
|
spiTransferTx = spiTransferX;
|
355
|
563
|
spiTransferRx = spiTransferX;
|
|
564
|
+ spiTxBlock = spiTxBlockX;
|
|
565
|
+ spiRxBlock = spiRxBlockX;
|
356
|
566
|
break;
|
357
|
567
|
}
|
358
|
568
|
|
|
@@ -361,41 +571,6 @@
|
361
|
571
|
WRITE(SCK_PIN, LOW);
|
362
|
572
|
}
|
363
|
573
|
|
364
|
|
- uint8_t spiRec() {
|
365
|
|
- WRITE(SS_PIN, LOW);
|
366
|
|
- WRITE(MOSI_PIN, 1); /* Output 1s 1*/
|
367
|
|
- uint8_t b = spiTransferRx(0xFF);
|
368
|
|
- WRITE(SS_PIN, HIGH);
|
369
|
|
- return b;
|
370
|
|
- }
|
371
|
|
-
|
372
|
|
- void spiRead(uint8_t* buf, uint16_t nbyte) {
|
373
|
|
- if (nbyte == 0) return;
|
374
|
|
- WRITE(SS_PIN, LOW);
|
375
|
|
- WRITE(MOSI_PIN, 1); /* Output 1s 1*/
|
376
|
|
- for (int i = 0; i < nbyte; i++) {
|
377
|
|
- buf[i] = spiTransferRx(0xff);
|
378
|
|
- }
|
379
|
|
- WRITE(SS_PIN, HIGH);
|
380
|
|
- }
|
381
|
|
-
|
382
|
|
- void spiSend(uint8_t b) {
|
383
|
|
- WRITE(SS_PIN, LOW);
|
384
|
|
- (void) spiTransferTx(b);
|
385
|
|
- WRITE(SS_PIN, HIGH);
|
386
|
|
- }
|
387
|
|
-
|
388
|
|
- void spiSendBlock(uint8_t token, const uint8_t* buf) {
|
389
|
|
-
|
390
|
|
- WRITE(SS_PIN, LOW);
|
391
|
|
- (void) spiTransferTx(token);
|
392
|
|
-
|
393
|
|
- for (uint16_t i = 0; i < 512; i++) {
|
394
|
|
- (void) spiTransferTx(buf[i]);
|
395
|
|
- }
|
396
|
|
- WRITE(SS_PIN, HIGH);
|
397
|
|
- }
|
398
|
|
-
|
399
|
574
|
#pragma GCC reset_options
|
400
|
575
|
|
401
|
576
|
#else
|