/* size is the firmware size in bytes (not 14b words) */ int load_firmware_(uint8_t target, uint8_t *firmware, uint16_t size) { int reg_rst; int reg_sel; /* check parameters */ if (target == MCU_ARB) { if (size != MCU_ARB_FW_BYTE) { MSG("ERROR: NOT A VALID SIZE FOR MCU ARG FIRMWARE\n"); return -1; } reg_rst = LGW_MCU_RST_0; reg_sel = LGW_MCU_SELECT_MUX_0; }else if (target == MCU_AGC) { if (size != MCU_AGC_FW_BYTE) { MSG("ERROR: NOT A VALID SIZE FOR MCU AGC FIRMWARE\n"); return -1; } reg_rst = LGW_MCU_RST_1; reg_sel = LGW_MCU_SELECT_MUX_1; } else { MSG("ERROR: NOT A VALID TARGET FOR LOADING FIRMWARE\n"); return -1; } /* reset the targeted MCU */ lgw_reg_w(reg_rst, 1); /* set mux to access MCU program RAM and set address to 0 */ lgw_reg_w(reg_sel, 0); lgw_reg_w(LGW_MCU_PROM_ADDR, 0); /* write the program in one burst */ lgw_reg_wb(LGW_MCU_PROM_DATA, firmware, size); /* give back control of the MCU program ram to the MCU */ lgw_reg_w(reg_sel, 1); return 0; }
int main(int argc, char **argv) { int i; int xi = 0; /* application option */ int test_number = 1; int cycle_number = 0; int repeats_per_cycle = 1000; bool error = false; /* in/out variables */ int32_t test_value; int32_t read_value; int32_t rb1, rb2, rb3; /* interstitial readbacks, to flush buffers if needed */ /* data buffer */ int32_t test_addr; uint8_t test_buff[BUFF_SIZE]; uint8_t read_buff[BUFF_SIZE]; /* parse command line options */ while ((i = getopt (argc, argv, "ht:")) != -1) { switch (i) { case 'h': usage(); return EXIT_FAILURE; break; case 't': i = sscanf(optarg, "%i", &xi); if ((i != 1) || (xi < 1) || (xi > 4)) { MSG("ERROR: invalid test number\n"); return EXIT_FAILURE; } else { test_number = xi; } break; default: MSG("ERROR: argument parsing use -h option for help\n"); usage(); return EXIT_FAILURE; } } MSG("INFO: Starting LoRa concentrator SPI stress-test number %i\n", test_number); /* configure signal handling */ sigemptyset(&sigact.sa_mask); sigact.sa_flags = 0; sigact.sa_handler = sig_handler; sigaction(SIGQUIT, &sigact, NULL); sigaction(SIGINT, &sigact, NULL); sigaction(SIGTERM, &sigact, NULL); /* start SPI link */ i = lgw_connect(); if (i != LGW_REG_SUCCESS) { MSG("ERROR: lgw_connect() did not return SUCCESS"); return EXIT_FAILURE; } if (test_number == 1) { /* single 8b register R/W stress test */ while ((quit_sig != 1) && (exit_sig != 1)) { printf("Cycle %i > ", cycle_number); for (i=0; i<repeats_per_cycle; ++i) { test_value = (rand() % 256); lgw_reg_w(LGW_IMPLICIT_PAYLOAD_LENGHT, test_value); lgw_reg_r(LGW_IMPLICIT_PAYLOAD_LENGHT, &read_value); if (read_value != test_value) { error = true; break; } } if (error) { printf("error during the %ith iteration: write 0x%02X, read 0x%02X\n", i+1, test_value, read_value); printf("Repeat read of target register:"); for (i=0; i<READS_WHEN_ERROR; ++i) { lgw_reg_r(LGW_IMPLICIT_PAYLOAD_LENGHT, &read_value); printf(" 0x%02X", read_value); } printf("\n"); return EXIT_FAILURE; } else { printf("did %i R/W on an 8 bits reg with no error\n", repeats_per_cycle); ++cycle_number; } } } else if (test_number == 2) { /* single 8b register R/W with interstitial VERSION check stress test */ while ((quit_sig != 1) && (exit_sig != 1)) { printf("Cycle %i > ", cycle_number); for (i=0; i<repeats_per_cycle; ++i) { test_value = (rand() % 256); lgw_reg_r(LGW_VERSION, &rb1); lgw_reg_w(LGW_IMPLICIT_PAYLOAD_LENGHT, test_value); lgw_reg_r(LGW_VERSION, &rb2); lgw_reg_r(LGW_IMPLICIT_PAYLOAD_LENGHT, &read_value); lgw_reg_r(LGW_VERSION, &rb3); if ((rb1 != VERS) || (rb2 != VERS) || (rb3 != VERS) || (read_value != test_value)) { error = true; break; } } if (error) { printf("error during the %ith iteration: write %02X, read %02X, version (%i, %i, %i)\n", i+1, test_value, read_value, rb1, rb2, rb3); printf("Repeat read of target register:"); for (i=0; i<READS_WHEN_ERROR; ++i) { lgw_reg_r(LGW_IMPLICIT_PAYLOAD_LENGHT, &read_value); printf(" 0x%02X", read_value); } printf("\n"); return EXIT_FAILURE; } else { printf("did %i R/W on an 8 bits reg with no error\n", repeats_per_cycle); ++cycle_number; } } } else if (test_number == 3) { /* 32b register R/W stress test */ while ((quit_sig != 1) && (exit_sig != 1)) { printf("Cycle %i > ", cycle_number); for (i=0; i<repeats_per_cycle; ++i) { test_value = (rand() & 0x0000FFFF); test_value += (int32_t)(rand() & 0x0000FFFF) << 16; lgw_reg_w(LGW_FSK_REF_PATTERN_LSB, test_value); lgw_reg_r(LGW_FSK_REF_PATTERN_LSB, &read_value); if (read_value != test_value) { error = true; break; } } if (error) { printf("error during the %ith iteration: write 0x%08X, read 0x%08X\n", i+1, test_value, read_value); printf("Repeat read of target register:"); for (i=0; i<READS_WHEN_ERROR; ++i) { lgw_reg_r(LGW_FSK_REF_PATTERN_LSB, &read_value); printf(" 0x%08X", read_value); } printf("\n"); return EXIT_FAILURE; } else { printf("did %i R/W on a 32 bits reg with no error\n", repeats_per_cycle); ++cycle_number; } } } else if (test_number == 4) { /* databuffer R/W stress test */ while ((quit_sig != 1) && (exit_sig != 1)) { for (i=0; i<BUFF_SIZE; ++i) { test_buff[i] = rand() & 0xFF; } printf("Cycle %i > ", cycle_number); test_addr = rand() & 0xFFFF; lgw_reg_w(LGW_RX_DATA_BUF_ADDR, test_addr); /* write at random offset in memory */ lgw_reg_wb(LGW_RX_DATA_BUF_DATA, test_buff, BUFF_SIZE); lgw_reg_w(LGW_RX_DATA_BUF_ADDR, test_addr); /* go back to start of segment */ lgw_reg_rb(LGW_RX_DATA_BUF_DATA, read_buff, BUFF_SIZE); for (i=0; ((i<BUFF_SIZE) && (test_buff[i] == read_buff[i])); ++i); if (i != BUFF_SIZE) { printf("error during the buffer comparison\n"); printf("Written values:\n"); for (i=0; i<BUFF_SIZE; ++i) { printf(" %02X ", test_buff[i]); if (i%16 == 15) printf("\n"); } printf("\n"); printf("Read values:\n"); for (i=0; i<BUFF_SIZE; ++i) { printf(" %02X ", read_buff[i]); if (i%16 == 15) printf("\n"); } printf("\n"); lgw_reg_w(LGW_RX_DATA_BUF_ADDR, test_addr); /* go back to start of segment */ lgw_reg_rb(LGW_RX_DATA_BUF_DATA, read_buff, BUFF_SIZE); printf("Re-read values:\n"); for (i=0; i<BUFF_SIZE; ++i) { printf(" %02X ", read_buff[i]); if (i%16 == 15) printf("\n"); } printf("\n"); return EXIT_FAILURE; } else { printf("did a %i-byte R/W on a data buffer with no error\n", BUFF_SIZE); ++cycle_number; } } } else { MSG("ERROR: invalid test number"); usage(); } /* close SPI link */ i = lgw_disconnect(); if (i != LGW_REG_SUCCESS) { MSG("ERROR: lgw_disconnect() did not return SUCCESS"); return EXIT_FAILURE; } MSG("INFO: Exiting LoRa concentrator SPI stress-test program\n"); return EXIT_SUCCESS; }