Contiki 2.6
|
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 }