Line No. | Rev | Author | Line |
---|---|---|---|
1 | 32 | kaklik | /****************************************************************************** |
2 | |||
3 | MRF24WB0M Driver SPI interface routines |
||
4 | Module for Microchip TCP/IP Stack |
||
5 | |||
6 | ******************************************************************************* |
||
7 | FileName: WF_Spi.c |
||
8 | Dependencies: TCP/IP Stack header files |
||
9 | Processor: PIC18, PIC24F, PIC24H, dsPIC30F, dsPIC33F, PIC32 |
||
10 | Compiler: Microchip C32 v1.10b or higher |
||
11 | Microchip C30 v3.22 or higher |
||
12 | Microchip C18 v3.34 or higher |
||
13 | Company: Microchip Technology, Inc. |
||
14 | |||
15 | Software License Agreement |
||
16 | |||
17 | Copyright (C) 2002-2010 Microchip Technology Inc. All rights reserved. |
||
18 | |||
19 | Microchip licenses to you the right to use, modify, copy, and distribute: |
||
20 | (i) the Software when embedded on a Microchip microcontroller or digital |
||
21 | signal controller product ("Device") which is integrated into |
||
22 | Licensee's product; or |
||
23 | (ii) ONLY the Software driver source files ENC28J60.c, ENC28J60.h, |
||
24 | ENCX24J600.c and ENCX24J600.h ported to a non-Microchip device used in |
||
25 | conjunction with a Microchip ethernet controller for the sole purpose |
||
26 | of interfacing with the ethernet controller. |
||
27 | |||
28 | You should refer to the license agreement accompanying this Software for |
||
29 | additional information regarding your rights and obligations. |
||
30 | |||
31 | THE SOFTWARE AND DOCUMENTATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY |
||
32 | KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION, ANY WARRANTY |
||
33 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND |
||
34 | NON-INFRINGEMENT. IN NO EVENT SHALL MICROCHIP BE LIABLE FOR ANY INCIDENTAL, |
||
35 | SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES, LOST PROFITS OR LOST DATA, COST |
||
36 | OF PROCUREMENT OF SUBSTITUTE GOODS, TECHNOLOGY OR SERVICES, ANY CLAIMS BY |
||
37 | THIRD PARTIES (INCLUDING BUT NOT LIMITED TO ANY DEFENSE THEREOF), ANY CLAIMS |
||
38 | FOR INDEMNITY OR CONTRIBUTION, OR OTHER SIMILAR COSTS, WHETHER ASSERTED ON |
||
39 | THE BASIS OF CONTRACT, TORT (INCLUDING NEGLIGENCE), BREACH OF WARRANTY, OR |
||
40 | OTHERWISE. |
||
41 | |||
42 | |||
43 | Author Date Comment |
||
44 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||
45 | Zero G Sep 2008 Initial version |
||
46 | KO 31 Oct 2008 Port to PIC24F and PIC32 for TCP/IP stack v4.52 |
||
47 | ******************************************************************************/ |
||
48 | |||
49 | /* |
||
50 | ********************************************************************************************************* |
||
51 | * INCLUDES |
||
52 | ********************************************************************************************************* |
||
53 | */ |
||
54 | |||
55 | #include "TCPIP Stack/WFMac.h" |
||
56 | |||
57 | #if defined(WF_CS_TRIS) |
||
58 | |||
59 | /* |
||
60 | ********************************************************************************************************* |
||
61 | * DEFINES |
||
62 | ********************************************************************************************************* |
||
63 | */ |
||
64 | |||
65 | /* used for assertions */ |
||
66 | #ifdef WF_DEBUG |
||
67 | #define WF_MODULE_NUMBER WF_MODULE_WF_SPI |
||
68 | #endif |
||
69 | |||
70 | /* Indicate here if the MRF24WB0M is sharing the SPI bus with another device. For the */ |
||
71 | /* Microchip demos only the PIC18 on the PICDEM.net 2 board shares the SPI bus. */ |
||
72 | #if defined(__18CXX) |
||
73 | #define SPI_IS_SHARED |
||
74 | #endif |
||
75 | |||
76 | #if defined (SPI_IS_SHARED) |
||
77 | /* SPI context save variables */ |
||
78 | static BYTE SPIONSave; |
||
79 | #if defined( __18CXX) |
||
80 | static BYTE SPICON1Save; |
||
81 | static BYTE SPISTATSave; |
||
82 | #elif defined( __C30__ ) |
||
83 | static WORD SPICON1Save; |
||
84 | static WORD SPICON2Save; |
||
85 | static WORD SPISTATSave; |
||
86 | #elif defined( __PIC32MX__ ) |
||
87 | static DWORD SPICON1Save; |
||
88 | static DWORD SPISTATSave; |
||
89 | #else |
||
90 | #error Cannot define SPI context save variables. |
||
91 | #endif |
||
92 | #endif /* SPI_IS_SHARED */ |
||
93 | |||
94 | //============================================================================ |
||
95 | // SPI Definitions |
||
96 | //============================================================================ |
||
97 | |||
98 | #if defined (__18CXX) |
||
99 | #define ClearSPIDoneFlag() {WF_SPI_IF = 0;} |
||
100 | #define WaitForDataByte() {while(!WF_SPI_IF); WF_SPI_IF = 0;} |
||
101 | #define SPI_ON_BIT (WF_SPICON1bits.SSPEN) |
||
102 | #elif defined(__C30__) |
||
103 | #define ClearSPIDoneFlag() |
||
104 | static inline __attribute__((__always_inline__)) void WaitForDataByte( void ) |
||
105 | { |
||
106 | while ((WF_SPISTATbits.SPITBF == 1) || (WF_SPISTATbits.SPIRBF == 0)); |
||
107 | } |
||
108 | |||
109 | #define SPI_ON_BIT (WF_SPISTATbits.SPIEN) |
||
110 | #elif defined( __PIC32MX__ ) |
||
111 | #define ClearSPIDoneFlag() |
||
112 | static inline __attribute__((__always_inline__)) void WaitForDataByte( void ) |
||
113 | { |
||
114 | while (!WF_SPISTATbits.SPITBE || !WF_SPISTATbits.SPIRBF); |
||
115 | } |
||
116 | |||
117 | #define SPI_ON_BIT (WF_SPICON1bits.ON) |
||
118 | #else |
||
119 | #error Determine SPI flag mechanism |
||
120 | #endif |
||
121 | |||
122 | /* |
||
123 | ********************************************************************************************************* |
||
124 | * LOCAL FUNCTION PROTOTYPES |
||
125 | ********************************************************************************************************* |
||
126 | */ |
||
127 | |||
128 | #if defined (SPI_IS_SHARED) |
||
129 | static void SaveSpiContext(void); |
||
130 | static void RestoreSpiContext(void); |
||
131 | #endif |
||
132 | static void ConfigureSpiMRF24WB0M(void); |
||
133 | |||
134 | |||
135 | /***************************************************************************** |
||
136 | Function: |
||
137 | void WF_SpiInit(void) |
||
138 | |||
139 | Summary: |
||
140 | Initializes the SPI interface to the MRF24WB0M device. |
||
141 | |||
142 | Description: |
||
143 | Configures the SPI interface for communications with the MRF24WB0M. |
||
144 | |||
145 | Precondition: |
||
146 | None |
||
147 | |||
148 | Parameters: |
||
149 | None |
||
150 | |||
151 | Returns: |
||
152 | None |
||
153 | |||
154 | Remarks: |
||
155 | This function is called by WFHardwareInit. |
||
156 | *****************************************************************************/ |
||
157 | void WF_SpiInit(void) |
||
158 | { |
||
159 | /* disable the spi interrupt */ |
||
160 | #if defined( __PIC32MX__ ) |
||
161 | WF_SPI_IE_CLEAR = WF_SPI_INT_BITS; |
||
162 | #else |
||
163 | WF_SPI_IE = 0; |
||
164 | #endif |
||
165 | #if defined( __18CXX) |
||
166 | WF_SPI_IP = 0; |
||
167 | #endif |
||
168 | |||
169 | // Set up the SPI module on the PIC for communications with the MRF24WB0M |
||
170 | WF_CS_IO = 1; |
||
171 | WF_CS_TRIS = 0; // Drive SPI MRF24WB0M chip select pin |
||
172 | #if defined( __18CXX) |
||
173 | WF_SCK_TRIS = 0; /* SPI Clock is an output */ |
||
174 | WF_SDO_TRIS = 0; /* SPI Data Out is an output */ |
||
175 | WF_SDI_TRIS = 1; /* SPI Data In is an input */ |
||
176 | #else |
||
177 | // We'll let the module control the pins. |
||
178 | #endif |
||
179 | |||
180 | #if !defined( SPI_IS_SHARED ) |
||
181 | ConfigureSpiMRF24WB0M(); |
||
182 | #endif |
||
183 | |||
184 | /* clear the completion flag */ |
||
185 | ClearSPIDoneFlag(); |
||
186 | } |
||
187 | |||
188 | |||
189 | /* |
||
190 | Fsck = Fpb |
||
191 | ------------------ |
||
192 | 2 * (SPIxBRG + 1) |
||
193 | |||
194 | Note that the maximum possible baud rate is |
||
195 | Fpb/2 (SPIXBRG = 0) and the minimum possible baud |
||
196 | rate is FPB /1024. |
||
197 | */ |
||
198 | |||
199 | |||
200 | /***************************************************************************** |
||
201 | Function: |
||
202 | void ConfigureSpiMRF24WB0M(void) |
||
203 | |||
204 | Summary: |
||
205 | Configures the SPI interface to the MRF24WB0M. |
||
206 | |||
207 | Description: |
||
208 | Configures the SPI interface for communications with the MRF24WB0M. |
||
209 | |||
210 | Precondition: |
||
211 | None |
||
212 | |||
213 | Parameters: |
||
214 | None |
||
215 | |||
216 | Returns: |
||
217 | None |
||
218 | |||
219 | Remarks: |
||
220 | If the SPI bus is shared with other peripherals this function is called |
||
221 | each time an SPI transaction occurs by WF_SpiEnableChipSelect. Otherwise it |
||
222 | is called once during initialization by WF_SpiInit. |
||
223 | *****************************************************************************/ |
||
224 | static void ConfigureSpiMRF24WB0M(void) |
||
225 | { |
||
226 | /*----------------------------------------------------------------*/ |
||
227 | /* After we save context, configure SPI for MRF24WB0M communications */ |
||
228 | /*----------------------------------------------------------------*/ |
||
229 | /* enable the SPI clocks */ |
||
230 | /* set as master */ |
||
231 | /* clock idles high */ |
||
232 | /* ms bit first */ |
||
233 | /* 8 bit tranfer length */ |
||
234 | /* data changes on falling edge */ |
||
235 | /* data is sampled on rising edge */ |
||
236 | /* set the clock divider */ |
||
237 | #if defined(__18CXX) |
||
238 | WF_SPICON1 = 0x30; // SSPEN bit is set, SPI in master mode, (0x30 is for FOSC/4), |
||
239 | // IDLE state is high level (0x32 is for FOSC/64) |
||
240 | WF_SPISTATbits.CKE = 0; // Transmit data on falling edge of clock |
||
241 | WF_SPISTATbits.SMP = 1; // Input sampled at end? of data output time |
||
242 | #elif defined(__C30__) |
||
243 | WF_SPICON1 = 0x027B; // Fcy Primary prescaler 1:1, secondary prescaler 2:1, CKP=1, CKE=0, SMP=1 |
||
244 | WF_SPICON2 = 0x0000; |
||
245 | WF_SPISTAT = 0x8000; // Enable the module |
||
246 | #elif defined( __PIC32MX__ ) |
||
247 | WF_SPI_BRG = (GetPeripheralClock()-1ul)/2ul/WF_MAX_SPI_FREQ; |
||
248 | WF_SPICON1 = 0x00000260; // sample at end, data change idle to active, clock idle high, master |
||
249 | WF_SPICON1bits.ON = 1; |
||
250 | #else |
||
251 | #error Configure SPI for the selected processor |
||
252 | #endif |
||
253 | } |
||
254 | |||
255 | /***************************************************************************** |
||
256 | Function: |
||
257 | void WF_SpiEnableChipSelect(void) |
||
258 | |||
259 | Summary: |
||
260 | Enables the MRF24WB0M SPI chip select. |
||
261 | |||
262 | Description: |
||
263 | Enables the MRF24WB0M SPI chip select as part of the sequence of SPI |
||
264 | communications. |
||
265 | |||
266 | Precondition: |
||
267 | None |
||
268 | |||
269 | Parameters: |
||
270 | None |
||
271 | |||
272 | Returns: |
||
273 | None |
||
274 | |||
275 | Remarks: |
||
276 | If the SPI bus is shared with other peripherals then the current SPI context |
||
277 | is saved. |
||
278 | *****************************************************************************/ |
||
279 | void WF_SpiEnableChipSelect(void) |
||
280 | { |
||
281 | #if defined(__18CXX) |
||
282 | static volatile UINT8 dummy; |
||
283 | #endif |
||
284 | |||
285 | #if defined(SPI_IS_SHARED) |
||
286 | SaveSpiContext(); |
||
287 | ConfigureSpiMRF24WB0M(); |
||
288 | #endif |
||
289 | |||
290 | /* set Slave Select low (enable SPI chip select on MRF24WB0M) */ |
||
291 | WF_CS_IO = 0; |
||
292 | |||
293 | /* clear any pending interrupts */ |
||
294 | #if defined(__18CXX) |
||
295 | dummy = WF_SSPBUF; |
||
296 | ClearSPIDoneFlag(); |
||
297 | #endif |
||
298 | |||
299 | |||
300 | } |
||
301 | |||
302 | /***************************************************************************** |
||
303 | Function: |
||
304 | void WF_SpiDisableChipSelect(void) |
||
305 | |||
306 | Summary: |
||
307 | Disables the MRF24WB0M SPI chip select. |
||
308 | |||
309 | Description: |
||
310 | Disables the MRF24WB0M SPI chip select as part of the sequence of SPI |
||
311 | communications. |
||
312 | |||
313 | Precondition: |
||
314 | None |
||
315 | |||
316 | Parameters: |
||
317 | None |
||
318 | |||
319 | Returns: |
||
320 | None |
||
321 | |||
322 | Remarks: |
||
323 | If the SPI bus is shared with other peripherals then the current SPI context |
||
324 | is restored. |
||
325 | *****************************************************************************/ |
||
326 | void WF_SpiDisableChipSelect(void) |
||
327 | { |
||
328 | /* Disable the interrupt */ |
||
329 | #if defined( __PIC32MX__ ) |
||
330 | WF_SPI_IE_CLEAR = WF_SPI_INT_BITS; |
||
331 | #else |
||
332 | WF_SPI_IE = 0; |
||
333 | #endif |
||
334 | |||
335 | /* set Slave Select high ((disable SPI chip select on MRF24WB0M) */ |
||
336 | WF_CS_IO = 1; |
||
337 | |||
338 | #if defined(SPI_IS_SHARED) |
||
339 | RestoreSpiContext(); |
||
340 | #endif |
||
341 | } |
||
342 | |||
343 | /***************************************************************************** |
||
344 | Function: |
||
345 | void WFSpiTxRx(void) |
||
346 | |||
347 | Summary: |
||
348 | Transmits and receives SPI bytes |
||
349 | |||
350 | Description: |
||
351 | Transmits and receives N bytes of SPI data. |
||
352 | |||
353 | Precondition: |
||
354 | None |
||
355 | |||
356 | Parameters: |
||
357 | p_txBuf - pointer to SPI tx data |
||
358 | txLen - number of bytes to Tx |
||
359 | p_rxBuf - pointer to where SPI rx data will be stored |
||
360 | rxLen - number of SPI rx bytes caller wants copied to p_rxBuf |
||
361 | |||
362 | Returns: |
||
363 | None |
||
364 | |||
365 | Remarks: |
||
366 | Will clock out the larger of txLen or rxLen, and pad if necessary. |
||
367 | *****************************************************************************/ |
||
368 | void WFSpiTxRx(UINT8 *p_txBuf, |
||
369 | UINT16 txLen, |
||
370 | UINT8 *p_rxBuf, |
||
371 | UINT16 rxLen) |
||
372 | { |
||
373 | #if defined(__18CXX) |
||
374 | static UINT16 byteCount; /* avoid local variables in functions called from interrupt routine */ |
||
375 | static UINT16 i; |
||
376 | static UINT8 rxTrash; |
||
377 | #else |
||
378 | UINT16 byteCount; |
||
379 | UINT16 i; |
||
380 | UINT8 rxTrash; |
||
381 | #endif |
||
382 | |||
383 | |||
384 | #ifdef WF_DEBUG |
||
385 | /* Cannot communicate with MRF24WB0M when it is in hibernate mode */ |
||
386 | { |
||
387 | static UINT8 state; /* avoid local vars in functions called from interrupt */ |
||
388 | WF_GetPowerSaveState(&state); |
||
389 | WF_ASSERT(state != WF_PS_HIBERNATE); |
||
390 | } |
||
391 | #endif |
||
392 | |||
393 | /* total number of byte to clock is whichever is larger, txLen or rxLen */ |
||
394 | byteCount = (txLen >= rxLen)?txLen:rxLen; |
||
395 | |||
396 | for (i = 0; i < byteCount; ++i) |
||
397 | { |
||
398 | /* if still have bytes to transmit from tx buffer */ |
||
399 | if (txLen > 0) |
||
400 | { |
||
401 | WF_SSPBUF = *p_txBuf++; |
||
402 | --txLen; |
||
403 | } |
||
404 | /* else done writing bytes out from tx buffer */ |
||
405 | else |
||
406 | { |
||
407 | WF_SSPBUF = 0xff; /* clock out a "don't care" byte */ |
||
408 | } |
||
409 | |||
410 | /* wait until tx/rx byte to completely clock out */ |
||
411 | WaitForDataByte(); |
||
412 | |||
413 | /* if still have bytes to read into rx buffer */ |
||
414 | if (rxLen > 0) |
||
415 | { |
||
416 | *p_rxBuf++ = WF_SSPBUF; |
||
417 | --rxLen; |
||
418 | } |
||
419 | /* else done reading bytes into rx buffer */ |
||
420 | else |
||
421 | { |
||
422 | rxTrash = WF_SSPBUF; /* read and throw away byte */ |
||
423 | } |
||
424 | } /* end for loop */ |
||
425 | |||
426 | } |
||
427 | |||
428 | #if defined(__18CXX) |
||
429 | /***************************************************************************** |
||
430 | Function: |
||
431 | void WFSpiTxRx_Rom(void) |
||
432 | |||
433 | Summary: |
||
434 | Transmits and receives SPI bytes |
||
435 | |||
436 | Description: |
||
437 | Specific to the PIC18, transmits bytes from ROM storage and receives SPI data |
||
438 | bytes. |
||
439 | |||
440 | Precondition: |
||
441 | None |
||
442 | |||
443 | Parameters: |
||
444 | p_txBuf - pointer to SPI ROM tx data |
||
445 | txLen - number of bytes to Tx |
||
446 | p_rxBuf - pointer to where SPI rx data will be stored |
||
447 | rxLen - number of SPI rx bytes caller wants copied to p_rxBuf |
||
448 | |||
449 | Returns: |
||
450 | None |
||
451 | |||
452 | Remarks: |
||
453 | Will clock out the larger of txLen or rxLen, and pad if necessary. |
||
454 | *****************************************************************************/ |
||
455 | void WFSpiTxRx_Rom(ROM UINT8 *p_txBuf, |
||
456 | UINT16 txLen, |
||
457 | UINT8 *p_rxBuf, |
||
458 | UINT16 rxLen) |
||
459 | { |
||
460 | static UINT16 byteCount; /* avoid local variables in functions called from interrupt routine */ |
||
461 | static UINT16 i; |
||
462 | static UINT8 rxTrash; |
||
463 | |||
464 | /* total number of byte to clock is whichever is larger, txLen or rxLen */ |
||
465 | byteCount = (txLen >= rxLen)?txLen:rxLen; |
||
466 | |||
467 | for (i = 0; i < byteCount; ++i) |
||
468 | { |
||
469 | /* if still have bytes to transmit from tx buffer */ |
||
470 | if (txLen > 0) |
||
471 | { |
||
472 | WF_SSPBUF = *p_txBuf++; |
||
473 | --txLen; |
||
474 | } |
||
475 | /* else done writing bytes out from tx buffer */ |
||
476 | else |
||
477 | { |
||
478 | WF_SSPBUF = 0xff; /* clock out a "don't care" byte */ |
||
479 | } |
||
480 | |||
481 | // wait until tx/rx byte completely clocked out |
||
482 | WaitForDataByte(); |
||
483 | |||
484 | /* if still have bytes to read into rx buffer */ |
||
485 | if (rxLen > 0) |
||
486 | { |
||
487 | *p_rxBuf++ = WF_SSPBUF; |
||
488 | --rxLen; |
||
489 | } |
||
490 | /* else done reading bytes into rx buffer */ |
||
491 | else |
||
492 | { |
||
493 | rxTrash = WF_SSPBUF; /* read and throw away byte */ |
||
494 | } |
||
495 | } /* end for loop */ |
||
496 | } |
||
497 | #endif |
||
498 | |||
499 | #if defined (SPI_IS_SHARED) |
||
500 | /***************************************************************************** |
||
501 | Function: |
||
502 | void SaveSpiContext(void) |
||
503 | |||
504 | Summary: |
||
505 | Saves SPI context. |
||
506 | |||
507 | Description: |
||
508 | Saves the SPI context (mainly speed setting) before using the SPI to |
||
509 | access MRF24WB0M. Turn off the SPI module before reconfiguring it. |
||
510 | We only need this function if SPI lines are shared. |
||
511 | |||
512 | Precondition: |
||
513 | None |
||
514 | |||
515 | Parameters: |
||
516 | None |
||
517 | |||
518 | Returns: |
||
519 | None |
||
520 | |||
521 | Remarks: |
||
522 | Only called if SPI_IS_SHARED is defined |
||
523 | *****************************************************************************/ |
||
524 | static void SaveSpiContext(void) |
||
525 | { |
||
526 | // Save SPI state (clock speed) |
||
527 | SPICON1Save = WF_SPICON1; |
||
528 | #if defined( __C30__ ) |
||
529 | SPICON2Save = WF_SPICON2; |
||
530 | #endif |
||
531 | SPISTATSave = WF_SPISTAT; |
||
532 | SPIONSave = SPI_ON_BIT; |
||
533 | SPI_ON_BIT = 0; |
||
534 | } |
||
535 | |||
536 | /***************************************************************************** |
||
537 | Function: |
||
538 | void RestoreSpiContext(void) |
||
539 | |||
540 | Summary: |
||
541 | Restores SPI context. |
||
542 | |||
543 | Description: |
||
544 | Restores the SPI context (mainly speed setting) after using the SPI to |
||
545 | access MRF24WB0M. Turn off the SPI module before reconfiguring it. |
||
546 | We only need this function if SPI lines are shared. |
||
547 | |||
548 | Precondition: |
||
549 | None |
||
550 | |||
551 | Parameters: |
||
552 | None |
||
553 | |||
554 | Returns: |
||
555 | None |
||
556 | |||
557 | Remarks: |
||
558 | Only called if SPI_IS_SHARED is defined |
||
559 | *****************************************************************************/ |
||
560 | static void RestoreSpiContext(void) |
||
561 | { |
||
562 | SPI_ON_BIT = 0; |
||
563 | WF_SPICON1 = SPICON1Save; |
||
564 | #if defined( __C30__ ) |
||
565 | WF_SPICON2 = SPICON2Save; |
||
566 | #endif |
||
567 | WF_SPISTAT = SPISTATSave; |
||
568 | SPI_ON_BIT = SPIONSave; |
||
569 | } |
||
570 | #endif /* SPI_IS_SHARED */ |
||
571 | |||
572 | |||
573 | |||
574 | #else |
||
575 | // dummy func to keep compiler happy when module has no executeable code |
||
576 | void MCHP_Spi_EmptyFunc(void) |
||
577 | { |
||
578 | } |
||
579 | #endif /* WF_CS_TRIS */ |
||
580 |
Powered by WebSVN v2.8.3