@@ -433,10 +433,11 @@ void e3xx_radio_control_impl::loopback_self_test(const size_t chan)
433
433
_ad9361->set_clock_rate (30.72e6 );
434
434
// Put AD936x in loopback mode
435
435
_ad9361->data_port_loopback (true );
436
- RFNOC_LOG_INFO (" Performing CODEC loopback test... " );
436
+ RFNOC_LOG_INFO (
437
+ " Performing CODEC loopback test on channel " << std::to_string (chan) << " ... " );
437
438
size_t hash = size_t (time (NULL ));
438
439
constexpr size_t loopback_count = 100 ;
439
-
440
+ constexpr size_t retries = 3 ;
440
441
// Allow some time for AD936x to enter loopback mode.
441
442
// There is no clear statement in the documentation of how long it takes,
442
443
// but UG-570 does say to "allow six ADC_CLK/64 clock cycles of flush time"
@@ -445,31 +446,49 @@ void e3xx_radio_control_impl::loopback_self_test(const size_t chan)
445
446
// Sleeping 1ms is far more than enough.
446
447
std::this_thread::sleep_for (std::chrono::milliseconds (1 ));
447
448
448
- for (size_t i = 0 ; i < loopback_count; i++) {
449
- // Create test word
450
- boost::hash_combine (hash, i);
451
- const uint32_t word32 = uint32_t (hash) & 0xfff0fff0 ;
452
- // Write test word to codec_idle idle register (on TX side)
453
- regs ().poke32 (regmap::RADIO_BASE_ADDR + chan * regmap::REG_CHAN_OFFSET
454
- + regmap::REG_TX_IDLE_VALUE,
455
- word32);
456
-
457
- // Read back values - TX is lower 32-bits and RX is upper 32-bits
458
- const uint32_t rb_tx =
459
- regs ().peek32 (regmap::RADIO_BASE_ADDR + chan * regmap::REG_CHAN_OFFSET
460
- + regmap::REG_TX_IDLE_VALUE);
461
- const uint32_t rb_rx =
462
- regs ().peek32 (regmap::RADIO_BASE_ADDR + chan * regmap::REG_CHAN_OFFSET
463
- + regmap::REG_RX_DATA);
464
-
465
- // Compare TX and RX values to test word
466
- bool test_fail = word32 != rb_tx or word32 != rb_rx;
467
- if (test_fail) {
468
- RFNOC_LOG_WARNING (
469
- " CODEC loopback test failed! "
470
- << boost::format (" Expected: 0x%08X Received (TX/RX): 0x%08X/0x%08X" )
471
- % word32 % rb_tx % rb_rx);
472
- throw uhd::runtime_error (" CODEC loopback test failed." );
449
+ bool test_fail = true ;
450
+ while (test_fail) {
451
+ size_t tries = 0 ;
452
+ for (size_t i = 0 ; i < loopback_count; i++) {
453
+ // Create test word
454
+ boost::hash_combine (hash, i);
455
+ const uint32_t word32 = uint32_t (hash) & 0xfff0fff0 ;
456
+ // Write test word to codec_idle idle register (on TX side)
457
+ regs ().poke32 (regmap::RADIO_BASE_ADDR + chan * regmap::REG_CHAN_OFFSET
458
+ + regmap::REG_TX_IDLE_VALUE,
459
+ word32);
460
+
461
+ // Read back values - TX is lower 32-bits and RX is upper 32-bits
462
+ const uint32_t rb_tx =
463
+ regs ().peek32 (regmap::RADIO_BASE_ADDR + chan * regmap::REG_CHAN_OFFSET
464
+ + regmap::REG_TX_IDLE_VALUE);
465
+ const uint32_t rb_rx =
466
+ regs ().peek32 (regmap::RADIO_BASE_ADDR + chan * regmap::REG_CHAN_OFFSET
467
+ + regmap::REG_RX_DATA);
468
+
469
+ // Compare TX and RX values to test word
470
+ test_fail = word32 != rb_tx or word32 != rb_rx;
471
+ if (test_fail) {
472
+ RFNOC_LOG_DEBUG (
473
+ " CODEC loopback test failure: "
474
+ << boost::format (" Expected: 0x%08X Received (TX/RX): 0x%08X/0x%08X" )
475
+ % word32 % rb_tx % rb_rx);
476
+ if (tries < retries) {
477
+ // TODO: Investigate why loopback test sometimes fails
478
+ // Upon failure, setting the streaming mode again makes
479
+ // it work for some reason.
480
+ this ->set_streaming_mode (true , true , true , true );
481
+
482
+ // Try again
483
+ RFNOC_LOG_DEBUG (" Retrying CODEC loopback test for channel "
484
+ << std::to_string (chan) << " ... " );
485
+ tries++;
486
+ break ;
487
+ } else {
488
+ RFNOC_LOG_ERROR (" CODEC loopback test failed!" );
489
+ throw uhd::runtime_error (" CODEC loopback test failed." );
490
+ }
491
+ }
473
492
}
474
493
}
475
494
RFNOC_LOG_INFO (" CODEC loopback test passed" );
0 commit comments