Contiki 3.x
maca.c
1 /*
2  * Copyright (c) 2010, Mariano Alvira <mar@devl.org> and other contributors
3  * to the MC1322x project (http://mc1322x.devl.org)
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  * notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  * notice, this list of conditions and the following disclaimer in the
13  * documentation and/or other materials provided with the distribution.
14  * 3. Neither the name of the Institute nor the names of its contributors
15  * may be used to endorse or promote products derived from this software
16  * without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
19  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21  * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
22  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28  * SUCH DAMAGE.
29  *
30  * This file is part of libmc1322x: see http://mc1322x.devl.org
31  * for details.
32  *
33  *
34  */
35 
36 #include <mc1322x.h>
37 #include <stdio.h>
38 
39 #ifndef DEBUG_MACA
40 #define DEBUG_MACA 0
41 #endif
42 #if (DEBUG_MACA == 0)
43 #define PRINTF(...)
44 #else
45 #define PRINTF(...) printf(__VA_ARGS__)
46 #endif
47 
48 #ifndef MACA_BOUND_CHECK
49 #define MACA_BOUND_CHECK 0
50 #endif
51 #if (MACA_BOUND_CHECK == 0)
52 #define BOUND_CHECK(x)
53 #else
54 #define BOUND_CHECK(x) bound_check(x)
55 #endif
56 
57 #ifndef NUM_PACKETS
58 #define NUM_PACKETS 32
59 #endif
60 
61 /* for 250kHz clock */
62 #define MACA_CLOCK_DIV 95
63 /* (32 chips/sym) * (sym/4bits) * (8bits/byte) = (64 chips/byte) */
64 /* (8 chips/clk) * (byte/64 chips) = byte/8clks */
65 #define CLK_PER_BYTE 8
66 
67 #ifndef RECV_SOFTIMEOUT
68 #define RECV_SOFTIMEOUT (1024*128*CLK_PER_BYTE)
69 #endif
70 
71 #ifndef CPL_TIMEOUT
72 #define CPL_TIMEOUT (2*128*CLK_PER_BYTE)
73 #endif
74 
75 #ifndef MACA_INSERT_ACK
76 #define MACA_INSERT_ACK 1
77 #endif
78 
79 /* Bit in first byte of 802.15.4 message that indicates an */
80 /* acknowledgereply frame is expected */
81 #define MAC_ACK_REQUEST_FLAG 0x20
82 
83 #define reg(x) (*(volatile uint32_t *)(x))
84 
85 int count_packets(void);
86 void Print_Packets(char *s);
87 
88 static volatile packet_t packet_pool[NUM_PACKETS];
89 static volatile packet_t *free_head, *rx_end, *tx_end, *dma_tx, *dma_rx;
90 
91 /* rx_head and tx_head are visible to the outside */
92 /* so you can peek at it and see if there is data */
93 /* waiting for you, or data still to be sent */
94 volatile packet_t *rx_head, *tx_head;
95 
96 /* used for ack recpetion if the packet_pool goes empty */
97 /* doesn't go back into the pool when freed */
98 static volatile packet_t dummy_ack;
99 static volatile packet_t dummy_rx;
100 
101 /* incremented on every maca entry */
102 /* you can use this to detect that the receive loop is still running */
103 volatile uint32_t maca_entry = 0;
104 
105 enum posts {
106  NO_POST = 0,
107  TX_POST,
108  RX_POST,
109  MAX_POST,
110 };
111 static volatile uint8_t last_post = NO_POST;
112 
113 /* maca_pwr indicates whether the radio is on or off */
114 /* Test it before accessing any radio function or the CPU may hang */
115 volatile uint8_t maca_pwr = 0;
116 
117 volatile uint8_t fcs_mode = USE_FCS;
118 volatile uint8_t prm_mode = PROMISC;
119 
120 /* call periodically to */
121 /* check that maca_entry is changing */
122 /* if it is not, it will do a manual call to maca_isr which should */
123 /* get the ball rolling again */
124 /* also checks that the clock is running --- if it isn't then */
125 /* it calls redoes the maca intialization but _DOES NOT_ free all packets */
126 
127 void check_maca(void) {
128  safe_irq_disable(MACA);
129  static volatile uint32_t last_time;
130  static volatile uint32_t last_entry;
131  volatile uint32_t i;
132 #if DEBUG_MACA
133  volatile uint32_t count;
134 #endif
135 
136 
137  /* if *MACA_CLK == last_time */
138  /* try waiting for one clock period */
139  /* since maybe check_maca is getting called quickly */
140  for(i=0; (i < 1024) && (*MACA_CLK == last_time); i++) { continue; }
141 
142  if(*MACA_CLK == last_time) {
143  PRINTF("check maca: maca_clk stopped, restarting\n");
144  /* clock isn't running */
145  ResumeMACASync();
146  *INTFRC = (1<<INT_NUM_MACA);
147  } else {
148  if((last_time > (*MACA_SFTCLK + RECV_SOFTIMEOUT)) &&
149  (last_time > (*MACA_CPLCLK + CPL_TIMEOUT))) {
150  PRINTF("check maca: complete clocks expired\n");
151  /* all complete clocks have expired */
152  /* check that maca entry is changing */
153  /* if not, do call the isr to restart the cycle */
154  if(last_entry == maca_entry) {
155  PRINTF("check maca: forcing isr\n");
156  *INTFRC = (1<<INT_NUM_MACA);
157  }
158  }
159  }
160 
161  last_entry = maca_entry;
162  last_time = *MACA_CLK;
163 
164 #if DEBUG_MACA
165  if((count = count_packets()) != NUM_PACKETS) {
166  PRINTF("check maca: count_packets %d\n", (int)count);
167  Print_Packets("check_maca");
168 #if PACKET_STATS
169  for(i=0; i<NUM_PACKETS; i++) {
170  printf("packet 0x%lx seen %d post_tx %d get_free %d rxd %d\n",
171  (uint32_t) &packet_pool[i],
172  packet_pool[i].seen,
173  packet_pool[i].post_tx,
174  packet_pool[i].get_free,
175  packet_pool[i].rxd);
176  }
177 #endif
178  if(bit_is_set(*NIPEND, INT_NUM_MACA)) { *INTFRC = (1 << INT_NUM_MACA); }
179  }
180 #endif /* DEBUG_MACA */
181  irq_restore();
182 }
183 
184 void maca_init(void) {
185  reset_maca();
186  radio_init();
187  flyback_init();
188  init_phy();
189  maca_pwr = 1;
190  set_channel(0); /* things get weird if you never set a channel */
191  set_power(0); /* set the power too --- who knows what happens if you don't */
192  free_head = 0; tx_head = 0; rx_head = 0; rx_end = 0; tx_end = 0; dma_tx = 0; dma_rx = 0;
193  free_all_packets();
194 
195  #if DEBUG_MACA
196  Print_Packets("maca_init");
197  #endif
198 
199  /* initial radio command */
200  /* nop, promiscuous, no cca */
201  *MACA_CONTROL =
202  (prm_mode << PRM) |
203  (NO_CCA << MACA_MODE);
204 
205  enable_irq(MACA);
206  *INTFRC = (1 << INT_NUM_MACA);
207 }
208 
209 #define print_packets(x) Print_Packets(x)
210 void Print_Packets(char *s) {
211  volatile packet_t *p;
212 
213  printf("packet pool after %s:\n\r",s);
214  p = free_head;
215  printf("free_head: 0x%lx ", (uint32_t) free_head);
216  while(p != 0) {
217  p = p->left;
218  printf("->0x%lx", (uint32_t) p);
219  }
220  printf("\n\r");
221 
222  p = tx_head;
223  printf("tx_head: 0x%lx ", (uint32_t) tx_head);
224  while(p != 0) {
225  p = p->left;
226  printf("->0x%lx", (uint32_t) p);
227  }
228  printf("\n\r");
229 
230  p = rx_head;
231  printf("rx_head: 0x%lx ", (uint32_t) rx_head);
232  while(p != 0) {
233  p = p->left;
234  printf("->0x%lx", (uint32_t) p);
235  }
236  printf("\n\r");
237 
238  printf("dma_rx: 0x%lx\n", (uint32_t) dma_rx);
239  printf("dma_tx: 0x%lx\n", (uint32_t) dma_tx);
240 
241 }
242 
243 inline void bad_packet_bounds(void) {
244  PRINTF("bad packet bounds! Halting.\n");
245  while(1) { continue; }
246 }
247 
248 int count_packets(void) {
249  volatile int8_t total = -1;
250 
251 #if PACKET_STATS
252  volatile packet_t *pk;
253  volatile uint8_t tx, rx, free;
254  volatile int i;
255 
256  for(i = 0; i < NUM_PACKETS; i++) {
257  packet_pool[i].seen = 0;
258  }
259 
260  pk = tx_head; tx = 0;
261  while( pk != 0 ) {
262  if(pk->seen == 0) { tx++; }
263  pk->seen++;
264  pk = pk->left;
265  }
266  pk = rx_head; rx = 0;
267  while( pk != 0 ) {
268  if(pk->seen == 0) { rx++; }
269  pk->seen++;
270  pk = pk->left;
271  }
272  pk = free_head; free = 0;
273  while( pk != 0 ) {
274  if(pk->seen == 0) { free++; }
275  pk->seen++;
276  pk = pk->left;
277  }
278 
279  total = free + rx + tx;
280  if(dma_rx && (dma_rx->seen == 0)) { dma_rx->seen++; total++; }
281  if(dma_tx && (dma_tx->seen == 0)) { dma_tx->seen++; total++; }
282 #endif /* PACKET_STATS */
283 
284  return total;
285 }
286 
287 void bound_check(volatile packet_t *p) {
288  volatile int i;
289 
290  if((p == 0) ||
291  (p == &dummy_ack)) { return; }
292  for(i=0; i < NUM_PACKETS; i++) {
293  if(p == &packet_pool[i]) { return; }
294  }
295 
296  bad_packet_bounds();
297 }
298 
299 
300 /* public packet routines */
301 /* heads are to the right */
302 /* ends are to the left */
303 void maca_free_packet(volatile packet_t *p) {
304  safe_irq_disable(MACA);
305 
306  BOUND_CHECK(p);
307 
308  if(!p) { PRINTF("free_packet passed packet 0\n\r"); return; }
309  if(p == &dummy_ack) { return; }
310 
311  BOUND_CHECK(free_head);
312 
313  p->length = 0; p->offset = 0;
314  p->left = free_head; p->right = 0;
315 #if PACKET_STATS
316  p->seen = 0;
317  p->post_tx = 0;
318  p->get_free = 0;
319  p->rxd = 0;
320 #endif
321 
322  free_head = p;
323 
324  BOUND_CHECK(free_head);
325 
326  irq_restore();
327  if(bit_is_set(*NIPEND, INT_NUM_MACA)) { *INTFRC = (1 << INT_NUM_MACA); }
328 
329  return;
330 }
331 
332 volatile packet_t* get_free_packet(void) {
333  volatile packet_t *p;
334 
335  safe_irq_disable(MACA);
336 
337  BOUND_CHECK(free_head);
338 
339  p = free_head;
340  if( p != 0 ) {
341  free_head = p->left;
342  free_head->right = 0;
343  }
344 
345  BOUND_CHECK(free_head);
346 
347 #if PACKET_STATS
348  p->get_free++;
349 #endif
350 
351 // print_packets("get_free_packet");
352  irq_restore();
353  if(bit_is_set(*NIPEND, INT_NUM_MACA)) { *INTFRC = (1 << INT_NUM_MACA); }
354 
355  return p;
356 }
357 
358 void post_receive(void) {
359  last_post = RX_POST;
360  /* this sets the rxlen field */
361  /* this is undocumented but very important */
362  /* you will not receive anything without setting it */
363  *MACA_TXLEN = (MAX_PACKET_SIZE << 16);
364  if(dma_rx == 0) {
365  dma_rx = get_free_packet();
366  if (dma_rx == 0) {
367  PRINTF("trying to fill MACA_DMARX in post_receieve but out of packet buffers\n\r");
368  dma_rx = &dummy_rx;
369  /* set the sftclock so that we return to the maca_isr */
370  *MACA_SFTCLK = *MACA_CLK + RECV_SOFTIMEOUT; /* soft timeout */
371  *MACA_TMREN = (1 << maca_tmren_sft);
372  /* no free buffers, so don't start a reception */
373  enable_irq(MACA);
374  return;
375  }
376  }
377  BOUND_CHECK(dma_rx);
378  BOUND_CHECK(dma_tx);
379  *MACA_DMARX = (uint32_t)&(dma_rx->data[0]);
380  /* with timeout */
381  *MACA_SFTCLK = *MACA_CLK + RECV_SOFTIMEOUT; /* soft timeout */
382  *MACA_TMREN = (1 << maca_tmren_sft);
383  /* start the receive sequence */
384  *MACA_CONTROL = ( (1 << maca_ctrl_asap) |
385  ( 4 << PRECOUNT) |
386  ( fcs_mode << NOFC ) |
387  ( prm_mode << PRM) |
388 #if 0 //dak says removing ctrl auto fixes the autoack checksum error --- doesn't cause a performance issue either
389  (1 << maca_ctrl_auto) |
390 #endif
391  (maca_ctrl_seq_rx));
392  /* status bit 10 is set immediately */
393  /* then 11, 10, and 9 get set */
394  /* they are cleared once we get back to maca_isr */
395 }
396 
397 
398 volatile packet_t* rx_packet(void) {
399  volatile packet_t *p;
400  safe_irq_disable(MACA);
401 
402  BOUND_CHECK(rx_head);
403 
404  p = rx_head;
405  if( p != 0 ) {
406  rx_head = p->left;
407  rx_head->right = 0;
408  }
409 
410 #if PACKET_STATS
411  p->rxd++;
412 #endif
413 
414 // print_packets("rx_packet");
415  irq_restore();
416  if(bit_is_set(*NIPEND, INT_NUM_MACA)) { *INTFRC = (1 << INT_NUM_MACA); }
417 
418  return p;
419 }
420 
421 void post_tx(void) {
422  /* set dma tx pointer to the payload */
423  /* and set the tx len */
424  disable_irq(MACA);
425  last_post = TX_POST;
426  dma_tx = tx_head;
427 #if PACKET_STATS
428  dma_tx->post_tx++;
429 #endif
430  *MACA_TXSEQNR = dma_tx->data[2];
431  *MACA_TXLEN = (uint32_t)((dma_tx->length) + 2) | (3 << 16); /* set rx len to ACK length */
432  *MACA_DMATX = (uint32_t)&(dma_tx->data[ 0 + dma_tx->offset]);
433  if(dma_rx == 0) {
434  dma_rx = get_free_packet();
435  if (dma_rx == 0) {
436  dma_rx = &dummy_ack;
437  PRINTF("trying to fill MACA_DMARX on post_tx but out of packet buffers\n\r");
438  }
439 
440  }
441  BOUND_CHECK(dma_rx);
442  BOUND_CHECK(dma_tx);
443  *MACA_DMARX = (uint32_t)&(dma_rx->data[0]);
444  /* disable soft timeout clock */
445  /* disable start clock */
446  *MACA_TMRDIS = (1 << maca_tmren_sft) | ( 1<< maca_tmren_cpl) | ( 1 << maca_tmren_strt ) ;
447 
448  /* set complete clock to long value */
449  /* acts like a watchdog in case the MACA locks up */
450  *MACA_CPLCLK = *MACA_CLK + CPL_TIMEOUT;
451  /* enable complete clock */
452  *MACA_TMREN = (1 << maca_tmren_cpl);
453 
454  enable_irq(MACA);
455  *MACA_CONTROL = ( ( 4 << PRECOUNT) |
456  ( prm_mode << PRM) |
457  (maca_ctrl_mode_no_cca << maca_ctrl_mode) |
458  (1 << maca_ctrl_asap) |
459  (maca_ctrl_seq_tx));
460  /* status bit 10 is set immediately */
461  /* then 11, 10, and 9 get set */
462  /* they are cleared once we get back to maca_isr */
463 }
464 
465 void tx_packet(volatile packet_t *p) {
466  safe_irq_disable(MACA);
467 
468  BOUND_CHECK(p);
469 
470  if(!p) { PRINTF("tx_packet passed packet 0\n\r"); return; }
471  if(tx_head == 0) {
472  /* start a new queue if empty */
473  tx_end = p;
474  tx_end->left = 0; tx_end->right = 0;
475  tx_head = tx_end;
476  } else {
477  /* add p to the end of the queue */
478  tx_end->left = p;
479  p->right = tx_end;
480  /* move the queue */
481  tx_end = p; tx_end->left = 0;
482  }
483 // print_packets("tx packet");
484  irq_restore();
485  if(bit_is_set(*NIPEND, INT_NUM_MACA)) { *INTFRC = (1 << INT_NUM_MACA); }
486  if(last_post == NO_POST) { *INTFRC = (1<<INT_NUM_MACA); }
487  /* if we are in a reception cycle, advance the softclock timeout to now */
488  if(last_post == RX_POST) { *MACA_SFTCLK = *MACA_CLK + CLK_PER_BYTE; }
489  return;
490 }
491 
492 void free_all_packets(void) {
493  volatile int i;
494  safe_irq_disable(MACA);
495 
496  free_head = 0;
497  for(i=0; i<NUM_PACKETS; i++) {
498  maca_free_packet((volatile packet_t *)&(packet_pool[i]));
499  }
500  rx_head = 0; rx_end = 0;
501  tx_head = 0; tx_end = 0;
502 
503  irq_restore();
504  if(bit_is_set(*NIPEND, INT_NUM_MACA)) { *INTFRC = (1 << INT_NUM_MACA); }
505 
506  return;
507 }
508 
509 /* private routines used by driver */
510 
511 void free_tx_head(void) {
512  volatile packet_t *p;
513  safe_irq_disable(MACA);
514 
515  BOUND_CHECK(tx_head);
516 
517  p = tx_head;
518  tx_head = tx_head->left;
519  if(tx_head == 0) { tx_end = 0; }
520  maca_free_packet(p);
521 
522 // print_packets("free tx head");
523  irq_restore();
524  if(bit_is_set(*NIPEND, INT_NUM_MACA)) { *INTFRC = (1 << INT_NUM_MACA); }
525 
526  return;
527 }
528 
529 void add_to_rx(volatile packet_t *p) {
530  safe_irq_disable(MACA);
531 
532  BOUND_CHECK(p);
533 
534  if(!p) { PRINTF("add_to_rx passed packet 0\n\r"); return; }
535  p->offset = 1; /* first byte is the length */
536  if(rx_head == 0) {
537  /* start a new queue if empty */
538  rx_end = p;
539  rx_end->left = 0; rx_end->right = 0;
540  rx_head = rx_end;
541  } else {
542  rx_end->left = p;
543  p->right = rx_end;
544  rx_end = p; rx_end->left = 0;
545  }
546 
547 // print_packets("add to rx");
548  irq_restore();
549  if(bit_is_set(*NIPEND, INT_NUM_MACA)) { *INTFRC = (1 << INT_NUM_MACA); }
550 
551  return;
552 }
553 
554 void insert_at_rx_head(volatile packet_t *p) {
555  safe_irq_disable(MACA);
556 
557  BOUND_CHECK(p);
558 
559  if(!p) { PRINTF("insert_at_rx_head passed packet 0\n\r"); return; }
560  p->offset = 1; /* first byte is the length */
561  if(rx_head == 0) {
562  /* start a new queue if empty */
563  rx_end = p;
564  rx_end->left = 0; rx_end->right = 0;
565  rx_head = rx_end;
566  } else {
567  rx_head->right = p;
568  p->left = rx_head;
569  p->right = 0;
570  rx_head = p;
571  }
572 
573 // print_packets("insert at rx head");
574  irq_restore();
575  if(bit_is_set(*NIPEND, INT_NUM_MACA)) { *INTFRC = (1 << INT_NUM_MACA); }
576 
577  return;
578 }
579 
580 
581 void decode_status(void) {
582  volatile uint32_t code;
583 
584  code = get_field(*MACA_STATUS,CODE);
585  /* PRINTF("status code 0x%x\n\r",code); */
586 
587  switch(code)
588  {
589  case ABORTED:
590  {
591  PRINTF("maca: aborted\n\r");
592  ResumeMACASync();
593  break;
594 
595  }
596  case NOT_COMPLETED:
597  {
598  PRINTF("maca: not completed\n\r");
599  ResumeMACASync();
600  break;
601 
602  }
603  case CODE_TIMEOUT:
604  {
605  PRINTF("maca: timeout\n\r");
606  ResumeMACASync();
607  break;
608 
609  }
610  case NO_ACK:
611  {
612  PRINTF("maca: no ack\n\r");
613  ResumeMACASync();
614  break;
615 
616  }
617  case EXT_TIMEOUT:
618  {
619  PRINTF("maca: ext timeout\n\r");
620  ResumeMACASync();
621  break;
622 
623  }
624  case EXT_PND_TIMEOUT:
625  {
626  PRINTF("maca: ext pnd timeout\n\r");
627  ResumeMACASync();
628  break;
629  }
630  case SUCCESS:
631  {
632  //PRINTF("maca: success\n\r");
633  ResumeMACASync();
634  break;
635  }
636  default:
637  {
638  PRINTF("status: %x", (unsigned int)*MACA_STATUS);
639  ResumeMACASync();
640 
641  }
642  }
643 }
644 
645 void maca_isr(void) {
646 
647 // print_packets("maca_isr");
648 
649  maca_entry++;
650 
651  if (bit_is_set(*MACA_STATUS, maca_status_ovr))
652  { PRINTF("maca overrun\n\r"); }
653  if (bit_is_set(*MACA_STATUS, maca_status_busy))
654  { PRINTF("maca busy\n\r"); }
655  if (bit_is_set(*MACA_STATUS, maca_status_crc))
656  { PRINTF("maca crc error\n\r"); }
657  if (bit_is_set(*MACA_STATUS, maca_status_to))
658  { PRINTF("maca timeout\n\r"); }
659 
660  if (data_indication_irq()) {
661  *MACA_CLRIRQ = (1 << maca_irq_di);
662 
663  if (dma_rx != &dummy_ack && dma_rx != &dummy_rx)
664  {
665  dma_rx->length = *MACA_GETRXLVL - 2; /* packet length does not include FCS */
666  dma_rx->lqi = get_lqi();
667  dma_rx->rx_time = *MACA_TIMESTAMP;
668 
669  /* check if received packet needs an ack */
670  if(prm_mode == AUTOACK && (dma_rx->data[1] & 0x20)) {
671  /* this wait is necessary to auto-ack */
672  volatile uint32_t wait_clk;
673  wait_clk = *MACA_CLK + 200;
674  while(*MACA_CLK < wait_clk) { continue; }
675  }
676 
677  if(maca_rx_callback != 0) { maca_rx_callback(dma_rx); }
678 
679  add_to_rx(dma_rx);
680  }
681  dma_rx = 0;
682  }
683  if (filter_failed_irq()) {
684  PRINTF("maca filter failed\n\r");
685  ResumeMACASync();
686  *MACA_CLRIRQ = (1 << maca_irq_flt);
687  }
688  if (checksum_failed_irq()) {
689  PRINTF("maca checksum failed\n\r");
690  ResumeMACASync();
691  *MACA_CLRIRQ = (1 << maca_irq_crc);
692  }
693  if (softclock_irq()) {
694  *MACA_CLRIRQ = (1 << maca_irq_sftclk);
695  }
696  if (poll_irq()) {
697  *MACA_CLRIRQ = (1 << maca_irq_poll);
698  }
699  if(action_complete_irq()) {
700  /* PRINTF("maca action complete %d\n\r", get_field(*MACA_CONTROL,SEQUENCE)); */
701  if(last_post == TX_POST) {
702  tx_head->status = get_field(*MACA_STATUS,CODE);
703 
704 #if MACA_INSERT_ACK
705 /* Having sent a message with the acknowledge request flag set the
706  * MACA hardware will only give a tx success indication if the message
707  * was acknowledged by the remote node. We need to detect this
708  * condition and inject an ACK packet into the internal receive stream
709  * as the higher layers are expecting to see an ACK packet.*/
710 
711  if(tx_head->status == SUCCESS && (tx_head->data[0] & MAC_ACK_REQUEST_FLAG)) {
712 
713  /* Create the dummy ack packet */
714 
715  static volatile packet_t *ack_p;
716  if(ack_p = get_free_packet()) {
717  ack_p->length = 3;
718  ack_p->offset = 1;
719  ack_p->data[0] = 3;
720  ack_p->data[1] = 0x02;
721  ack_p->data[2] = 0;
722  ack_p->data[3] = *MACA_TXSEQNR;
723  insert_at_rx_head(ack_p);
724  }
725 
726  }
727 #endif
728 
729  if(maca_tx_callback != 0) { maca_tx_callback(tx_head); }
730  dma_tx = 0;
731  free_tx_head();
732  last_post = NO_POST;
733  }
734  ResumeMACASync();
735  *MACA_CLRIRQ = (1 << maca_irq_acpl);
736  }
737 
738  decode_status();
739 
740  if (*MACA_IRQ != 0)
741  { PRINTF("*MACA_IRQ %x\n\r", (unsigned int)*MACA_IRQ); }
742 
743  if(tx_head != 0) {
744  post_tx();
745  } else {
746  post_receive();
747  }
748 }
749 
750 
751 static uint8_t ram_values[4];
752 
753 
754 void init_phy(void)
755 {
756 // *MACA_TMREN = (1 << maca_tmren_strt) | (1 << maca_tmren_cpl);
757  *MACA_CLKDIV = MACA_CLOCK_DIV;
758  *MACA_WARMUP = 0x00180012;
759  *MACA_EOFDELAY = 0x00000004;
760  *MACA_CCADELAY = 0x001a0022;
761  *MACA_TXCCADELAY = 0x00000025;
762  *MACA_FRAMESYNC0 = 0x000000A7;
763  *MACA_CLK = 0x00000008;
764  *MACA_RXACKDELAY = 30;
765  *MACA_RXEND = 180;
766  *MACA_TXACKDELAY = 68;
767  *MACA_MASKIRQ = ((1 << maca_irq_rst) |
768  (1 << maca_irq_acpl) |
769  (1 << maca_irq_cm) |
770  (1 << maca_irq_flt) |
771  (1 << maca_irq_crc) |
772  (1 << maca_irq_di) |
773  (1 << maca_irq_sftclk)
774  );
775  *MACA_SLOTOFFSET = 0x00350000;
776 }
777 
778 void reset_maca(void)
779 {
780  volatile uint32_t cnt;
781 
782  *MACA_RESET = (1 << maca_reset_rst);
783 
784  for(cnt = 0; cnt < 100; cnt++) {};
785 
786  *MACA_RESET = (1 << maca_reset_clkon);
787 
788  *MACA_CONTROL = maca_ctrl_seq_nop;
789 
790  for(cnt = 0; cnt < 400000; cnt++) {};
791 
792  /* Clear all interrupts. */
793  *MACA_CLRIRQ = 0xffff;
794 }
795 
796 
797 /*
798  004030c4 <SMAC_InitFlybackSettings>:
799  4030c4: 4806 ldr r0, [pc, #24] (4030e0 <SMAC_InitFlybackSettings+0x1c>) // r0 gets base 0x80009a00
800  4030c6: 6881 ldr r1, [r0, #8] // r1 gets *(0x80009a08)
801  4030c8: 4806 ldr r0, [pc, #24] (4030e4 <SMAC_InitFlybackSettings+0x20>) // r0 gets 0x0000f7df
802  4030ca: 4308 orrs r0, r1 // or them, r0 has it
803  4030cc: 4904 ldr r1, [pc, #16] (4030e0 <SMAC_InitFlybackSettings+0x1c>) // r1 gets base 0x80009a00
804  4030ce: 6088 str r0, [r1, #8] // put r0 into 0x80009a08
805  4030d0: 0008 lsls r0, r1, #0 // r0 gets r1, r0 is the base now
806  4030d2: 4905 ldr r1, [pc, #20] (4030e8 <SMAC_InitFlybackSettings+0x24>) // r1 gets 0x00ffffff
807  4030d4: 60c1 str r1, [r0, #12] // put 0x00ffffff into base+12
808  4030d6: 0b09 lsrs r1, r1, #12 // r1 = 0x00ffffff >> 12
809  4030d8: 6101 str r1, [r0, #16] // put r1 base+16
810  4030da: 2110 movs r1, #16 // r1 gets 16
811  4030dc: 6001 str r1, [r0, #0] // put r1 in the base
812  4030de: 4770 bx lr // return
813  4030e0: 80009a00 .word 0x80009a00
814  4030e4: 0000f7df .word 0x0000f7df
815  4030e8: 00ffffff .word 0x00ffffff
816 */
817 
818 /* tested and is good */
819 #define RF_BASE 0x80009a00
820 void flyback_init(void) {
821  uint32_t val8, or;
822 
823  val8 = *(volatile uint32_t *)(RF_BASE+8);
824  or = val8 | 0x0000f7df;
825  *(volatile uint32_t *)(RF_BASE+8) = or;
826  *(volatile uint32_t *)(RF_BASE+12) = 0x00ffffff;
827  *(volatile uint32_t *)(RF_BASE+16) = (((uint32_t)0x00ffffff)>>12);
828  *(volatile uint32_t *)(RF_BASE) = 16;
829  /* good luck and godspeed */
830 }
831 
832 #define MAX_SEQ1 2
833 const uint32_t addr_seq1[MAX_SEQ1] = {
834  0x80003048,
835  0x8000304c,
836 };
837 
838 const uint32_t data_seq1[MAX_SEQ1] = {
839  0x00000f78,
840  0x00607707,
841 };
842 
843 
844 #define MAX_SEQ2 2
845 const uint32_t addr_seq2[MAX_SEQ2] = {
846  0x8000a050,
847  0x8000a054,
848 };
849 
850 const uint32_t data_seq2[MAX_SEQ2] = {
851  0x0000047b,
852  0x0000007b,
853 };
854 
855 #define MAX_CAL3_SEQ1 3
856 const uint32_t addr_cal3_seq1[MAX_CAL3_SEQ1] = { 0x80009400,0x80009a04,0x80009a00, };
857 const uint32_t data_cal3_seq1[MAX_CAL3_SEQ1] = {0x00020017,0x8185a0a4,0x8c900025, };
858 
859 #define MAX_CAL3_SEQ2 2
860 const uint32_t addr_cal3_seq2[MAX_CAL3_SEQ2] = { 0x80009a00,0x80009a00,};
861 const uint32_t data_cal3_seq2[MAX_CAL3_SEQ2] = { 0x8c900021,0x8c900027,};
862 
863 #define MAX_CAL3_SEQ3 1
864 const uint32_t addr_cal3_seq3[MAX_CAL3_SEQ3] = { 0x80009a00 };
865 const uint32_t data_cal3_seq3[MAX_CAL3_SEQ3] = { 0x8c900000 };
866 
867 #define MAX_CAL5 4
868 const uint32_t addr_cal5[MAX_CAL5] = {
869  0x80009400,
870  0x8000a050,
871  0x8000a054,
872  0x80003048,
873 };
874 const uint32_t data_cal5[MAX_CAL5] = {
875  0x00000017,
876  0x00000000,
877  0x00000000,
878  0x00000f00,
879 };
880 
881 #define MAX_DATA 43
882 const uint32_t addr_reg_rep[MAX_DATA] = { 0x80004118,0x80009204,0x80009208,0x8000920c,0x80009210,0x80009300,0x80009304,0x80009308,0x8000930c,0x80009310,0x80009314,0x80009318,0x80009380,0x80009384,0x80009388,0x8000938c,0x80009390,0x80009394,0x8000a008,0x8000a018,0x8000a01c,0x80009424,0x80009434,0x80009438,0x8000943c,0x80009440,0x80009444,0x80009448,0x8000944c,0x80009450,0x80009460,0x80009464,0x8000947c,0x800094e0,0x800094e4,0x800094e8,0x800094ec,0x800094f0,0x800094f4,0x800094f8,0x80009470,0x8000981c,0x80009828 };
883 
884 const uint32_t data_reg_rep[MAX_DATA] = { 0x00180012,0x00000605,0x00000504,0x00001111,0x0fc40000,0x20046000,0x4005580c,0x40075801,0x4005d801,0x5a45d800,0x4a45d800,0x40044000,0x00106000,0x00083806,0x00093807,0x0009b804,0x000db800,0x00093802,0x00000015,0x00000002,0x0000000f,0x0000aaa0,0x01002020,0x016800fe,0x8e578248,0x000000dd,0x00000946,0x0000035a,0x00100010,0x00000515,0x00397feb,0x00180358,0x00000455,0x00000001,0x00020003,0x00040014,0x00240034,0x00440144,0x02440344,0x04440544,0x0ee7fc00,0x00000082,0x0000002a };
885 
886 void maca_off(void) {
887  /* Do nothing if already off */
888  if (maca_pwr == 0) return;
889 
890  /* wait here till complete and then go off */
891  while (last_post == TX_POST) {
892  return;
893  }
894 
895  disable_irq(MACA);
896  maca_pwr = 0;
897 
898  /* Disable clocks, cancel possible delayed RX post */
899  /* Note mcu will hang if radio is off when a startclk post comes through */
900  *MACA_TMRDIS = (1 << maca_tmren_sft) | ( 1<< maca_tmren_cpl) | ( 1 << maca_tmren_strt);
901 
902  /* Turn off the radio regulators */
903  CRM->VREG_CNTLbits.VREG_1P8V_EN = 0;
904  CRM->VREG_CNTLbits.VREG_1P5V_EN = 0;
905 
906  /* Hold the maca in reset */
907  maca_reset = maca_reset_rst;
908 }
909 
910 void maca_on(void) {
911 
912  if (maca_pwr != 0) {
913  return;
914  }
915  maca_pwr = 1;
916 
917  /* Turn the radio regulators back on */
918  CRM->VREG_CNTLbits.VREG_1P8V_EN = 1;
919  CRM->VREG_CNTLbits.VREG_1P5V_EN = 3;
920  while(CRM->STATUSbits.VREG_1P8V_RDY == 0) { continue; }
921  while(CRM->STATUSbits.VREG_1P5V_RDY == 0) { continue; }
922 
923  /* Take out of reset */
924  *MACA_RESET = (1 << maca_reset_clkon);
925 
926  /* Wait for VREG_1P5V_RDY indication */
927  while (!((*(volatile uint32_t *)0x80003018) & (1<< 19))) {}
928 
929  /* If last turnoff had a pending RX post we will get an action complete/PLL unlock interrupt.
930  * If an abort is now issued we will get an action complete/abort interrupt.
931  * This action complete is delayed by some unknown amount, just clearing MACA_IRQ below will not stop it.
932  * However a NOP does the job!
933  */
934  *MACA_CONTROL = maca_ctrl_seq_nop | (1 << maca_ctrl_asap);
935 
936 /* Something is allowing reserved interrupt 13 on restart? */
937 
938  *MACA_MASKIRQ = ((1 << maca_irq_rst) |
939  (1 << maca_irq_acpl) |
940  (1 << maca_irq_cm) |
941  (1 << maca_irq_flt) |
942  (1 << maca_irq_crc) |
943  (1 << maca_irq_di) |
944  (1 << maca_irq_sftclk)
945  );
946 
947  last_post = NO_POST;
948  *MACA_CLRIRQ = 0xffff;
949  enable_irq(MACA);
950 
951  *INTFRC = (1 << INT_NUM_MACA);
952 }
953 
954 /* initialized with 0x4c */
955 uint8_t ctov[16] = {
956  0x0b,
957  0x0b,
958  0x0b,
959  0x0a,
960  0x0d,
961  0x0d,
962  0x0c,
963  0x0c,
964  0x0f,
965  0x0e,
966  0x0e,
967  0x0e,
968  0x11,
969  0x10,
970  0x10,
971  0x0f,
972 };
973 
974 /* get_ctov thanks to Umberto */
975 
976 #define _INIT_CTOV_WORD_1 0x00dfbe77
977 #define _INIT_CTOV_WORD_2 0x023126e9
978 uint8_t get_ctov( uint32_t r0, uint32_t r1 )
979 {
980 
981  r0 = r0 * _INIT_CTOV_WORD_1;
982  r0 += ( r1 << 22 );
983  r0 += _INIT_CTOV_WORD_2;
984 
985  r0 = (uint32_t)(((int32_t)r0) >> 25);
986 
987  return (uint8_t)r0;
988 }
989 
990 
991 /* radio_init has been tested to be good */
992 void radio_init(void) {
993  volatile uint32_t i;
994  /* sequence 1 */
995  for(i=0; i<MAX_SEQ1; i++) {
996  if((unsigned int)addr_seq1[i] != (unsigned int)CRM_VREG_CNTL) {
997  *(volatile uint32_t *)(addr_seq1[i]) = data_seq1[i];
998  }
999  }
1000  /* seq 1 delay */
1001  for(i=0; i<0x161a8; i++) { continue; }
1002  /* sequence 2 */
1003  for(i=0; i<MAX_SEQ2; i++) {
1004  *(volatile uint32_t *)(addr_seq2[i]) = data_seq2[i];
1005  }
1006  /* modem val */
1007  *(volatile uint32_t *)0x80009000 = 0x80050100;
1008  /* cal 3 seq 1*/
1009  for(i=0; i<MAX_CAL3_SEQ1; i++) {
1010  *(volatile uint32_t *)(addr_cal3_seq1[i]) = data_cal3_seq1[i];
1011  }
1012  /* cal 3 delay */
1013  for(i=0; i<0x11194; i++) { continue; }
1014  /* cal 3 seq 2*/
1015  for(i=0; i<MAX_CAL3_SEQ2; i++) {
1016  *(volatile uint32_t *)(addr_cal3_seq2[i]) = data_cal3_seq2[i];
1017  }
1018  /* cal 3 delay */
1019  for(i=0; i<0x11194; i++) { continue; }
1020  /* cal 3 seq 3*/
1021  for(i=0; i<MAX_CAL3_SEQ3; i++) {
1022  *(volatile uint32_t *)(addr_cal3_seq3[i]) = data_cal3_seq3[i];
1023  }
1024  /* cal 5 */
1025  for(i=0; i<MAX_CAL5; i++) {
1026  if((unsigned int)addr_cal5[i] != (unsigned int)CRM_VREG_CNTL) {
1027  *(volatile uint32_t *)(addr_cal5[i]) = data_cal5[i];
1028  }
1029  }
1030  /*reg replacment */
1031  for(i=0; i<MAX_DATA; i++) {
1032  *(volatile uint32_t *)(addr_reg_rep[i]) = data_reg_rep[i];
1033  }
1034 
1035  PRINTF("initfromflash\n\r");
1036 
1037  init_from_flash(0x1F000);
1038 
1039  PRINTF("ram_values:\n\r");
1040  for(i=0; i<4; i++) {
1041  PRINTF(" 0x%02x\n\r",ram_values[i]);
1042  }
1043 
1044  PRINTF("radio_init: ctov parameter 0x%02x\n\r",ram_values[3]);
1045  for(i=0; i<16; i++) {
1046  ctov[i] = get_ctov(i,ram_values[3]);
1047  PRINTF("radio_init: ctov[%d] = 0x%02x\n\r",(int)i,ctov[i]);
1048  }
1049 
1050 
1051 }
1052 
1053 const uint32_t PSMVAL[19] = {
1054  0x0000080f,
1055  0x0000080f,
1056  0x0000080f,
1057  0x0000080f,
1058  0x0000081f,
1059  0x0000081f,
1060  0x0000081f,
1061  0x0000080f,
1062  0x0000080f,
1063  0x0000080f,
1064  0x0000001f,
1065  0x0000000f,
1066  0x0000000f,
1067  0x00000816,
1068  0x0000001b,
1069  0x0000000b,
1070  0x00000802,
1071  0x00000817,
1072  0x00000003,
1073 };
1074 
1075 const uint32_t PAVAL[19] = {
1076  0x000022c0,
1077  0x000022c0,
1078  0x000022c0,
1079  0x00002280,
1080  0x00002303,
1081  0x000023c0,
1082  0x00002880,
1083  0x000029f0,
1084  0x000029f0,
1085  0x000029f0,
1086  0x000029c0,
1087  0x00002bf0,
1088  0x000029f0,
1089  0x000028a0,
1090  0x00002800,
1091  0x00002ac0,
1092  0x00002880,
1093  0x00002a00,
1094  0x00002b00,
1095 };
1096 
1097 const uint32_t AIMVAL[19] = {
1098  0x000123a0,
1099  0x000163a0,
1100  0x0001a3a0,
1101  0x0001e3a0,
1102  0x000223a0,
1103  0x000263a0,
1104  0x0002a3a0,
1105  0x0002e3a0,
1106  0x000323a0,
1107  0x000363a0,
1108  0x0003a3a0,
1109  0x0003a3a0,
1110  0x0003e3a0,
1111  0x000423a0,
1112  0x000523a0,
1113  0x000423a0,
1114  0x0004e3a0,
1115  0x0004e3a0,
1116  0x0004e3a0,
1117 };
1118 
1119 #define RF_REG 0x80009400
1120 void set_demodulator_type(uint8_t demod) {
1121  uint32_t val = reg(RF_REG);
1122  if(demod == DEMOD_NCD) {
1123  val = (val & ~1);
1124  } else {
1125  val = (val | 1);
1126  }
1127  reg(RF_REG) = val;
1128 }
1129 
1130 /* tested and seems to be good */
1131 #define ADDR_POW1 0x8000a014
1132 #define ADDR_POW2 ADDR_POW1 + 12
1133 #define ADDR_POW3 ADDR_POW1 + 64
1134 void set_power(uint8_t power) {
1135  safe_irq_disable(MACA);
1136 
1137  reg(ADDR_POW1) = PSMVAL[power];
1138 
1139 /* see http://devl.org/pipermail/mc1322x/2009-October/000065.html */
1140 /* reg(ADDR_POW2) = (ADDR_POW1>>18) | PAVAL[power]; */
1141 #ifdef USE_PA
1142  reg(ADDR_POW2) = 0xffffdfff & PAVAL[power]; /* single port */
1143 #else
1144  reg(ADDR_POW2) = 0x00002000 | PAVAL[power]; /* dual port */
1145 #endif
1146 
1147  reg(ADDR_POW3) = AIMVAL[power];
1148 
1149  irq_restore();
1150  if(bit_is_set(*NIPEND, INT_NUM_MACA)) { *INTFRC = (1 << INT_NUM_MACA); }
1151 
1152 }
1153 
1154 const uint8_t VCODivI[16] = {
1155  0x2f,
1156  0x2f,
1157  0x2f,
1158  0x2f,
1159  0x2f,
1160  0x2f,
1161  0x2f,
1162  0x2f,
1163  0x2f,
1164  0x30,
1165  0x30,
1166  0x30,
1167  0x30,
1168  0x30,
1169  0x30,
1170  0x30,
1171 };
1172 
1173 const uint32_t VCODivF[16] = {
1174  0x00355555,
1175  0x006aaaaa,
1176  0x00a00000,
1177  0x00d55555,
1178  0x010aaaaa,
1179  0x01400000,
1180  0x01755555,
1181  0x01aaaaaa,
1182  0x01e00000,
1183  0x00155555,
1184  0x004aaaaa,
1185  0x00800000,
1186  0x00b55555,
1187  0x00eaaaaa,
1188  0x01200000,
1189  0x01555555,
1190 };
1191 
1192 /* tested good */
1193 #define ADDR_CHAN1 0x80009800
1194 #define ADDR_CHAN2 (ADDR_CHAN1+12)
1195 #define ADDR_CHAN3 (ADDR_CHAN1+16)
1196 #define ADDR_CHAN4 (ADDR_CHAN1+48)
1197 void set_channel(uint8_t chan) {
1198  volatile uint32_t tmp;
1199  safe_irq_disable(MACA);
1200 
1201  tmp = reg(ADDR_CHAN1);
1202  tmp = tmp & 0xbfffffff;
1203  reg(ADDR_CHAN1) = tmp;
1204 
1205  reg(ADDR_CHAN2) = VCODivI[chan];
1206  reg(ADDR_CHAN3) = VCODivF[chan];
1207 
1208  tmp = reg(ADDR_CHAN4);
1209  tmp = tmp | 2;
1210  reg(ADDR_CHAN4) = tmp;
1211 
1212  tmp = reg(ADDR_CHAN4);
1213  tmp = tmp | 4;
1214  reg(ADDR_CHAN4) = tmp;
1215 
1216  tmp = tmp & 0xffffe0ff;
1217  tmp = tmp | (((ctov[chan])<<8)&0x1F00);
1218  reg(ADDR_CHAN4) = tmp;
1219  /* duh! */
1220  irq_restore();
1221  if(bit_is_set(*NIPEND, INT_NUM_MACA)) { *INTFRC = (1 << INT_NUM_MACA); }
1222 }
1223 
1224 uint8_t (*get_lqi)(void) = (void *) 0x0000e04d;
1225 
1226 #define ROM_END 0x0013ffff
1227 #define ENTRY_EOF 0x00000e0f
1228 /* processes up to 4 words of initialization entries */
1229 /* returns the number of words processed */
1230 uint32_t exec_init_entry(volatile uint32_t *entries, uint8_t *valbuf)
1231 {
1232  volatile uint32_t i;
1233  if(entries[0] <= ROM_END) {
1234  if (entries[0] == 0) {
1235  /* do delay command*/
1236  PRINTF("init_entry: delay 0x%08x\n\r", (unsigned int)entries[1]);
1237  for(i=0; i<entries[1]; i++) { continue; }
1238  return 2;
1239  } else if (entries[0] == 1) {
1240  /* do bit set/clear command*/
1241  PRINTF("init_entry: bit set clear 0x%08x 0x%08x 0x%08x\n\r", (unsigned int)entries[1], (unsigned int)entries[2], (unsigned int)entries[3]);
1242  reg(entries[2]) = (reg(entries[2]) & ~entries[1]) | (entries[3] & entries[1]);
1243  return 4;
1244  } else if ((entries[0] >= 16) &&
1245  (entries[0] < 0xfff1)) {
1246  /* store bytes in valbuf */
1247  PRINTF("init_entry: store in valbuf 0x%02x position %d\n\r",
1248  (unsigned int)entries[1],
1249  (unsigned int)(entries[0]>>4)-1);
1250  valbuf[(entries[0]>>4)-1] = entries[1];
1251  return 2;
1252  } else if (entries[0] == ENTRY_EOF) {
1253  PRINTF("init_entry: eof ");
1254  return 0;
1255  } else {
1256  /* invalid command code */
1257  PRINTF("init_entry: invaild code 0x%08x\n\r",(unsigned int)entries[0]);
1258  return 0;
1259  }
1260  } else { /* address isn't in ROM space */
1261  /* do store value in address command */
1262  PRINTF("init_entry: address value pair - *0x%08x = 0x%08x\n\r",
1263  (unsigned int)entries[0],
1264  (unsigned int)entries[1]);
1265  if ((unsigned int)entries[0] != (unsigned int)CRM_VREG_CNTL) {
1266  reg(entries[0]) = entries[1];
1267  } else {
1268  PRINTF("skipping VREG_CNTL\n\r");
1269  }
1270  return 2;
1271  }
1272 }
1273 
1274 
1275 #define FLASH_INIT_MAGIC 0x00000abc
1276 uint32_t init_from_flash(uint32_t addr) {
1277  nvmType_t type=0;
1278  nvmErr_t err;
1279  volatile uint32_t buf[8];
1280  volatile uint32_t len;
1281  volatile uint32_t i=0,j;
1282 
1283  err = nvm_detect(gNvmInternalInterface_c, &type);
1284  PRINTF("nvm_detect returned type 0x%08x err 0x%02x\n\r", type, err);
1285 
1286  nvm_setsvar(0);
1287  err = nvm_read(gNvmInternalInterface_c, type, (uint8_t *)buf, addr, 8);
1288  i+=8;
1289  PRINTF("nvm_read returned: 0x%02x\n\r",err);
1290 
1291  for(j=0; j<4; j++) {
1292  PRINTF("0x%08x\n\r",(unsigned int)buf[j]);
1293  }
1294 
1295  if(buf[0] == FLASH_INIT_MAGIC) {
1296  len = buf[1] & 0x0000ffff;
1297  while(i < (len-4)) {
1298  err = nvm_read(gNvmInternalInterface_c, type, (uint8_t *)buf, addr+i, 32);
1299  i += 4*exec_init_entry(buf, ram_values);
1300  }
1301  } else {
1302  i = 0;
1303  }
1304  nvm_setsvar(1);
1305  return i;
1306 }
1307 
1308 /*
1309  * Do the ABORT-Wait-NOP-Wait sequence in order to prevent MACA malfunctioning.
1310  * This seqeunce is synchronous and no interrupts should be triggered when it is done.
1311  */
1312 void ResumeMACASync(void)
1313 {
1314  volatile uint32_t clk, TsmRxSteps, LastWarmupStep, LastWarmupData, LastWarmdownStep, LastWarmdownData;
1315 // bool_t tmpIsrStatus;
1316  volatile uint32_t i;
1317  safe_irq_disable(MACA);
1318 
1319 // ITC_DisableInterrupt(gMacaInt_c);
1320 // AppInterrupts_ProtectFromMACAIrq(tmpIsrStatus); <- Original from MAC code, but not sure how is it implemented
1321 
1322  /* Manual TSM modem shutdown */
1323 
1324  /* read TSM_RX_STEPS */
1325  TsmRxSteps = (*((volatile uint32_t *)(0x80009204)));
1326 
1327  /* isolate the RX_WU_STEPS */
1328  /* shift left to align with 32-bit addressing */
1329  LastWarmupStep = (TsmRxSteps & 0x1f) << 2;
1330  /* Read "current" TSM step and save this value for later */
1331  LastWarmupData = (*((volatile uint32_t *)(0x80009300 + LastWarmupStep)));
1332 
1333  /* isolate the RX_WD_STEPS */
1334  /* right-shift bits down to bit 0 position */
1335  /* left-shift to align with 32-bit addressing */
1336  LastWarmdownStep = ((TsmRxSteps & 0x1f00) >> 8) << 2;
1337  /* write "last warmdown data" to current TSM step to shutdown rx */
1338  LastWarmdownData = (*((volatile uint32_t *)(0x80009300 + LastWarmdownStep)));
1339  (*((volatile uint32_t *)(0x80009300 + LastWarmupStep))) = LastWarmdownData;
1340 
1341  /* Abort */
1342  MACA_WRITE(maca_control, 1);
1343 
1344  /* Wait ~8us */
1345  for (clk = maca_clk, i = 0; maca_clk - clk < 3 && i < 300; i++)
1346  ;
1347 
1348  /* NOP */
1349  MACA_WRITE(maca_control, 0);
1350 
1351  /* Wait ~8us */
1352  for (clk = maca_clk, i = 0; maca_clk - clk < 3 && i < 300; i++)
1353  ;
1354 
1355 
1356  /* restore original "last warmup step" data to TSM (VERY IMPORTANT!!!) */
1357  (*((volatile uint32_t *)(0x80009300 + LastWarmupStep))) = LastWarmupData;
1358 
1359 
1360 
1361  /* Clear all MACA interrupts - we should have gotten the ABORT IRQ */
1362  MACA_WRITE(maca_clrirq, 0xFFFF);
1363 
1364 // AppInterrupts_UnprotectFromMACAIrq(tmpIsrStatus); <- Original from MAC code, but not sure how is it implemented
1365 // ITC_EnableInterrupt(gMacaInt_c);
1366 // enable_irq(MACA);
1367  irq_restore();
1368 
1369 }
radio_status_t radio_init(bool cal_rc_osc, hal_rx_start_isr_event_handler_t rx_event, hal_trx_end_isr_event_handler_t trx_end_event, radio_rx_callback rx_callback)
Initialize the Transceiver Access Toolbox and lower layers.
Definition: radio.c:160