Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
SimpleSpirit1.cpp
00001 /*** Mbed Includes ***/ 00002 #include "SimpleSpirit1.h" 00003 #include "radio_spi.h" 00004 00005 #define SPIRIT_GPIO_IRQ (SPIRIT_GPIO_3) 00006 00007 static uint16_t last_state; 00008 #define SPIRIT1_STATUS() ((last_state = (uint16_t)refresh_state()) & SPIRIT1_STATE_STATEBITS) 00009 00010 #define XO_ON (0x1) 00011 00012 #define BUSYWAIT_UNTIL(cond, millisecs) \ 00013 do { \ 00014 uint32_t start = us_ticker_read(); \ 00015 while (!(cond) && ((us_ticker_read() - start) < ((uint32_t)millisecs)*1000U)); \ 00016 } while(0) 00017 00018 #define st_lib_spirit_irqs SpiritIrqs 00019 00020 #define STATE_TIMEOUT (100) 00021 00022 // betzw: switching force & back from standby is on some devices quite unstable 00023 #define USE_STANDBY_STATE 00024 00025 /*** Class Implementation ***/ 00026 /** Static Class Variables **/ 00027 SimpleSpirit1 *SimpleSpirit1::_singleton = NULL; 00028 00029 /** Constructor **/ 00030 SimpleSpirit1::SimpleSpirit1(PinName mosi, PinName miso, PinName sclk, 00031 PinName irq, PinName cs, PinName sdn, 00032 PinName led) : 00033 _spi(mosi, miso, sclk), 00034 _irq(irq), 00035 _chip_select(cs), 00036 _shut_down(sdn), 00037 _led(led), 00038 _current_irq_callback(), 00039 _rx_receiving_timeout() 00040 { 00041 } 00042 00043 /** Init Function **/ 00044 void SimpleSpirit1::init() { 00045 /* reset irq disable counter and irq callback & disable irq */ 00046 _nr_of_irq_disables = 0; 00047 disable_spirit_irq(); 00048 00049 /* unselect chip */ 00050 chip_unselect(); 00051 00052 /* configure spi */ 00053 _spi.format(8, 0); /* 8-bit, mode = 0, [order = SPI_MSB] only available in mbed3 */ 00054 _spi.frequency(10000000); // 10MHz (i.e. max speed allowed for Spirit1) 00055 00056 /* install irq handler */ 00057 _irq.mode(PullUp); 00058 _irq.fall(Callback<void()>(this, &SimpleSpirit1::IrqHandler)); 00059 00060 /* init cube vars */ 00061 spirit_on = OFF; 00062 last_rssi = 0 ; //MGR 00063 last_sqi = 0 ; //MGR 00064 00065 /* set frequencies */ 00066 radio_set_xtal_freq(XTAL_FREQUENCY); 00067 mgmt_set_freq_base((uint32_t)BASE_FREQUENCY); 00068 00069 /* restart board */ 00070 enter_shutdown(); 00071 exit_shutdown(); 00072 00073 /* soft core reset */ 00074 cmd_strobe(SPIRIT1_STROBE_SRES); 00075 00076 /* Configures the SPIRIT1 radio part */ 00077 SRadioInit x_radio_init = { 00078 XTAL_OFFSET_PPM, 00079 (uint32_t)BASE_FREQUENCY, 00080 (uint32_t)CHANNEL_SPACE, 00081 CHANNEL_NUMBER, 00082 MODULATION_SELECT, 00083 DATARATE, 00084 (uint32_t)FREQ_DEVIATION, 00085 (uint32_t)BANDWIDTH 00086 }; 00087 radio_init(&x_radio_init); 00088 radio_set_pa_level_dbm(0,POWER_DBM); 00089 radio_set_pa_level_max_index(0); 00090 00091 /* Configures the SPIRIT1 packet handler part*/ 00092 PktBasicInit x_basic_init = { 00093 PREAMBLE_LENGTH, 00094 SYNC_LENGTH, 00095 SYNC_WORD, 00096 LENGTH_TYPE, 00097 LENGTH_WIDTH, 00098 CRC_MODE, 00099 CONTROL_LENGTH, 00100 EN_ADDRESS, 00101 EN_FEC, 00102 EN_WHITENING 00103 }; 00104 pkt_basic_init(&x_basic_init); 00105 00106 /* Enable the following interrupt sources, routed to GPIO */ 00107 irq_de_init(NULL); 00108 irq_clear_status(); 00109 irq_set_status(TX_DATA_SENT , S_ENABLE); 00110 irq_set_status(RX_DATA_READY ,S_ENABLE); 00111 irq_set_status(RX_DATA_DISC , S_ENABLE); 00112 irq_set_status(VALID_SYNC , S_ENABLE); 00113 irq_set_status(TX_FIFO_ERROR , S_ENABLE); 00114 irq_set_status(RX_FIFO_ERROR , S_ENABLE); 00115 #ifndef RX_FIFO_THR_WA 00116 irq_set_status(TX_FIFO_ALMOST_EMPTY , S_ENABLE); 00117 irq_set_status(RX_FIFO_ALMOST_FULL , S_ENABLE); 00118 #endif // !RX_FIFO_THR_WA 00119 00120 /* Configure Spirit1 */ 00121 radio_persistent_rx(S_ENABLE); 00122 qi_set_sqi_threshold(SQI_TH_0); 00123 qi_sqi_check(S_ENABLE); 00124 qi_set_rssi_threshold_dbm(CCA_THRESHOLD); 00125 timer_set_rx_timeout_stop_condition(SQI_ABOVE_THRESHOLD); 00126 timer_set_infinite_rx_timeout(); 00127 radio_afc_freeze_on_sync(S_ENABLE); 00128 calibration_rco(S_ENABLE); 00129 00130 spirit_on = OFF; 00131 CLEAR_TXBUF(); 00132 CLEAR_RXBUF(); 00133 _spirit_tx_started = false; 00134 _is_receiving = false; 00135 00136 /* Configure the radio to route the IRQ signal to its GPIO 3 */ 00137 SGpioInit x_gpio_init = { 00138 SPIRIT_GPIO_IRQ, 00139 SPIRIT_GPIO_MODE_DIGITAL_OUTPUT_LP , 00140 SPIRIT_GPIO_DIG_OUT_IRQ 00141 }; 00142 spirit_gpio_init(&x_gpio_init); 00143 00144 /* Setup CSMA/CA */ 00145 CsmaInit x_csma_init = { 00146 S_ENABLE, // enable persistent mode 00147 TBIT_TIME_64 , // Tcca time 00148 TCCA_TIME_3 , // Lcca length 00149 3, // max nr of backoffs (<8) 00150 1, // BU counter seed 00151 8 // BU prescaler 00152 }; 00153 csma_ca_init(&x_csma_init); 00154 00155 #ifdef USE_STANDBY_STATE 00156 /* Puts the SPIRIT1 in STANDBY mode (125us -> rx/tx) */ 00157 cmd_strobe(SPIRIT1_STROBE_STANDBY); 00158 #endif // USE_STANDBY_STATE 00159 } 00160 00161 static volatile int tx_fifo_remaining = 0; // to be used in irq handler 00162 static volatile int tx_buffer_pos = 0; // to be used in irq handler 00163 const volatile uint8_t *tx_fifo_buffer = NULL; // to be used in irq handler 00164 int SimpleSpirit1::send(const void *payload, unsigned int payload_len) { 00165 /* Checks if the payload length is supported */ 00166 if(payload_len > MAX_PACKET_LEN) { 00167 return RADIO_TX_ERR; 00168 } 00169 00170 disable_spirit_irq(); 00171 00172 BUSYWAIT_UNTIL(SPIRIT1_STATUS() == SPIRIT1_STATE_RX, STATE_TIMEOUT); 00173 #ifndef NDEBUG 00174 if((last_state & SPIRIT1_STATE_STATEBITS) != SPIRIT1_STATE_RX) { 00175 debug("\n\rAssert failed in: %s (%d): state=%x\n\r", __func__, __LINE__, last_state>>1); 00176 } 00177 #endif 00178 00179 /* Reset State to Ready */ 00180 set_ready_state(); 00181 00182 cmd_strobe(SPIRIT1_STROBE_FTX); // flush TX FIFO buffer 00183 00184 #ifndef NDEBUG 00185 debug_if(!(linear_fifo_read_num_elements_tx_fifo() == 0), "\n\rAssert failed in: %s (%d)\n\r", __func__, __LINE__); 00186 #endif 00187 00188 pkt_basic_set_payload_length(payload_len); // set desired payload len 00189 00190 csma_ca_state(S_ENABLE); // enable CSMA/CA 00191 00192 /* Init buffer & number of bytes to be send */ 00193 tx_fifo_remaining = payload_len; 00194 tx_fifo_buffer = (const uint8_t*)payload; 00195 00196 int8_t fifo_available = SPIRIT_MAX_FIFO_LEN; // fill-up whole fifo 00197 int8_t to_send = (tx_fifo_remaining > fifo_available) ? fifo_available : tx_fifo_remaining; 00198 00199 tx_fifo_remaining -= to_send; 00200 00201 /* Fill FIFO Buffer */ 00202 if(to_send > 0) { 00203 spi_write_linear_fifo(to_send, (uint8_t*)&tx_fifo_buffer[0]); 00204 } 00205 00206 tx_buffer_pos = to_send; 00207 _spirit_tx_started = true; 00208 00209 enable_spirit_irq(); 00210 00211 /* Start transmitting */ 00212 cmd_strobe(SPIRIT1_STROBE_TX); 00213 00214 while(tx_fifo_remaining != 0); // wait until not everything is yet send (evtl. by irq handler) 00215 00216 BUSYWAIT_UNTIL(!_spirit_tx_started, STATE_TIMEOUT); 00217 #ifdef HEAVY_DEBUG 00218 debug("\n\r%s (%d): state=%x, _spirit_tx_started=%d\n\r", __func__, __LINE__, SPIRIT1_STATUS()>>1, _spirit_tx_started); 00219 #endif 00220 00221 _spirit_tx_started = false; // in case of state timeout 00222 00223 csma_ca_state(S_DISABLE); // disable CSMA/CA 00224 00225 cmd_strobe(SPIRIT1_STROBE_RX); // Return to RX state 00226 00227 return RADIO_TX_OK; 00228 } 00229 00230 /** Set Ready State **/ 00231 void SimpleSpirit1::set_ready_state(void) { 00232 uint16_t state; 00233 00234 disable_spirit_irq(); 00235 00236 _spirit_tx_started = false; 00237 _is_receiving = false; 00238 stop_rx_timeout(); 00239 00240 cmd_strobe(SPIRIT1_STROBE_FRX); 00241 CLEAR_RXBUF(); 00242 CLEAR_TXBUF(); 00243 00244 state = SPIRIT1_STATUS(); 00245 if(state == SPIRIT1_STATE_STANDBY) { 00246 cmd_strobe(SPIRIT1_STROBE_READY); 00247 } else if(state == SPIRIT1_STATE_RX) { 00248 cmd_strobe(SPIRIT1_STROBE_SABORT); 00249 } else if(state != SPIRIT1_STATE_READY) { 00250 #ifndef NDEBUG 00251 debug("\n\rAssert failed in: %s (%d): state=%x\n\r", __func__, __LINE__, state>>1); 00252 #endif 00253 } 00254 00255 BUSYWAIT_UNTIL((SPIRIT1_STATUS() == SPIRIT1_STATE_READY) && ((last_state & XO_ON) == XO_ON), STATE_TIMEOUT); 00256 if(last_state != (SPIRIT1_STATE_READY | XO_ON)) { 00257 error("\n\rSpirit1: failed to become ready (%x) => pls. reset!\n\r", last_state); 00258 enable_spirit_irq(); 00259 return; 00260 } 00261 00262 irq_clear_status(); 00263 00264 enable_spirit_irq(); 00265 } 00266 00267 int SimpleSpirit1::off(void) { 00268 if(spirit_on == ON) { 00269 /* Disables the mcu to get IRQ from the SPIRIT1 */ 00270 disable_spirit_irq(); 00271 00272 /* first stop rx/tx */ 00273 set_ready_state(); 00274 00275 #ifdef USE_STANDBY_STATE 00276 /* Puts the SPIRIT1 in STANDBY */ 00277 cmd_strobe(SPIRIT1_STROBE_STANDBY); 00278 BUSYWAIT_UNTIL(SPIRIT1_STATUS() == SPIRIT1_STATE_STANDBY, STATE_TIMEOUT); 00279 if((last_state & SPIRIT1_STATE_STATEBITS) != SPIRIT1_STATE_STANDBY) { 00280 error("\n\rSpirit1: failed to enter standby (%x)\n\r", last_state>>1); 00281 return 1; 00282 } 00283 #endif // USE_STANDBY_STATE 00284 00285 spirit_on = OFF; 00286 _nr_of_irq_disables = 1; 00287 } 00288 return 0; 00289 } 00290 00291 int SimpleSpirit1::on(void) { 00292 if(spirit_on == OFF) { 00293 set_ready_state(); 00294 00295 /* now we go to Rx */ 00296 cmd_strobe(SPIRIT1_STROBE_RX); 00297 00298 BUSYWAIT_UNTIL(SPIRIT1_STATUS() == SPIRIT1_STATE_RX, STATE_TIMEOUT); 00299 if((last_state & SPIRIT1_STATE_STATEBITS) != SPIRIT1_STATE_RX) { 00300 error("\n\rSpirit1: failed to enter rx (%x) => retry\n\r", last_state>>1); 00301 } 00302 00303 /* Enables the mcu to get IRQ from the SPIRIT1 */ 00304 spirit_on = ON; 00305 #ifndef NDEBUG 00306 debug_if(!(_nr_of_irq_disables == 1), "\n\rAssert failed in: %s (%d)\n\r", __func__, __LINE__); 00307 #endif 00308 enable_spirit_irq(); 00309 } 00310 00311 #ifndef NDEBUG 00312 if(SPIRIT1_STATUS() != SPIRIT1_STATE_RX) { 00313 debug("\n\rAssert failed in: %s (%d): state=%x\n\r", __func__, __LINE__, last_state>>1); 00314 } 00315 #endif 00316 00317 return 0; 00318 } 00319 00320 uint8_t SimpleSpirit1::refresh_state(void) { 00321 uint8_t mcstate; 00322 00323 SpiritSpiReadRegisters(MC_STATE0_BASE, 1, &mcstate); 00324 00325 return mcstate; 00326 } 00327 00328 int SimpleSpirit1::read(void *buf, unsigned int bufsize) 00329 { 00330 disable_spirit_irq(); 00331 00332 /* Checks if the RX buffer is empty */ 00333 if(IS_RXBUF_EMPTY()) { 00334 #ifndef NDEBUG 00335 debug("\n\rBuffer is empty\n\r"); 00336 #endif 00337 set_ready_state(); 00338 00339 cmd_strobe(SPIRIT1_STROBE_RX); 00340 BUSYWAIT_UNTIL(SPIRIT1_STATUS() == SPIRIT1_STATE_RX, STATE_TIMEOUT); 00341 enable_spirit_irq(); 00342 return 0; 00343 } 00344 00345 if(bufsize < spirit_rx_len) { 00346 enable_spirit_irq(); 00347 00348 /* If buf has the correct size */ 00349 #ifndef NDEBUG 00350 debug("\n\rTOO SMALL BUF\n\r"); 00351 #endif 00352 return 0; 00353 } else { 00354 /* Copies the packet received */ 00355 memcpy(buf, spirit_rx_buf, spirit_rx_len); 00356 00357 bufsize = spirit_rx_len; 00358 CLEAR_RXBUF(); 00359 00360 enable_spirit_irq(); 00361 00362 return bufsize; 00363 } 00364 00365 } 00366 00367 int SimpleSpirit1::channel_clear(void) 00368 { 00369 float rssi_value; 00370 /* Local variable used to memorize the SPIRIT1 state */ 00371 uint8_t spirit_state = ON; 00372 00373 if(spirit_on == OFF) { 00374 /* Wakes up the SPIRIT1 */ 00375 on(); 00376 spirit_state = OFF; 00377 } 00378 00379 #ifndef NDEBUG 00380 if(SPIRIT1_STATUS() != SPIRIT1_STATE_RX) { 00381 debug("\n\rAssert failed in: %s (%d): state=%x\n\r", __func__, __LINE__, last_state>>1); 00382 } 00383 #endif 00384 00385 disable_spirit_irq(); 00386 00387 /* Reset State to Ready */ 00388 set_ready_state(); 00389 00390 /* Stores the RSSI value */ 00391 rssi_value = qi_get_rssi_dbm(); 00392 00393 enable_spirit_irq(); 00394 00395 /* Puts the SPIRIT1 in its previous state */ 00396 if(spirit_state==OFF) { 00397 off(); 00398 #ifndef NDEBUG 00399 #ifdef USE_STANDBY_STATE 00400 if(SPIRIT1_STATUS() != SPIRIT1_STATE_STANDBY) { 00401 #else 00402 if(SPIRIT1_STATUS() != SPIRIT1_STATE_READY) { 00403 #endif 00404 debug("\n\rAssert failed in: %s (%d): state=%x\n\r", __func__, __LINE__, last_state>>1); 00405 } 00406 #endif 00407 } else { 00408 disable_spirit_irq(); 00409 00410 set_ready_state(); 00411 00412 cmd_strobe(SPIRIT1_STROBE_RX); 00413 BUSYWAIT_UNTIL(SPIRIT1_STATUS() == SPIRIT1_STATE_RX, STATE_TIMEOUT); 00414 if((last_state & SPIRIT1_STATE_STATEBITS) != SPIRIT1_STATE_RX) { 00415 error("\n\rSpirit1: (#2) failed to enter rx (%x) => retry\n\r", last_state>>1); 00416 } 00417 00418 enable_spirit_irq(); 00419 00420 #ifndef NDEBUG 00421 if(SPIRIT1_STATUS() != SPIRIT1_STATE_RX) { 00422 debug("\n\rAssert failed in: %s (%d): state=%x\n\r", __func__, __LINE__, last_state>>1); 00423 } 00424 #endif 00425 } 00426 00427 /* Checks the RSSI value with the threshold */ 00428 if(rssi_value<CCA_THRESHOLD) { 00429 return 0; 00430 } else { 00431 return 1; 00432 } 00433 } 00434 00435 int SimpleSpirit1::get_pending_packet(void) 00436 { 00437 return !IS_RXBUF_EMPTY(); 00438 } 00439 00440 /** Spirit Irq Callback **/ 00441 /* betzw - TODO: use threaded interrupt handling when `MBED_CONF_RTOS_PRESENT` is defined (see `atmel-rf-driver`) */ 00442 void SimpleSpirit1::IrqHandler() { 00443 st_lib_spirit_irqs x_irq_status; 00444 00445 /* get interrupt source from radio */ 00446 irq_get_status(&x_irq_status); 00447 00448 /* The IRQ_TX_DATA_SENT notifies the packet received. Puts the SPIRIT1 in RX */ 00449 if(x_irq_status.IRQ_TX_DATA_SENT) { 00450 #ifdef DEBUG_IRQ 00451 uint32_t *tmp = (uint32_t*)&x_irq_status; 00452 debug_if(!_spirit_tx_started, "\n\rAssert failed in: %s (%d)\n\r", __func__, __LINE__); 00453 debug_if(!((*tmp) & IRQ_TX_DATA_SENT_MASK), "\n\rAssert failed in: %s (%d)\n\r", __func__, __LINE__); 00454 debug_if(tx_fifo_remaining != 0, "\n\rAssert failed in: %s (%d)\n\r", __func__, __LINE__); 00455 #endif 00456 00457 tx_fifo_buffer = NULL; 00458 _spirit_tx_started = false; 00459 00460 /* call user callback */ 00461 if(_current_irq_callback) { 00462 _current_irq_callback(TX_DONE); 00463 } 00464 00465 /* Disable handling of other TX flags */ 00466 x_irq_status.IRQ_TX_FIFO_ALMOST_EMPTY = S_RESET; 00467 } 00468 00469 #ifndef RX_FIFO_THR_WA 00470 /* The IRQ_TX_FIFO_ALMOST_EMPTY notifies an nearly empty TX fifo */ 00471 if(x_irq_status.IRQ_TX_FIFO_ALMOST_EMPTY) { 00472 #ifdef DEBUG_IRQ 00473 uint32_t *tmp = (uint32_t*)&x_irq_status; 00474 debug_if(!((*tmp) & IRQ_TX_FIFO_ALMOST_EMPTY_MASK), "\n\rAssert failed in: %s (%d)\n\r", __func__, __LINE__); 00475 debug_if(!_spirit_tx_started, "\n\rAssert failed in: %s (%d)\n\r", __func__, __LINE__); 00476 debug_if(tx_fifo_buffer == NULL, "\n\rAssert failed in: %s (%d)\n\r", __func__, __LINE__); 00477 #endif 00478 00479 int8_t fifo_available = SPIRIT_MAX_FIFO_LEN/2; // fill-up half fifo 00480 int8_t to_send = (tx_fifo_remaining > fifo_available) ? fifo_available : tx_fifo_remaining; 00481 00482 tx_fifo_remaining -= to_send; 00483 00484 /* Fill FIFO Buffer */ 00485 if(to_send > 0) { 00486 spi_write_linear_fifo(to_send, (uint8_t*)&tx_fifo_buffer[tx_buffer_pos]); 00487 } 00488 tx_buffer_pos += to_send; 00489 } 00490 #endif // !RX_FIFO_THR_WA 00491 00492 /* Transmission error */ 00493 if(x_irq_status.IRQ_TX_FIFO_ERROR) { 00494 #ifdef DEBUG_IRQ 00495 uint32_t *tmp = (uint32_t*)&x_irq_status; 00496 debug("\n\r%s (%d): irq=%x\n\r", __func__, __LINE__, *tmp); 00497 debug_if(!((*tmp) & IRQ_TX_FIFO_ERROR_MASK), "\n\rAssert failed in: %s (%d)\n\r", __func__, __LINE__); 00498 #endif 00499 if(_spirit_tx_started) { 00500 _spirit_tx_started = false; 00501 /* call user callback */ 00502 if(_current_irq_callback) { 00503 _current_irq_callback(TX_ERR); 00504 } 00505 } 00506 00507 /* reset data still to be sent */ 00508 tx_fifo_remaining = 0; 00509 } 00510 00511 /* The IRQ_RX_DATA_READY notifies a new packet arrived */ 00512 if(x_irq_status.IRQ_RX_DATA_READY) { 00513 #ifdef DEBUG_IRQ 00514 uint32_t *tmp = (uint32_t*)&x_irq_status; 00515 debug_if(!((*tmp) & IRQ_RX_DATA_READY_MASK), "\n\rAssert failed in: %s (%d)\n\r", __func__, __LINE__); 00516 #endif 00517 00518 if(!_is_receiving) { // spurious irq?!? (betzw: see comments on macro 'RX_FIFO_THR_WA'!) 00519 #ifdef HEAVY_DEBUG 00520 debug("\n\r%s (%d): irq=%x\n\r", __func__, __LINE__, *tmp); 00521 #endif 00522 } else { 00523 _is_receiving = false; // Finished receiving 00524 stop_rx_timeout(); 00525 00526 spirit_rx_len = pkt_basic_get_received_pkt_length(); 00527 00528 #ifdef DEBUG_IRQ 00529 debug_if(!(spirit_rx_len <= MAX_PACKET_LEN), "\n\r%s (%d): irq=%x\n\r", __func__, __LINE__, *tmp); 00530 #endif 00531 00532 if(spirit_rx_len <= MAX_PACKET_LEN) { 00533 uint8_t to_receive = spirit_rx_len - _spirit_rx_pos; 00534 if(to_receive > 0) { 00535 spi_read_linear_fifo(to_receive, &spirit_rx_buf[_spirit_rx_pos]); 00536 _spirit_rx_pos += to_receive; 00537 } 00538 } 00539 00540 cmd_strobe(SPIRIT1_STROBE_FRX); 00541 00542 last_rssi = qi_get_rssi(); //MGR 00543 last_sqi = qi_get_sqi(); //MGR 00544 00545 /* call user callback */ 00546 if((_spirit_rx_pos == spirit_rx_len) && _current_irq_callback) { 00547 _current_irq_callback(RX_DONE); 00548 } 00549 00550 /* Disable handling of other RX flags */ 00551 x_irq_status.IRQ_RX_FIFO_ALMOST_FULL = S_RESET; 00552 } 00553 } 00554 00555 #ifndef RX_FIFO_THR_WA 00556 /* RX FIFO almost full */ 00557 if(x_irq_status.IRQ_RX_FIFO_ALMOST_FULL) { 00558 #ifdef DEBUG_IRQ 00559 uint32_t *tmp = (uint32_t*)&x_irq_status; 00560 debug_if(!((*tmp) & IRQ_RX_FIFO_ALMOST_FULL_MASK), "\n\rAssert failed in: %s (%d)\n\r", __func__, __LINE__); 00561 #endif 00562 if(!_is_receiving) { // spurious irq?!? 00563 #ifdef DEBUG_IRQ 00564 debug("\n\r%s (%d): irq=%x\n\r", __func__, __LINE__, *tmp); 00565 #endif 00566 } else { 00567 uint8_t fifo_available = linear_fifo_read_num_elements_rx_fifo(); 00568 if((fifo_available + _spirit_rx_pos) <= MAX_PACKET_LEN) { 00569 spi_read_linear_fifo(fifo_available, &spirit_rx_buf[_spirit_rx_pos]); 00570 _spirit_rx_pos += fifo_available; 00571 } else { 00572 #ifdef DEBUG_IRQ 00573 debug("\n\r%s (%d): irq=%x\n\r", __func__, __LINE__, *tmp); 00574 #endif 00575 } 00576 } 00577 } 00578 #endif // !RX_FIFO_THR_WA 00579 00580 /* Reception errors */ 00581 if((x_irq_status.IRQ_RX_FIFO_ERROR) || (x_irq_status.IRQ_RX_DATA_DISC)) { 00582 #ifdef DEBUG_IRQ 00583 uint32_t *tmp = (uint32_t*)&x_irq_status; 00584 debug("\n\r%s (%d): irq=%x\n\r", __func__, __LINE__, *tmp); 00585 debug_if(!((*tmp) & (IRQ_RX_FIFO_ERROR_MASK | IRQ_RX_DATA_DISC_MASK)), "\n\rAssert failed in: %s (%d)\n\r", __func__, __LINE__); 00586 #endif 00587 rx_timeout_handler(); 00588 if(_spirit_tx_started) { 00589 _spirit_tx_started = false; 00590 /* call user callback */ 00591 if(_current_irq_callback) { 00592 _current_irq_callback(TX_ERR); 00593 } 00594 } 00595 } 00596 00597 /* The IRQ_VALID_SYNC is used to notify a new packet is coming */ 00598 if(x_irq_status.IRQ_VALID_SYNC) { 00599 #ifdef DEBUG_IRQ 00600 uint32_t *tmp = (uint32_t*)&x_irq_status; 00601 debug_if(!((*tmp) & IRQ_VALID_SYNC_MASK), "\n\rAssert failed in: %s (%d)\n\r", __func__, __LINE__); 00602 #endif 00603 /* betzw - NOTE: there is a race condition between Spirit1 receiving packets and 00604 * the MCU trying to send a packet, which gets resolved in favor of 00605 * sending. 00606 */ 00607 if(_spirit_tx_started) { 00608 #ifdef DEBUG_IRQ 00609 debug("\n\r%s (%d): irq=%x\n\r", __func__, __LINE__, *tmp); 00610 #endif 00611 } else { 00612 _is_receiving = true; 00613 start_rx_timeout(); 00614 } 00615 } 00616 }
Generated on Wed Jul 13 2022 01:16:06 by
