Contiki 2.6

maca.c

00001 /*
00002  * Copyright (c) 2010, Mariano Alvira <mar@devl.org> and other contributors
00003  * to the MC1322x project (http://mc1322x.devl.org)
00004  * All rights reserved.
00005  *
00006  * Redistribution and use in source and binary forms, with or without
00007  * modification, are permitted provided that the following conditions
00008  * are met:
00009  * 1. Redistributions of source code must retain the above copyright
00010  *    notice, this list of conditions and the following disclaimer.
00011  * 2. Redistributions in binary form must reproduce the above copyright
00012  *    notice, this list of conditions and the following disclaimer in the
00013  *    documentation and/or other materials provided with the distribution.
00014  * 3. Neither the name of the Institute nor the names of its contributors
00015  *    may be used to endorse or promote products derived from this software
00016  *    without specific prior written permission.
00017  *
00018  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
00019  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00020  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00021  * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
00022  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00023  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
00024  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
00025  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00026  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
00027  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
00028  * SUCH DAMAGE.
00029  *
00030  * This file is part of libmc1322x: see http://mc1322x.devl.org
00031  * for details. 
00032  *
00033  *
00034  */
00035 
00036 #include <mc1322x.h>
00037 #include <stdio.h>
00038 
00039 #ifndef DEBUG_MACA 
00040 #define DEBUG_MACA 0
00041 #endif
00042 #if (DEBUG_MACA == 0)
00043 #define PRINTF(...) 
00044 #else
00045 #define PRINTF(...) printf(__VA_ARGS__)
00046 #endif
00047 
00048 #ifndef MACA_BOUND_CHECK
00049 #define MACA_BOUND_CHECK 0
00050 #endif
00051 #if (MACA_BOUND_CHECK == 0)
00052 #define BOUND_CHECK(x)
00053 #else
00054 #define BOUND_CHECK(x) bound_check(x)
00055 #endif
00056 
00057 #ifndef NUM_PACKETS
00058 #define NUM_PACKETS 32
00059 #endif
00060 
00061 /* for 250kHz clock */
00062 #define MACA_CLOCK_DIV 95
00063 /* (32 chips/sym) * (sym/4bits) * (8bits/byte) = (64 chips/byte)  */
00064 /* (8 chips/clk) * (byte/64 chips) = byte/8clks */
00065 #define CLK_PER_BYTE 8 
00066 
00067 #ifndef RECV_SOFTIMEOUT
00068 #define RECV_SOFTIMEOUT (1024*128*CLK_PER_BYTE) 
00069 #endif
00070 
00071 #ifndef CPL_TIMEOUT
00072 #define CPL_TIMEOUT (2*128*CLK_PER_BYTE) 
00073 #endif
00074 
00075 #ifndef MACA_INSERT_ACK
00076 #define MACA_INSERT_ACK 1
00077 #endif
00078 
00079 /* Bit in first byte of 802.15.4 message that indicates an */
00080 /* acknowledgereply frame is expected */
00081 #define MAC_ACK_REQUEST_FLAG 0x20
00082 
00083 #define reg(x) (*(volatile uint32_t *)(x))
00084 
00085 int count_packets(void);
00086 void Print_Packets(char *s);
00087 
00088 static volatile packet_t packet_pool[NUM_PACKETS];
00089 static volatile packet_t *free_head, *rx_end, *tx_end, *dma_tx, *dma_rx;
00090 
00091 /* rx_head and tx_head are visible to the outside */
00092 /* so you can peek at it and see if there is data */
00093 /* waiting for you, or data still to be sent */
00094 volatile packet_t *rx_head, *tx_head;
00095 
00096 /* used for ack recpetion if the packet_pool goes empty */
00097 /* doesn't go back into the pool when freed */
00098 static volatile packet_t dummy_ack;
00099 
00100 /* incremented on every maca entry */
00101 /* you can use this to detect that the receive loop is still running */
00102 volatile uint32_t maca_entry = 0;
00103 
00104 enum posts {
00105         NO_POST = 0,
00106         TX_POST,
00107         RX_POST,
00108         MAX_POST,
00109 };
00110 static volatile uint8_t last_post = NO_POST;
00111 
00112 volatile uint8_t fcs_mode = USE_FCS; 
00113 volatile uint8_t prm_mode = PROMISC;
00114 
00115 /* call periodically to */
00116 /* check that maca_entry is changing */
00117 /* if it is not, it will do a manual call to maca_isr which should */
00118 /* get the ball rolling again */
00119 /* also checks that the clock is running --- if it isn't then */
00120 /* it calls redoes the maca intialization but _DOES NOT_ free all packets */ 
00121 
00122 void check_maca(void) {
00123         safe_irq_disable(MACA);
00124         static volatile uint32_t last_time;
00125         static volatile uint32_t last_entry;
00126         volatile uint32_t i;
00127 #if DEBUG_MACA
00128         volatile uint32_t count;
00129 #endif 
00130         
00131 
00132         /* if *MACA_CLK == last_time */
00133         /* try waiting for one clock period */
00134         /* since maybe check_maca is getting called quickly */  
00135         for(i=0; (i < 1024) && (*MACA_CLK == last_time); i++) { continue; }
00136 
00137         if(*MACA_CLK == last_time) {
00138                 PRINTF("check maca: maca_clk stopped, restarting\n");
00139                 /* clock isn't running */
00140                 ResumeMACASync();
00141                 *INTFRC = (1<<INT_NUM_MACA);
00142         } else {
00143                 if((last_time > (*MACA_SFTCLK + RECV_SOFTIMEOUT)) &&
00144                    (last_time > (*MACA_CPLCLK + CPL_TIMEOUT))) {
00145                         PRINTF("check maca: complete clocks expired\n");
00146                         /* all complete clocks have expired */
00147                         /* check that maca entry is changing */
00148                         /* if not, do call the isr to restart the cycle */
00149                         if(last_entry == maca_entry) {
00150                                 PRINTF("check maca: forcing isr\n");
00151                                 *INTFRC = (1<<INT_NUM_MACA);
00152                         }
00153                 }
00154         }
00155                 
00156         last_entry = maca_entry;
00157         last_time = *MACA_CLK;
00158 
00159 #if DEBUG_MACA
00160         if((count = count_packets()) != NUM_PACKETS) {
00161                 PRINTF("check maca: count_packets %d\n", (int)count);
00162                 Print_Packets("check_maca");
00163 #if PACKET_STATS
00164                 for(i=0; i<NUM_PACKETS; i++) {
00165                         printf("packet 0x%lx seen %d post_tx %d get_free %d rxd %d\n", 
00166                                (uint32_t) &packet_pool[i], 
00167                                packet_pool[i].seen, 
00168                                packet_pool[i].post_tx, 
00169                                packet_pool[i].get_free, 
00170                                packet_pool[i].rxd);
00171                 }
00172 #endif
00173                 if(bit_is_set(*NIPEND, INT_NUM_MACA)) { *INTFRC = (1 << INT_NUM_MACA); }
00174         }
00175 #endif /* DEBUG_MACA */
00176         irq_restore();
00177 }
00178 
00179 void maca_init(void) {
00180         reset_maca();
00181         radio_init();
00182         flyback_init();
00183         init_phy();
00184         set_channel(0); /* things get weird if you never set a channel */
00185         set_power(0);   /* set the power too --- who knows what happens if you don't */
00186         free_head = 0; tx_head = 0; rx_head = 0; rx_end = 0; tx_end = 0; dma_tx = 0; dma_rx = 0;
00187         free_all_packets();
00188 
00189         #if DEBUG_MACA
00190         Print_Packets("maca_init");
00191         #endif
00192         
00193         /* initial radio command */
00194         /* nop, promiscuous, no cca */
00195         *MACA_CONTROL =
00196                 (prm_mode << PRM) |
00197                 (NO_CCA << MACA_MODE);
00198         
00199         enable_irq(MACA);
00200         *INTFRC = (1 << INT_NUM_MACA);
00201 }
00202 
00203 #define print_packets(x) Print_Packets(x)
00204 void Print_Packets(char *s) {
00205         volatile packet_t *p;
00206 
00207         printf("packet pool after %s:\n\r",s);
00208         p = free_head;  
00209         printf("free_head: 0x%lx ", (uint32_t) free_head);
00210         while(p != 0) {
00211                 p = p->left;
00212                 printf("->0x%lx", (uint32_t) p);
00213         }
00214         printf("\n\r");
00215 
00216         p = tx_head;
00217         printf("tx_head: 0x%lx ", (uint32_t) tx_head);
00218         while(p != 0) {
00219                 p = p->left;
00220                 printf("->0x%lx", (uint32_t) p);
00221         }
00222         printf("\n\r");
00223 
00224         p = rx_head;
00225         printf("rx_head: 0x%lx ", (uint32_t) rx_head);
00226         while(p != 0) {
00227                 p = p->left;
00228                 printf("->0x%lx", (uint32_t) p);
00229         }
00230         printf("\n\r");
00231 
00232         printf("dma_rx: 0x%lx\n", (uint32_t) dma_rx);
00233         printf("dma_tx: 0x%lx\n", (uint32_t) dma_tx);
00234 
00235 }
00236 
00237 inline void bad_packet_bounds(void) {
00238         PRINTF("bad packet bounds! Halting.\n");
00239         while(1) { continue; }
00240 }
00241 
00242 int count_packets(void) {
00243         volatile int8_t total = -1;
00244 
00245 #if PACKET_STATS
00246         volatile packet_t *pk;
00247         volatile uint8_t tx, rx, free;
00248         volatile int i;
00249 
00250         for(i = 0; i < NUM_PACKETS; i++) {
00251                 packet_pool[i].seen = 0;
00252         }
00253 
00254         pk = tx_head; tx = 0;
00255         while( pk != 0 ) {
00256                 if(pk->seen == 0) { tx++; }
00257                 pk->seen++;
00258                 pk = pk->left;
00259         }
00260         pk = rx_head; rx = 0;
00261         while( pk != 0 ) {
00262                 if(pk->seen == 0) { rx++; }
00263                 pk->seen++;
00264                 pk = pk->left;
00265         }
00266         pk = free_head; free = 0;
00267         while( pk != 0 ) {
00268                 if(pk->seen == 0) { free++; }
00269                 pk->seen++;
00270                 pk = pk->left;
00271         }
00272 
00273         total = free + rx + tx;
00274         if(dma_rx && (dma_rx->seen == 0)) { dma_rx->seen++; total++; }
00275         if(dma_tx && (dma_tx->seen == 0)) { dma_tx->seen++; total++; }
00276 #endif /* PACKET_STATS */
00277 
00278         return total;
00279 }       
00280 
00281 void bound_check(volatile packet_t *p) {
00282         volatile int i;
00283 
00284         if((p == 0) ||
00285            (p == &dummy_ack)) { return; }
00286         for(i=0; i < NUM_PACKETS; i++) {
00287                 if(p == &packet_pool[i]) { return; }
00288         }
00289 
00290         bad_packet_bounds();
00291 }
00292 
00293 
00294 /* public packet routines */
00295 /* heads are to the right */
00296 /* ends are to the left */
00297 void free_packet(volatile packet_t *p) {
00298         safe_irq_disable(MACA);
00299 
00300         BOUND_CHECK(p);
00301 
00302         if(!p) {  PRINTF("free_packet passed packet 0\n\r"); return; }
00303         if(p == &dummy_ack) { return; }
00304 
00305         BOUND_CHECK(free_head);
00306 
00307         p->length = 0; p->offset = 0;
00308         p->left = free_head; p->right = 0;
00309 #if PACKET_STATS
00310         p->seen = 0; 
00311         p->post_tx = 0;
00312         p->get_free = 0;
00313         p->rxd = 0;
00314 #endif
00315 
00316         free_head = p;
00317 
00318         BOUND_CHECK(free_head);
00319 
00320         irq_restore();
00321         if(bit_is_set(*NIPEND, INT_NUM_MACA)) { *INTFRC = (1 << INT_NUM_MACA); }
00322 
00323         return;
00324 }
00325 
00326 volatile packet_t* get_free_packet(void) {
00327         volatile packet_t *p;
00328 
00329         safe_irq_disable(MACA);
00330         
00331         BOUND_CHECK(free_head);
00332 
00333         p = free_head;
00334         if( p != 0 ) {          
00335                 free_head = p->left;
00336                 free_head->right = 0;
00337         }
00338 
00339         BOUND_CHECK(free_head);
00340 
00341 #if PACKET_STATS
00342         p->get_free++;
00343 #endif
00344 
00345 //      print_packets("get_free_packet");
00346         irq_restore();
00347         if(bit_is_set(*NIPEND, INT_NUM_MACA)) { *INTFRC = (1 << INT_NUM_MACA); }
00348 
00349         return p;
00350 }
00351 
00352 void post_receive(void) {
00353         last_post = RX_POST;
00354         /* this sets the rxlen field */
00355         /* this is undocumented but very important */
00356         /* you will not receive anything without setting it */
00357         *MACA_TXLEN = (MAX_PACKET_SIZE << 16);
00358         if(dma_rx == 0) {
00359                 dma_rx = get_free_packet();
00360                 if (dma_rx == 0) {
00361                         PRINTF("trying to fill MACA_DMARX in post_receieve but out of packet buffers\n\r");             
00362                         /* set the sftclock so that we return to the maca_isr */
00363                         *MACA_SFTCLK = *MACA_CLK + RECV_SOFTIMEOUT; /* soft timeout */ 
00364                         *MACA_TMREN = (1 << maca_tmren_sft);
00365                         /* no free buffers, so don't start a reception */
00366                         enable_irq(MACA);
00367                         return;
00368                 }
00369         }
00370         BOUND_CHECK(dma_rx);
00371         BOUND_CHECK(dma_tx);
00372         *MACA_DMARX = (uint32_t)&(dma_rx->data[0]);
00373         /* with timeout */              
00374         *MACA_SFTCLK = *MACA_CLK + RECV_SOFTIMEOUT; /* soft timeout */ 
00375         *MACA_TMREN = (1 << maca_tmren_sft);
00376         /* start the receive sequence */
00377         *MACA_CONTROL = ( (1 << maca_ctrl_asap) | 
00378                           ( 4 << PRECOUNT) |
00379                           ( fcs_mode << NOFC ) |
00380                           ( prm_mode << PRM) |
00381 #if 0 //dak says removing ctrl auto fixes the autoack checksum error --- doesn't cause a performance issue either
00382                           (1 << maca_ctrl_auto) |
00383 #endif
00384                           (maca_ctrl_seq_rx));
00385         /* status bit 10 is set immediately */
00386         /* then 11, 10, and 9 get set */ 
00387         /* they are cleared once we get back to maca_isr */ 
00388 }
00389 
00390 
00391 volatile packet_t* rx_packet(void) {
00392         volatile packet_t *p;
00393         safe_irq_disable(MACA);
00394 
00395         BOUND_CHECK(rx_head);
00396 
00397         p = rx_head;
00398         if( p != 0 ) {
00399                 rx_head = p->left;
00400                 rx_head->right = 0;
00401         }
00402 
00403 #if PACKET_STATS
00404         p->rxd++;
00405 #endif
00406 
00407 //      print_packets("rx_packet");
00408         irq_restore();
00409         if(bit_is_set(*NIPEND, INT_NUM_MACA)) { *INTFRC = (1 << INT_NUM_MACA); }
00410 
00411         return p;
00412 }
00413 
00414 void post_tx(void) {
00415         /* set dma tx pointer to the payload */
00416         /* and set the tx len */
00417         disable_irq(MACA);
00418         last_post = TX_POST;
00419         dma_tx = tx_head; 
00420 #if PACKET_STATS
00421         dma_tx->post_tx++;
00422 #endif
00423         *MACA_TXSEQNR = dma_tx->data[2];
00424         *MACA_TXLEN = (uint32_t)((dma_tx->length) + 2) | (3 << 16); /* set rx len to ACK length */
00425         *MACA_DMATX = (uint32_t)&(dma_tx->data[ 0 + dma_tx->offset]);
00426         if(dma_rx == 0) {
00427                 dma_rx = get_free_packet();
00428                 if (dma_rx == 0) { 
00429                         dma_rx = &dummy_ack;
00430                         PRINTF("trying to fill MACA_DMARX on post_tx but out of packet buffers\n\r");
00431                 }
00432                 
00433         }       
00434         BOUND_CHECK(dma_rx);
00435         BOUND_CHECK(dma_tx);
00436         *MACA_DMARX = (uint32_t)&(dma_rx->data[0]);
00437         /* disable soft timeout clock */
00438         /* disable start clock */
00439         *MACA_TMRDIS = (1 << maca_tmren_sft) | ( 1<< maca_tmren_cpl) | ( 1 << maca_tmren_strt ) ;
00440         
00441         /* set complete clock to long value */
00442         /* acts like a watchdog in case the MACA locks up */
00443         *MACA_CPLCLK = *MACA_CLK + CPL_TIMEOUT;
00444         /* enable complete clock */
00445         *MACA_TMREN = (1 << maca_tmren_cpl);
00446         
00447         enable_irq(MACA);
00448         *MACA_CONTROL = ( ( 4 << PRECOUNT) |
00449                           ( prm_mode << PRM) |
00450                           (maca_ctrl_mode_no_cca << maca_ctrl_mode) |
00451                           (1 << maca_ctrl_asap) |
00452                           (maca_ctrl_seq_tx));  
00453         /* status bit 10 is set immediately */
00454         /* then 11, 10, and 9 get set */ 
00455         /* they are cleared once we get back to maca_isr */ 
00456 }
00457 
00458 void tx_packet(volatile packet_t *p) {
00459         safe_irq_disable(MACA);
00460 
00461         BOUND_CHECK(p);
00462 
00463         if(!p) {  PRINTF("tx_packet passed packet 0\n\r"); return; }
00464         if(tx_head == 0) {
00465                 /* start a new queue if empty */
00466                 tx_end = p;
00467                 tx_end->left = 0; tx_end->right = 0;
00468                 tx_head = tx_end; 
00469         } else {
00470                 /* add p to the end of the queue */
00471                 tx_end->left = p;
00472                 p->right = tx_end;
00473                 /* move the queue */
00474                 tx_end = p; tx_end->left = 0;
00475         }
00476 //      print_packets("tx packet");
00477         irq_restore();
00478         if(bit_is_set(*NIPEND, INT_NUM_MACA)) { *INTFRC = (1 << INT_NUM_MACA); } 
00479         if(last_post == NO_POST) { *INTFRC = (1<<INT_NUM_MACA); }
00480         /* if we are in a reception cycle, advance the softclock timeout to now */
00481         if(last_post == RX_POST) { *MACA_SFTCLK = *MACA_CLK + CLK_PER_BYTE; }
00482         return;
00483 }
00484 
00485 void free_all_packets(void) {
00486         volatile int i;
00487         safe_irq_disable(MACA);
00488 
00489         free_head = 0;
00490         for(i=0; i<NUM_PACKETS; i++) {
00491                 free_packet((volatile packet_t *)&(packet_pool[i]));            
00492         }
00493         rx_head = 0; rx_end = 0;
00494         tx_head = 0; tx_end = 0;
00495 
00496         irq_restore();
00497         if(bit_is_set(*NIPEND, INT_NUM_MACA)) { *INTFRC = (1 << INT_NUM_MACA); }
00498 
00499         return;
00500 }
00501 
00502 /* private routines used by driver */
00503                 
00504 void free_tx_head(void) {
00505         volatile packet_t *p;
00506         safe_irq_disable(MACA);
00507 
00508         BOUND_CHECK(tx_head);
00509 
00510         p = tx_head;
00511         tx_head = tx_head->left;
00512         if(tx_head == 0) { tx_end = 0; }
00513         free_packet(p);
00514         
00515 //      print_packets("free tx head");
00516         irq_restore();
00517         if(bit_is_set(*NIPEND, INT_NUM_MACA)) { *INTFRC = (1 << INT_NUM_MACA); }
00518 
00519         return;
00520 }
00521 
00522 void add_to_rx(volatile packet_t *p) {
00523         safe_irq_disable(MACA);
00524 
00525         BOUND_CHECK(p);
00526         
00527         if(!p) {  PRINTF("add_to_rx passed packet 0\n\r"); return; }
00528         p->offset = 1; /* first byte is the length */
00529         if(rx_head == 0) {
00530                 /* start a new queue if empty */
00531                 rx_end = p;
00532                 rx_end->left = 0; rx_end->right = 0;
00533                 rx_head = rx_end; 
00534         } else {
00535                 rx_end->left = p;
00536                 p->right = rx_end;
00537                 rx_end = p; rx_end->left = 0;
00538         }
00539         
00540 //      print_packets("add to rx");
00541         irq_restore();
00542         if(bit_is_set(*NIPEND, INT_NUM_MACA)) { *INTFRC = (1 << INT_NUM_MACA); }
00543 
00544         return;
00545 }
00546 
00547 void insert_at_rx_head(volatile packet_t *p) {
00548         safe_irq_disable(MACA);
00549 
00550         BOUND_CHECK(p);
00551 
00552         if(!p) {  PRINTF("insert_at_rx_head passed packet 0\n\r"); return; }
00553         p->offset = 1; /* first byte is the length */
00554         if(rx_head == 0) {
00555                 /* start a new queue if empty */
00556                 rx_end = p;
00557                 rx_end->left = 0; rx_end->right = 0;
00558                 rx_head = rx_end;
00559         } else {
00560                 rx_head->right = p;
00561                 p->left = rx_head;
00562                 rx_head = p; rx_head->left = 0;
00563         }
00564 
00565 //      print_packets("insert at rx head");
00566         irq_restore();
00567         if(bit_is_set(*NIPEND, INT_NUM_MACA)) { *INTFRC = (1 << INT_NUM_MACA); }
00568 
00569         return;
00570 }
00571 
00572 
00573 void decode_status(void) {
00574         volatile uint32_t code;
00575         
00576         code = get_field(*MACA_STATUS,CODE);
00577         /* PRINTF("status code 0x%x\n\r",code); */
00578         
00579         switch(code)
00580         {
00581         case ABORTED:
00582         {
00583                 PRINTF("maca: aborted\n\r");
00584                 ResumeMACASync();
00585                 break;
00586                 
00587         }
00588         case NOT_COMPLETED:
00589         {
00590                 PRINTF("maca: not completed\n\r");
00591                 ResumeMACASync();
00592                 break;
00593                 
00594         }
00595         case CODE_TIMEOUT:
00596         {
00597                 PRINTF("maca: timeout\n\r");
00598                 ResumeMACASync();
00599                 break;
00600                 
00601         }
00602         case NO_ACK:
00603         {
00604                 PRINTF("maca: no ack\n\r");
00605                 ResumeMACASync();
00606                 break;
00607                 
00608         }
00609         case EXT_TIMEOUT:
00610         {
00611                 PRINTF("maca: ext timeout\n\r");
00612                 ResumeMACASync();
00613                 break;
00614                 
00615         }
00616         case EXT_PND_TIMEOUT:
00617         {
00618                 PRINTF("maca: ext pnd timeout\n\r");
00619                 ResumeMACASync();
00620                 break;
00621         }
00622         case SUCCESS:
00623         {
00624                 //PRINTF("maca: success\n\r");
00625                 ResumeMACASync();
00626                 break;                          
00627         }
00628         default:
00629         {
00630                 PRINTF("status: %x", (unsigned int)*MACA_STATUS);
00631                 ResumeMACASync();
00632                 
00633         }
00634         }
00635 }
00636 
00637 void maca_isr(void) {
00638 
00639 //      print_packets("maca_isr");
00640 
00641         maca_entry++;
00642 
00643         if (bit_is_set(*MACA_STATUS, maca_status_ovr))
00644         { PRINTF("maca overrun\n\r"); }
00645         if (bit_is_set(*MACA_STATUS, maca_status_busy))
00646         { PRINTF("maca busy\n\r"); } 
00647         if (bit_is_set(*MACA_STATUS, maca_status_crc))
00648         { PRINTF("maca crc error\n\r"); }
00649         if (bit_is_set(*MACA_STATUS, maca_status_to))
00650         { PRINTF("maca timeout\n\r"); }
00651 
00652         if (data_indication_irq()) {
00653                 *MACA_CLRIRQ = (1 << maca_irq_di);
00654                 dma_rx->length = *MACA_GETRXLVL - 2; /* packet length does not include FCS */
00655                 dma_rx->lqi = get_lqi();
00656                 dma_rx->rx_time = *MACA_TIMESTAMP;
00657 
00658                 /* check if received packet needs an ack */
00659                 if(prm_mode == AUTOACK && (dma_rx->data[1] & MAC_ACK_REQUEST_FLAG)) {
00660                         /* this wait is necessary to auto-ack */
00661                         volatile uint32_t wait_clk;
00662                         wait_clk = *MACA_CLK + 200;
00663                         while(*MACA_CLK < wait_clk) { continue; }
00664                 }
00665 
00666                 if(maca_rx_callback != 0) { maca_rx_callback(dma_rx); }
00667 
00668                 add_to_rx(dma_rx);
00669                 dma_rx = 0;
00670         }
00671         if (filter_failed_irq()) {
00672                 PRINTF("maca filter failed\n\r");
00673                 ResumeMACASync();
00674                 *MACA_CLRIRQ = (1 << maca_irq_flt);
00675         }
00676         if (checksum_failed_irq()) {
00677                 PRINTF("maca checksum failed\n\r");
00678                 ResumeMACASync();
00679                 *MACA_CLRIRQ = (1 << maca_irq_crc);
00680         }
00681         if (softclock_irq()) {
00682                 *MACA_CLRIRQ = (1 << maca_irq_sftclk);
00683         }
00684         if (poll_irq()) {               
00685                 *MACA_CLRIRQ = (1 << maca_irq_poll);
00686         }
00687         if(action_complete_irq()) {
00688                 /* PRINTF("maca action complete %d\n\r", get_field(*MACA_CONTROL,SEQUENCE)); */
00689                 if(last_post == TX_POST) {
00690                         tx_head->status = get_field(*MACA_STATUS,CODE);
00691 
00692 #if MACA_INSERT_ACK
00693 /* Having sent a message with the acknowledge request flag set the
00694  * MACA hardware will only give a tx success indication if the message
00695  * was acknowledged by the remote node. We need to detect this
00696  * condition and inject an ACK packet into the internal receive stream
00697  * as the higher layers are expecting to see an ACK packet.*/
00698 
00699                         if(tx_head->status == SUCCESS && (tx_head->data[0] & MAC_ACK_REQUEST_FLAG)) {
00700 
00701                                 /* Create the dummy ack packet */
00702 
00703                                 static volatile packet_t *ack_p;
00704                                 if(ack_p = get_free_packet()) {
00705                                         ack_p->length = 3;
00706                                         ack_p->offset = 1;
00707                                         ack_p->data[0] = 3;
00708                                         ack_p->data[1] = 0x02;
00709                                         ack_p->data[2] = 0;
00710                                         ack_p->data[3] = *MACA_TXSEQNR;
00711                                         insert_at_rx_head(ack_p);
00712                                 }
00713 
00714                         }
00715 #endif
00716 
00717                         if(maca_tx_callback != 0) { maca_tx_callback(tx_head); }
00718                         dma_tx = 0;
00719                         free_tx_head();
00720                         last_post = NO_POST;
00721                 }
00722                 ResumeMACASync();
00723                 *MACA_CLRIRQ = (1 << maca_irq_acpl);            
00724         }
00725 
00726         decode_status();
00727 
00728         if (*MACA_IRQ != 0)
00729         { PRINTF("*MACA_IRQ %x\n\r", (unsigned int)*MACA_IRQ); }
00730 
00731         if(tx_head != 0) {
00732                 post_tx();
00733         } else {
00734                 post_receive();
00735         } 
00736 }
00737 
00738 
00739 static uint8_t ram_values[4];
00740 
00741 
00742 void init_phy(void)
00743 {
00744 //  *MACA_TMREN = (1 << maca_tmren_strt) | (1 << maca_tmren_cpl);
00745         *MACA_CLKDIV = MACA_CLOCK_DIV;
00746         *MACA_WARMUP = 0x00180012;
00747         *MACA_EOFDELAY = 0x00000004;
00748         *MACA_CCADELAY = 0x001a0022;
00749         *MACA_TXCCADELAY = 0x00000025;
00750         *MACA_FRAMESYNC0 = 0x000000A7;
00751         *MACA_CLK = 0x00000008;
00752         *MACA_RXACKDELAY = 30;
00753         *MACA_RXEND = 180;
00754         *MACA_TXACKDELAY = 68; 
00755         *MACA_MASKIRQ = ((1 << maca_irq_rst)    | 
00756                          (1 << maca_irq_acpl)   | 
00757                          (1 << maca_irq_cm)     |
00758                          (1 << maca_irq_flt)    | 
00759                          (1 << maca_irq_crc)    | 
00760                          (1 << maca_irq_di)     |
00761                          (1 << maca_irq_sftclk)
00762                 );
00763         *MACA_SLOTOFFSET = 0x00350000;  
00764 }
00765 
00766 void reset_maca(void)
00767 {
00768         volatile uint32_t cnt;
00769         
00770         *MACA_RESET = (1 << maca_reset_rst);
00771         
00772         for(cnt = 0; cnt < 100; cnt++) {};
00773         
00774         *MACA_RESET = (1 << maca_reset_clkon);
00775         
00776         *MACA_CONTROL = maca_ctrl_seq_nop;
00777         
00778         for(cnt = 0; cnt < 400000; cnt++) {};
00779         
00780         /* Clear all interrupts. */
00781         *MACA_CLRIRQ = 0xffff;
00782 }
00783 
00784 
00785 /*
00786         004030c4 <SMAC_InitFlybackSettings>:
00787         4030c4:       4806            ldr     r0, [pc, #24]   (4030e0 <SMAC_InitFlybackSettings+0x1c>) // r0 gets base 0x80009a00
00788                 4030c6:       6881            ldr     r1, [r0, #8]                                             // r1 gets *(0x80009a08)
00789                 4030c8:       4806            ldr     r0, [pc, #24]   (4030e4 <SMAC_InitFlybackSettings+0x20>) // r0 gets 0x0000f7df
00790                 4030ca:       4308            orrs    r0, r1                                                   // or them, r0 has it
00791                 4030cc:       4904            ldr     r1, [pc, #16]   (4030e0 <SMAC_InitFlybackSettings+0x1c>) // r1 gets base 0x80009a00
00792                 4030ce:       6088            str     r0, [r1, #8]     // put r0 into 0x80009a08
00793                 4030d0:       0008            lsls    r0, r1, #0       // r0 gets r1, r0 is the base now
00794                 4030d2:       4905            ldr     r1, [pc, #20]   (4030e8 <SMAC_InitFlybackSettings+0x24>) // r1 gets 0x00ffffff
00795                 4030d4:       60c1            str     r1, [r0, #12]   // put 0x00ffffff into base+12
00796                 4030d6:       0b09            lsrs    r1, r1, #12     // r1 = 0x00ffffff >> 12
00797                 4030d8:       6101            str     r1, [r0, #16]   // put r1 base+16
00798                 4030da:       2110            movs    r1, #16         // r1 gets 16
00799                 4030dc:       6001            str     r1, [r0, #0]    // put r1 in the base
00800                 4030de:       4770            bx      lr              // return
00801                 4030e0:       80009a00        .word   0x80009a00
00802                 4030e4:       0000f7df        .word   0x0000f7df
00803                 4030e8:       00ffffff        .word   0x00ffffff
00804 */
00805 
00806 /* tested and is good */
00807 #define RF_BASE 0x80009a00
00808 void flyback_init(void) {
00809         uint32_t val8, or;
00810         
00811         val8 = *(volatile uint32_t *)(RF_BASE+8);
00812         or = val8 | 0x0000f7df;
00813         *(volatile uint32_t *)(RF_BASE+8) = or;
00814         *(volatile uint32_t *)(RF_BASE+12) = 0x00ffffff;
00815         *(volatile uint32_t *)(RF_BASE+16) = (((uint32_t)0x00ffffff)>>12);
00816         *(volatile uint32_t *)(RF_BASE) = 16;
00817         /* good luck and godspeed */
00818 }
00819 
00820 #define MAX_SEQ1 2
00821 const uint32_t addr_seq1[MAX_SEQ1] = {
00822         0x80003048,      
00823         0x8000304c,
00824 };
00825 
00826 const uint32_t data_seq1[MAX_SEQ1] = {
00827         0x00000f78,     
00828         0x00607707,
00829 };
00830 
00831 
00832 #define MAX_SEQ2 2
00833 const uint32_t addr_seq2[MAX_SEQ2] = {
00834         0x8000a050,      
00835         0x8000a054,      
00836 };
00837 
00838 const uint32_t data_seq2[MAX_SEQ2] = {
00839         0x0000047b,
00840         0x0000007b, 
00841 };
00842 
00843 #define MAX_CAL3_SEQ1 3
00844 const uint32_t addr_cal3_seq1[MAX_CAL3_SEQ1] = { 0x80009400,0x80009a04,0x80009a00, };
00845 const uint32_t data_cal3_seq1[MAX_CAL3_SEQ1] = {0x00020017,0x8185a0a4,0x8c900025, };
00846 
00847 #define MAX_CAL3_SEQ2 2
00848 const uint32_t addr_cal3_seq2[MAX_CAL3_SEQ2] = { 0x80009a00,0x80009a00,};
00849 const uint32_t data_cal3_seq2[MAX_CAL3_SEQ2] = { 0x8c900021,0x8c900027,};
00850 
00851 #define MAX_CAL3_SEQ3 1
00852 const uint32_t addr_cal3_seq3[MAX_CAL3_SEQ3] = { 0x80009a00 };
00853 const uint32_t data_cal3_seq3[MAX_CAL3_SEQ3] = { 0x8c900000 };
00854 
00855 #define MAX_CAL5 4
00856 const uint32_t addr_cal5[MAX_CAL5] = { 
00857         0x80009400,  
00858         0x8000a050,       
00859         0x8000a054,  
00860         0x80003048,
00861 };
00862 const uint32_t data_cal5[MAX_CAL5] = {
00863         0x00000017,
00864         0x00000000,            
00865         0x00000000,
00866         0x00000f00,
00867 };
00868 
00869 #define MAX_DATA 43
00870 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 };
00871 
00872 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 };
00873 
00874 void maca_off(void) {
00875         disable_irq(MACA);
00876         /* turn off the radio regulators */
00877         reg(0x80003048) =  0x00000f00;
00878         /* hold the maca in reset */
00879         maca_reset = maca_reset_rst;  
00880 }
00881 
00882 void maca_on(void) {
00883         /* turn the radio regulators back on */
00884         reg(0x80003048) =  0x00000f78; 
00885         /* reinitialize the phy */
00886         reset_maca();
00887         init_phy();
00888         
00889         enable_irq(MACA);
00890         *INTFRC = (1 << INT_NUM_MACA);
00891 }
00892 
00893 /* initialized with 0x4c */
00894 uint8_t ctov[16] = {
00895         0x0b,
00896         0x0b,
00897         0x0b,
00898         0x0a,
00899         0x0d,
00900         0x0d,
00901         0x0c,
00902         0x0c,
00903         0x0f,
00904         0x0e,
00905         0x0e,
00906         0x0e,
00907         0x11,
00908         0x10,
00909         0x10,
00910         0x0f,
00911 };
00912 
00913 /* get_ctov thanks to Umberto */
00914 
00915 #define _INIT_CTOV_WORD_1       0x00dfbe77
00916 #define _INIT_CTOV_WORD_2       0x023126e9
00917 uint8_t get_ctov( uint32_t r0, uint32_t r1 )
00918 {
00919 
00920         r0 = r0 * _INIT_CTOV_WORD_1;
00921         r0 += ( r1 << 22 );
00922         r0 += _INIT_CTOV_WORD_2;
00923 
00924         r0 = (uint32_t)(((int32_t)r0) >> 25);
00925 
00926         return (uint8_t)r0;
00927 }
00928 
00929 
00930 /* radio_init has been tested to be good */
00931 void radio_init(void) {
00932         volatile uint32_t i;
00933         /* sequence 1 */
00934         for(i=0; i<MAX_SEQ1; i++) {
00935                 *(volatile uint32_t *)(addr_seq1[i]) = data_seq1[i];
00936         }
00937         /* seq 1 delay */
00938         for(i=0; i<0x161a8; i++) { continue; }
00939         /* sequence 2 */
00940         for(i=0; i<MAX_SEQ2; i++) {
00941                 *(volatile uint32_t *)(addr_seq2[i]) = data_seq2[i];
00942         }
00943         /* modem val */
00944         *(volatile uint32_t *)0x80009000 = 0x80050100;
00945         /* cal 3 seq 1*/
00946         for(i=0; i<MAX_CAL3_SEQ1; i++) {
00947                 *(volatile uint32_t *)(addr_cal3_seq1[i]) = data_cal3_seq1[i];
00948         }
00949         /* cal 3 delay */
00950         for(i=0; i<0x11194; i++) { continue; }
00951         /* cal 3 seq 2*/
00952         for(i=0; i<MAX_CAL3_SEQ2; i++) {
00953                 *(volatile uint32_t *)(addr_cal3_seq2[i]) = data_cal3_seq2[i];
00954         }
00955         /* cal 3 delay */
00956         for(i=0; i<0x11194; i++) { continue; }
00957         /* cal 3 seq 3*/
00958         for(i=0; i<MAX_CAL3_SEQ3; i++) {
00959                 *(volatile uint32_t *)(addr_cal3_seq3[i]) = data_cal3_seq3[i];
00960         }
00961         /* cal 5 */
00962         for(i=0; i<MAX_CAL5; i++) {
00963                 *(volatile uint32_t *)(addr_cal5[i]) = data_cal5[i];
00964         }
00965         /*reg replacment */
00966         for(i=0; i<MAX_DATA; i++) {
00967                 *(volatile uint32_t *)(addr_reg_rep[i]) = data_reg_rep[i];
00968         }
00969         
00970         PRINTF("initfromflash\n\r");
00971 
00972         *(volatile uint32_t *)(0x80003048) = 0x00000f04; /* bypass the buck */
00973         for(i=0; i<0x161a8; i++) { continue; } /* wait for the bypass to take */
00974 //      while((((*(volatile uint32_t *)(0x80003018))>>17) & 1) !=1) { continue; } /* wait for the bypass to take */
00975         *(volatile uint32_t *)(0x80003048) = 0x00000fa4; /* start the regulators */
00976         for(i=0; i<0x161a8; i++) { continue; } /* wait for the bypass to take */
00977 
00978         init_from_flash(0x1F000);
00979 
00980         PRINTF("ram_values:\n\r");
00981         for(i=0; i<4; i++) {
00982                 PRINTF("  0x%02x\n\r",ram_values[i]);
00983         }
00984 
00985         PRINTF("radio_init: ctov parameter 0x%02x\n\r",ram_values[3]);
00986         for(i=0; i<16; i++) {
00987                 ctov[i] = get_ctov(i,ram_values[3]);
00988                 PRINTF("radio_init: ctov[%d] = 0x%02x\n\r",(int)i,ctov[i]);
00989         }
00990 
00991 
00992 }
00993 
00994 const uint32_t PSMVAL[19] = {
00995         0x0000080f,
00996         0x0000080f,
00997         0x0000080f,
00998         0x0000080f,
00999         0x0000081f,
01000         0x0000081f,
01001         0x0000081f,
01002         0x0000080f,
01003         0x0000080f,
01004         0x0000080f,
01005         0x0000001f,
01006         0x0000000f,
01007         0x0000000f,
01008         0x00000816,
01009         0x0000001b,
01010         0x0000000b,
01011         0x00000802,
01012         0x00000817,
01013         0x00000003,
01014 };
01015 
01016 const uint32_t PAVAL[19] = {
01017         0x000022c0,
01018         0x000022c0,
01019         0x000022c0,
01020         0x00002280,
01021         0x00002303,
01022         0x000023c0,
01023         0x00002880,
01024         0x000029f0,
01025         0x000029f0,
01026         0x000029f0,
01027         0x000029c0,
01028         0x00002bf0,
01029         0x000029f0,
01030         0x000028a0,
01031         0x00002800,
01032         0x00002ac0,
01033         0x00002880,
01034         0x00002a00,
01035         0x00002b00,
01036 };
01037 
01038 const uint32_t AIMVAL[19] = {
01039         0x000123a0,
01040         0x000163a0,
01041         0x0001a3a0,
01042         0x0001e3a0,
01043         0x000223a0,
01044         0x000263a0,
01045         0x0002a3a0,
01046         0x0002e3a0,
01047         0x000323a0,
01048         0x000363a0,
01049         0x0003a3a0,
01050         0x0003a3a0,
01051         0x0003e3a0,
01052         0x000423a0,
01053         0x000523a0,
01054         0x000423a0,
01055         0x0004e3a0,
01056         0x0004e3a0,
01057         0x0004e3a0,
01058 };
01059 
01060 #define RF_REG 0x80009400
01061 void set_demodulator_type(uint8_t demod) {
01062         uint32_t val = reg(RF_REG);
01063         if(demod == DEMOD_NCD) {
01064                 val = (val & ~1);
01065         } else {
01066                 val = (val | 1);
01067         }
01068         reg(RF_REG) = val;
01069 }
01070 
01071 /* tested and seems to be good */
01072 #define ADDR_POW1 0x8000a014
01073 #define ADDR_POW2 ADDR_POW1 + 12
01074 #define ADDR_POW3 ADDR_POW1 + 64
01075 void set_power(uint8_t power) {
01076         safe_irq_disable(MACA);
01077 
01078         reg(ADDR_POW1) = PSMVAL[power];
01079 
01080 /* see http://devl.org/pipermail/mc1322x/2009-October/000065.html */
01081 /*      reg(ADDR_POW2) = (ADDR_POW1>>18) | PAVAL[power]; */
01082 #ifdef USE_PA
01083         reg(ADDR_POW2) = 0xffffdfff & PAVAL[power]; /* single port */
01084 #else
01085         reg(ADDR_POW2) = 0x00002000 | PAVAL[power]; /* dual port */
01086 #endif
01087 
01088         reg(ADDR_POW3) = AIMVAL[power];
01089         
01090         irq_restore();
01091         if(bit_is_set(*NIPEND, INT_NUM_MACA)) { *INTFRC = (1 << INT_NUM_MACA); }
01092 
01093 }
01094 
01095 const uint8_t VCODivI[16] = {
01096         0x2f,
01097         0x2f,
01098         0x2f,
01099         0x2f,
01100         0x2f,
01101         0x2f,
01102         0x2f,
01103         0x2f,
01104         0x2f,
01105         0x30,
01106         0x30,
01107         0x30,
01108         0x30,
01109         0x30,
01110         0x30,
01111         0x30,
01112 };
01113 
01114 const uint32_t VCODivF[16] = {
01115         0x00355555,
01116         0x006aaaaa,
01117         0x00a00000,
01118         0x00d55555,
01119         0x010aaaaa,
01120         0x01400000,
01121         0x01755555,
01122         0x01aaaaaa,
01123         0x01e00000,
01124         0x00155555,
01125         0x004aaaaa,
01126         0x00800000,
01127         0x00b55555,
01128         0x00eaaaaa,
01129         0x01200000,
01130         0x01555555,             
01131 };
01132 
01133 /* tested good */
01134 #define ADDR_CHAN1 0x80009800
01135 #define ADDR_CHAN2 (ADDR_CHAN1+12)
01136 #define ADDR_CHAN3 (ADDR_CHAN1+16)
01137 #define ADDR_CHAN4 (ADDR_CHAN1+48)
01138 void set_channel(uint8_t chan) {
01139         volatile uint32_t tmp;
01140         safe_irq_disable(MACA);
01141 
01142         tmp = reg(ADDR_CHAN1);
01143         tmp = tmp & 0xbfffffff;
01144         reg(ADDR_CHAN1) = tmp;
01145 
01146         reg(ADDR_CHAN2) = VCODivI[chan];
01147         reg(ADDR_CHAN3) = VCODivF[chan];
01148 
01149         tmp = reg(ADDR_CHAN4);
01150         tmp = tmp | 2;
01151         reg(ADDR_CHAN4) = tmp;
01152 
01153         tmp = reg(ADDR_CHAN4);
01154         tmp = tmp | 4;
01155         reg(ADDR_CHAN4) = tmp;
01156 
01157         tmp = tmp & 0xffffe0ff;
01158         tmp = tmp | (((ctov[chan])<<8)&0x1F00);
01159         reg(ADDR_CHAN4) = tmp;
01160         /* duh! */
01161         irq_restore();
01162         if(bit_is_set(*NIPEND, INT_NUM_MACA)) { *INTFRC = (1 << INT_NUM_MACA); }
01163 }
01164 
01165 uint8_t (*get_lqi)(void) = (void *) 0x0000e04d;
01166 
01167 #define ROM_END 0x0013ffff
01168 #define ENTRY_EOF 0x00000e0f
01169 /* processes up to 4 words of initialization entries */
01170 /* returns the number of words processed */
01171 uint32_t exec_init_entry(volatile uint32_t *entries, uint8_t *valbuf) 
01172 {
01173         volatile uint32_t i;
01174         if(entries[0] <= ROM_END) {
01175                 if (entries[0] == 0) {
01176                         /* do delay command*/
01177                         PRINTF("init_entry: delay 0x%08x\n\r", (unsigned int)entries[1]);
01178                         for(i=0; i<entries[1]; i++) { continue; }
01179                         return 2;
01180                 } else if (entries[0] == 1) {
01181                         /* do bit set/clear command*/
01182                         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]);
01183                         reg(entries[2]) = (reg(entries[2]) & ~entries[1]) | (entries[3] & entries[1]);
01184                         return 4;
01185                 } else if ((entries[0] >= 16) &&
01186                            (entries[0] < 0xfff1)) {
01187                         /* store bytes in valbuf */
01188                         PRINTF("init_entry: store in valbuf 0x%02x position %d\n\r", 
01189                                (unsigned int)entries[1],
01190                                (unsigned int)(entries[0]>>4)-1);
01191                         valbuf[(entries[0]>>4)-1] = entries[1];
01192                         return 2;
01193                 } else if (entries[0] == ENTRY_EOF) {
01194                         PRINTF("init_entry: eof ");
01195                         return 0;
01196                 } else {
01197                         /* invalid command code */
01198                         PRINTF("init_entry: invaild code 0x%08x\n\r",(unsigned int)entries[0]);
01199                         return 0;
01200                 }
01201         } else { /* address isn't in ROM space */   
01202                  /* do store value in address command  */
01203                 PRINTF("init_entry: address value pair - *0x%08x = 0x%08x\n\r",
01204                        (unsigned int)entries[0],
01205                        (unsigned int)entries[1]);
01206                 reg(entries[0]) = entries[1];
01207                 return 2;
01208         }
01209 }
01210 
01211 
01212 #define FLASH_INIT_MAGIC 0x00000abc
01213 uint32_t init_from_flash(uint32_t addr) {
01214         nvmType_t type=0;
01215         nvmErr_t err;   
01216         volatile uint32_t buf[8];
01217         volatile uint32_t len;
01218         volatile uint32_t i=0,j;
01219 
01220         err = nvm_detect(gNvmInternalInterface_c, &type);
01221         PRINTF("nvm_detect returned type 0x%08x err 0x%02x\n\r", type, err);
01222                 
01223         nvm_setsvar(0);
01224         err = nvm_read(gNvmInternalInterface_c, type, (uint8_t *)buf, addr, 8);
01225         i+=8;
01226         PRINTF("nvm_read returned: 0x%02x\n\r",err);
01227         
01228         for(j=0; j<4; j++) {
01229                 PRINTF("0x%08x\n\r",(unsigned int)buf[j]);
01230         }
01231 
01232         if(buf[0] == FLASH_INIT_MAGIC) {
01233                 len = buf[1] & 0x0000ffff;
01234                 while(i < (len-4)) {
01235                         err = nvm_read(gNvmInternalInterface_c, type, (uint8_t *)buf, addr+i, 32);
01236                         i += 4*exec_init_entry(buf, ram_values);
01237                 }
01238         } else {
01239                 i = 0;
01240         }
01241         nvm_setsvar(1);
01242         return i;
01243 }
01244 
01245 /* 
01246  * Do the ABORT-Wait-NOP-Wait sequence in order to prevent MACA malfunctioning.
01247  * This seqeunce is synchronous and no interrupts should be triggered when it is done.
01248  */
01249 void ResumeMACASync(void)
01250 { 
01251   volatile uint32_t clk, TsmRxSteps, LastWarmupStep, LastWarmupData, LastWarmdownStep, LastWarmdownData;
01252 //  bool_t tmpIsrStatus;
01253   volatile uint32_t i;
01254   safe_irq_disable(MACA);
01255 
01256 //  ITC_DisableInterrupt(gMacaInt_c);  
01257 //  AppInterrupts_ProtectFromMACAIrq(tmpIsrStatus); <- Original from MAC code, but not sure how is it implemented
01258 
01259   /* Manual TSM modem shutdown */
01260 
01261   /* read TSM_RX_STEPS */
01262   TsmRxSteps = (*((volatile uint32_t *)(0x80009204)));
01263  
01264   /* isolate the RX_WU_STEPS */
01265   /* shift left to align with 32-bit addressing */
01266   LastWarmupStep = (TsmRxSteps & 0x1f) << 2;
01267   /* Read "current" TSM step and save this value for later */
01268   LastWarmupData = (*((volatile uint32_t *)(0x80009300 + LastWarmupStep)));
01269 
01270   /* isolate the RX_WD_STEPS */
01271   /* right-shift bits down to bit 0 position */
01272   /* left-shift to align with 32-bit addressing */
01273   LastWarmdownStep = ((TsmRxSteps & 0x1f00) >> 8) << 2;
01274   /* write "last warmdown data" to current TSM step to shutdown rx */
01275   LastWarmdownData = (*((volatile uint32_t *)(0x80009300 + LastWarmdownStep)));
01276   (*((volatile uint32_t *)(0x80009300 + LastWarmupStep))) = LastWarmdownData;
01277 
01278   /* Abort */
01279   MACA_WRITE(maca_control, 1);
01280   
01281   /* Wait ~8us */
01282   for (clk = maca_clk, i = 0; maca_clk - clk < 3 && i < 300; i++)
01283     ;
01284  
01285   /* NOP */
01286   MACA_WRITE(maca_control, 0);  
01287   
01288   /* Wait ~8us */  
01289   for (clk = maca_clk, i = 0; maca_clk - clk < 3 && i < 300; i++)
01290     ;
01291    
01292 
01293   /* restore original "last warmup step" data to TSM (VERY IMPORTANT!!!) */
01294   (*((volatile uint32_t *)(0x80009300 + LastWarmupStep))) = LastWarmupData;
01295 
01296   
01297   
01298   /* Clear all MACA interrupts - we should have gotten the ABORT IRQ */
01299   MACA_WRITE(maca_clrirq, 0xFFFF);
01300 
01301 //  AppInterrupts_UnprotectFromMACAIrq(tmpIsrStatus);  <- Original from MAC code, but not sure how is it implemented
01302 //  ITC_EnableInterrupt(gMacaInt_c);
01303 //  enable_irq(MACA);
01304   irq_restore();
01305 
01306 }