SZSPTP ez430-RF2480 1.0

ZigBee Sensor Network with synchronized time and time-stamped measurements.
spi.c
Go to the documentation of this file.
1 /*
2  * spi.c
3  *
4  * Created on: 31/10/2013
5  * Author: Fernando
6  */
7 
16 /*
17  * Reference connections:
18  * MSP430 in master mode
19  *
20  * (MSP430 pin number; pin name; config) <-> BUS name <-> (CC2480 pin number; pin name)
21  *
22  * (MSP430 26 P3.7: GPIO ) -> RESET_N -> (CC2480 10 RESETn)
23  *
24  * (MSP430 15 P4.0: GPIO ) -> CFG0 -> (CC2480 11 CFG0) - 1=32KHz crystal installed; 0=not
25  * (MSP430 16 P4.1: GPIO ) -> CFG1 -> (CC2480 12 CFG1) - 1=SPI; 0=UART
26  *
27  * (MSP430 03 P2.6: GPIO ) <- SRDY <- (CC2480 05 SRDY)
28  * (MSP430 25 P3.6: GPIO ) -> MRDY -> (CC2480 06 MRDY)
29  *
30  * (MSP430 09 P3.0: UCB0STE ) -> SS/CT -> (CC2480 15 SS/CT) - disabled in 3-pin SPI
31  * UCxSTE chooses between master active/inactive
32  *
33  * (MSP430 10 P3.1: UCB0SIMO) -> SI -> (CC2480 14 SI/TX)
34  * (MSP430 11 P3.2: UCB0SOMI) <- SO <- (CC2480 13 SO/RX)
35  * (MSP430 12 P3.3: UCB0CLK ) -> C/RT -> (CC2480 16 C/RT)
36  *
37  * (MSP430 17 P4.2: GPIO ) -> P_4.2 -> (CC2480 45 NC)
38  * (MSP430 18 P4.3: GPIO ) -> P_4.3 -> (CC2480 46 NC)
39  *
40  * From "swra175a.pdf":
41  *
42  * Frame format:
43  * ---------+------------------
44  * Bytes | 1 | 2 | 0-253 |
45  * +--------+---------+-------+
46  * Information | Length | Command | Data |
47  * ---------+------------------
48  *
49  * -------------------+-------
50  * Byte | Cmd0 | Cmd1 |
51  * -------+-----------+------+
52  * Bits | 7-5 | 4-0 | 7-0 |
53  * +------+-----------+------+
54  * Information | Type | Subsystem | ID |
55  * -------+-------------------
56  *
57  * Type
58  * 0: 0x00 POLL. Used to retrieve data, length, subsystem and id are set to 0;
59  * 1: 0x20 SREQ. Synchronous request;
60  * 2: 0x40 AREQ. Asynchronous request;
61  * 3: 0x60 SRSP. Synchronous response;
62  * 4-7: Reserved.
63  *
64  * Subsystem
65  * 0: Reserved
66  * 1: SYS interface
67  * 2: Reserved
68  * 3: Reserved
69  * 4: AF interface
70  * 5: ZDO interface
71  * 6: Simple API interface
72  * 7-32: Reserved
73  *
74  * ID
75  * Command ID, maps to a particular interface message. 0-255
76  *
77  * SS/CT will have the same signal as MRDY as if them were hardwired.
78  *
79  */
80 
81 /*
82  * ======== Standard MSP430 includes ========
83  */
84 #include <msp430.h>
85 
86 /*
87  * ======== Includes ========
88  */
89 #include "spi.h"
90 #include "cc2480ai.h"
91 #include "uart.h"
92 #include "im.h"
93 
94 /*
95  * ======== Constants ========
96  */
97 
98 /*
99  * ======== Macros ========
100  */
101 
105 #define SPI_SRDYBIT BIT6 // On port 2
106 
109 #define SPI_SETSRDYDETECTUP P2IES &= ~SPI_SRDYBIT
110 
113 #define SPI_SETSRDYDETECTDOWN P2IES |= SPI_SRDYBIT
114 
118 #define SPI_SSBIT 0x01 // bit 0 on port 3
119 
122 #define SPI_MRDYBIT BIT6 // On port 3
123 
126 #define SPI_CLRMRDY P3OUT &= ~(SPI_MRDYBIT | SPI_SSBIT)
127 
130 #define SPI_SETMRDY P3OUT |= SPI_MRDYBIT | SPI_SSBIT
131 
135 #define SPI_FRAMEHDRSIZE 3
136 
137 /*
138  * ======== Types ========
139  */
140 
144 typedef enum spi_state {
145  SPI_INIT,
146  SPI_IDLE,
147  SPI_AREQ_START,
148  SPI_AREQ_SENDING,
149  SPI_AREQ_SENT,
150  SPI_SREQ_START,
151  SPI_SREQ_SENDING,
152  SPI_SREQ_SENT,
153  SPI_SREQ_RECEIVING_START,
154  SPI_SREQ_RECEIVING,
155  SPI_SREQ_RECEIVING_OVER,
156  SPI_SREQ_RECEIVED,
157  SPI_POLL_START,
158  SPI_POLL_RECEIVING_START,
159  SPI_POLL_RECEIVING,
160  SPI_POLL_RECEIVING_OVER,
161  SPI_POOL_RECEIVED
162 } spi_state;
163 
164 /*
165  * ======== Global Variables ========
166  */
167 
173 
174 /*
175  * ======== Local Variables ========
176  */
177 
229 
233 char *spi_pBuf;
234 
239 
244 
249 
250 /*
251  * @brief Variable to detect freeze on SPI
252  */
253 UInt8 spi_freezeDetect;
254 
255 /*
256  * ======== Local Functions ========
257  */
258 
259 void spi_snd();
260 void spi_setPollCmd();
261 
262 /*
263  * ================
264  */
265 
274 #if DEBUG==1
276 #endif
278 }
279 
287 void spi_init() {
288  spi_currentState = SPI_INIT;
289  spi_bytesLeft = 0;
292 
293  // reset UCxRXIE, UCxTXIE, UCxRXIFG, UCOE, and UCFE and set UCxTXIFG
294  UCB0CTL1 |= UCSWRST;
295  // SRDY interrupt
296  P2IE &= ~SPI_SRDYBIT;
297  P2OUT |= SPI_SRDYBIT;
298  P2DIR &= ~SPI_SRDYBIT;
299  P2IFG &= ~SPI_SRDYBIT;
300  P2IES |= SPI_SRDYBIT;
301  P2IE |= SPI_SRDYBIT;
302  P3DIR |= SPI_MRDYBIT | SPI_SSBIT;
303 
305  SPI_SETMRDY;
306 
307  // release ICB0 for operation
308  UCB0CTL1 &= ~UCSWRST;
309  IE2 |= UCB0RXIE; // Must be done after releasing UCB0 for operation
310 
311  spi_currentState = SPI_IDLE;
312  spi_freezeDetect = 2;
313 
314 }
315 
325 UInt16 spi_proccess() {
326  // Sometimes the channel just "freezes" on SPI_SREQ_SENT the SRDY line
327  // doesn't go up as it should. There is no way to wake-up the other device, so
328  // it is reset:
329  if (spi_currentState != SPI_IDLE) {
330  spi_freezeDetect--;
331  if (!spi_freezeDetect) {
332  ccai_resetFull();
333  spi_freezeDetect = 10;
334  }
335  }
336  return 200;
337 }
338 
352 UInt8 spi_reqBegin(UInt8 len, UInt8 cmd0, UInt8 cmd1) {
353  // critical section: Disable Global IE
355  if ((spi_currentState != SPI_IDLE)
356  || (len > (SPI_BUFSIZE - SPI_FRAMEHDRSIZE))) {
357  // Enable Global IE before exit
359  return 0;
360  }
362  spi_buf[0] = len;
363  spi_buf[1] = cmd0;
364  spi_buf[2] = cmd1;
365  spi_pBuf = &spi_buf[3]; // prepare to write by spi_reqData below
366  spi_currentFreeBytes = len;
367  return 1;
368 }
369 
382 UInt8 spi_reqData(UInt8 len, void *pBuf) {
383  char *pcBuf;
384  UInt8 result;
385 
386  pcBuf = pBuf;
387  if (len > spi_currentFreeBytes) {
388  result = 0;
389  len = spi_currentFreeBytes;
390  } else
391  result = 1;
392  spi_currentFreeBytes -= len;
393 
394  while (len) {
395  len--;
396  *spi_pBuf++ = *pcBuf++;
397  }
398 
399  return result;
400 }
401 
411 void spi_reqEnd(UInt8 forwardToSerial) {
412  spi_pBuf = spi_buf;
413  spi_bytesLeft = *spi_pBuf + SPI_FRAMEHDRSIZE; // size of payload + size of header
414  // Avoid access violation
415  if (spi_bytesLeft > SPI_BUFSIZE) {
417  }
418  // Get request type
419  if ((spi_buf[1] & 0xE0) == 0x20) { // SREQ
420  spi_currentState = SPI_SREQ_START;
421  } else { // AREQ
422  spi_currentState = SPI_AREQ_START;
423  };
424  // Enable Global IE
426  SPI_CLRMRDY;
427 #if DEBUG==1
429 #else
430  if (forwardToSerial)
432 #endif
433 }
434 
444 UInt8 spi_busy() {
445  return (spi_currentState != SPI_IDLE);
446 }
447 
455 void spi_snd() {
456  if (spi_bytesLeft) {
457  spi_bytesLeft--;
458  switch (spi_currentState) {
459  case SPI_SREQ_RECEIVING:
460  case SPI_SREQ_RECEIVING_OVER:
461  case SPI_POLL_RECEIVING:
462  case SPI_POLL_RECEIVING_OVER:
463  UCB0TXBUF = 0; // If receiving, send only zeroes
464  break;
465  default:
466  UCB0TXBUF = *spi_pBuf;
467  break;
468  }
469  } else {
470  // nothing to send
471  switch (spi_currentState) {
472  case SPI_AREQ_SENDING:
473  spi_currentState = SPI_AREQ_SENT;
474  break;
475  case SPI_SREQ_SENDING:
476  spi_currentState = SPI_SREQ_SENT;
477  break;
478  case SPI_SREQ_RECEIVING_START:
479  spi_currentState = SPI_SREQ_RECEIVING;
480  // got header, read amount of data (payload) to receive
481  spi_bytesLeft = spi_buf[0];
482  // Avoid access violation (header is already on the buffer)
487  }
488  // continue normal receiving, *spi_pBuf is left at next byte to receive
489  spi_snd();
490  break;
491  case SPI_SREQ_RECEIVING:
492  if (spi_receiveOverFlow) {
495  spi_currentState = SPI_SREQ_RECEIVING_OVER;
496  // use send to receive and discard data awaiting on CC2480
497  spi_snd();
498  break;
499  }
500  case SPI_SREQ_RECEIVING_OVER:
501  spi_currentState = SPI_SREQ_RECEIVED;
502  // set MRDY high to terminate communication
503  SPI_SETMRDY;
505  spi_currentState = SPI_IDLE;
506  spi_freezeDetect = 2;
507  break;
508  case SPI_POLL_START:
509  // just wait for SRDY up
510  break;
511  case SPI_POLL_RECEIVING_START:
512  // got header, read amount of data (payload) to receive
513  spi_bytesLeft = spi_buf[0];
514  // Avoid access violation (header is already on the buffer)
519  }
520  // continue normal receiving, *spi_pBuf is left at next byte to receive
521  spi_currentState = SPI_POLL_RECEIVING;
522  spi_snd();
523  break;
524  case SPI_POLL_RECEIVING:
525  if (spi_receiveOverFlow) {
528  spi_currentState = SPI_POLL_RECEIVING_OVER;
529  // use send to receive and discard data awaiting on CC2480
530  spi_snd();
531  break;
532  }
533  case SPI_POLL_RECEIVING_OVER:
534  spi_currentState = SPI_POOL_RECEIVED;
535  // set MRDY high to terminate communication
536  SPI_SETMRDY;
538  spi_currentState = SPI_IDLE;
539  spi_freezeDetect = 2;
540  break;
541  default:
542  break;
543  }
544  }
545 }
546 
555  spi_buf[0] = 0;
556  spi_buf[1] = 0;
557  spi_buf[2] = 0;
558  spi_pBuf = spi_buf; // reset buffer position to send poll command and receive data
559  spi_bytesLeft = SPI_FRAMEHDRSIZE; // bytes to send
560 }
561 
569 void SPI_SRDYISR() {
570  P2IFG &= ~SPI_SRDYBIT; // clear IFG
571  switch (spi_currentState) {
572  case SPI_IDLE:
573  // Poll command
574  spi_currentState = SPI_POLL_START;
576  // Set poll command to initiate communication
577  spi_setPollCmd();
578  SPI_CLRMRDY;
579  spi_snd();
580  break;
581  case SPI_AREQ_START:
582  spi_currentState = SPI_AREQ_SENDING;
584  spi_snd();
585  break;
586  case SPI_AREQ_SENDING: // Normally this would not occur, act as SPI_AREQ_SENT
587  case SPI_AREQ_SENT:
589  SPI_SETMRDY;
590  spi_currentState = SPI_IDLE;
591  spi_freezeDetect = 2;
592  break;
593  case SPI_SREQ_START:
594  spi_currentState = SPI_SREQ_SENDING;
596  spi_snd();
597  break;
598  case SPI_SREQ_SENDING: // Normally this would not occur, act as SPI_SREQ_SENT
599  case SPI_SREQ_SENT:
600  spi_currentState = SPI_SREQ_RECEIVING_START;
602  // send poll command to start receiving data
603  spi_setPollCmd();
604  spi_snd();
605  break;
606  case SPI_POLL_START:
607  spi_currentState = SPI_POLL_RECEIVING_START;
609  // send poll command to start receiving data
610  spi_setPollCmd();
611  spi_snd();
612  break;
613  default:
614  break;
615  }
616 }
617 
626  char v;
627 
628  v = UCB0RXBUF;
629  switch (spi_currentState) {
630  case SPI_AREQ_SENDING:
631  case SPI_SREQ_SENDING:
632  *spi_pBuf++; // just advance pointer
633  break;
634  case SPI_SREQ_RECEIVING_START:
635  case SPI_SREQ_RECEIVING:
636  case SPI_POLL_START:
637  case SPI_POLL_RECEIVING_START:
638  case SPI_POLL_RECEIVING:
639  *spi_pBuf = v; // Read byte to buffer
640  *spi_pBuf++; // advance pointer
641  break;
642  default:
643  // invalid state to receive data, but there is data being received, it is discarded.
644  break;
645  }
646  spi_snd();
647 }
UART interface.
void SPI_SRDYISR()
ISR SRDY.
Definition: spi.c:569
#define SPI_MRDYBIT
MRDY bit mask.
Definition: spi.c:122
UInt8 spi_reqBegin(UInt8 len, UInt8 cmd0, UInt8 cmd1)
Request begin.
Definition: spi.c:352
UInt8 spi_reqData(UInt8 len, void *pBuf)
Request data.
Definition: spi.c:382
Interruption management (enable/disable) interface.
UInt8 spi_currentFreeBytes
Free bytes on current packet.
Definition: spi.c:248
char * spi_pBuf
Pointer to the position being transfered of buffer.
Definition: spi.c:233
UInt8 spi_receiveOverFlow
Data to receive that exceeds SPI_BUFSIZE.
Definition: spi.c:243
#define SPI_SRDYBIT
SRDY bit.
Definition: spi.c:105
#define SPI_CLRMRDY
Clear SS and MRDY bits.
Definition: spi.c:126
void SPI_USCIB0RX_ISR()
USCIB0 RX.
Definition: spi.c:625
void im_disable_interrupt()
Disable interrupt.
Definition: im.c:162
void ccai_resetFull()
Full reset.
Definition: cc2480ai.c:616
#define SPI_SETSRDYDETECTDOWN
Trigger interrupt when SRDY goes down.
Definition: spi.c:113
UInt8 spi_busy()
SPI busy.
Definition: spi.c:444
SPI interface.
#define SPI_SETMRDY
Set SS and MRDY bits.
Definition: spi.c:130
void im_enable_interrupt()
Enable interrupt.
Definition: im.c:222
spi_state
States for SPI.
Definition: spi.c:144
UInt8 uart_forwardCmd(char *pBuf)
Forward command.
Definition: uart.c:741
spi_state spi_currentState
Current state of SPI.
Definition: spi.c:228
UInt16 spi_bytesLeft
Amount of data queued to TX/RX.
Definition: spi.c:238
#define SPI_SSBIT
SS bit mask.
Definition: spi.c:118
char spi_buf[SPI_BUFSIZE]
SPI buffer, used to send and receive data.
Definition: spi.c:172
UInt16 spi_proccess()
SPI proccess.
Definition: spi.c:325
void spi_setPollCmd()
Set poll command.
Definition: spi.c:554
void ccai_process_message()
Proccess a received message.
Definition: cc2480ai.c:639
#define SPI_BUFSIZE
Size of the SPI buffer.
Definition: spi.h:47
CC2480 interface.
void spi_reqEnd(UInt8 forwardToSerial)
Request end.
Definition: spi.c:411
void spi_snd()
SPI send.
Definition: spi.c:455
#define SPI_SETSRDYDETECTUP
Trigger interrupt when SRDY goes up.
Definition: spi.c:109
void spi_init()
SPI initialization.
Definition: spi.c:287
void spi_process_message()
Process SPI message.
Definition: spi.c:273
#define SPI_FRAMEHDRSIZE
Size of Header of a frame: Length, cmd0 and cmd1.
Definition: spi.c:135