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