/* / _____) _ | | ( (____ _____ ____ _| |_ _____ ____| |__ \____ \| ___ | (_ _) ___ |/ ___) _ \ _____) ) ____| | | || |_| ____( (___| | | | (______/|_____)_|_|_| \__)_____)\____)_| |_| (C)2019 Semtech Description: Minimum test program for the loragw_com module License: Revised BSD License, see LICENSE.TXT file include in the project */ /* -------------------------------------------------------------------------- */ /* --- DEPENDANCIES --------------------------------------------------------- */ /* Fix an issue between POSIX and C99 */ #if __STDC_VERSION__ >= 199901L #define _XOPEN_SOURCE 600 #else #define _XOPEN_SOURCE 500 #endif #include #include #include #include #include /* sigaction */ #include /* getopt, access */ #include #include #include "loragw_com.h" #include "loragw_aux.h" #include "loragw_hal.h" /* -------------------------------------------------------------------------- */ /* --- PRIVATE MACROS ------------------------------------------------------- */ #define RAND_RANGE(min, max) (rand() % (max + 1 - min) + min) /* -------------------------------------------------------------------------- */ /* --- PRIVATE CONSTANTS ---------------------------------------------------- */ #define BUFF_SIZE_SPI 1024 #define BUFF_SIZE_USB 4096 #define SX1302_AGC_MCU_MEM 0x0000 #define SX1302_REG_COMMON 0x5600 #define SX1302_REG_AGC_MCU 0x5780 #define COM_TYPE_DEFAULT LGW_COM_SPI #define COM_PATH_DEFAULT "/dev/spidev0.0" /* -------------------------------------------------------------------------- */ /* --- GLOBAL VARIABLES ----------------------------------------------------- */ /* Signal handling variables */ static int exit_sig = 0; /* 1 -> application terminates cleanly (shut down hardware, close open files, etc) */ static int quit_sig = 0; /* 1 -> application terminates without shutting down the hardware */ /* Buffers */ static uint8_t * test_buff = NULL; static uint8_t * read_buff = NULL; /* -------------------------------------------------------------------------- */ /* --- SUBFUNCTIONS DECLARATION --------------------------------------------- */ static void sig_handler(int sigio); static void usage(void); static void exit_failure(void); /* -------------------------------------------------------------------------- */ /* --- MAIN FUNCTION -------------------------------------------------------- */ int main(int argc, char ** argv) { static struct sigaction sigact; /* SIGQUIT&SIGINT&SIGTERM signal handling */ uint16_t max_buff_size; uint8_t data = 0; int cycle_number = 0; int i, x; uint16_t size; /* COM interfaces */ const char com_path_default[] = COM_PATH_DEFAULT; const char * com_path = com_path_default; lgw_com_type_t com_type = COM_TYPE_DEFAULT; /* Parse command line options */ while ((i = getopt(argc, argv, "hd:u")) != -1) { switch (i) { case 'h': usage(); return EXIT_SUCCESS; break; case 'd': if (optarg != NULL) { com_path = optarg; } break; case 'u': com_type = LGW_COM_USB; break; default: printf("ERROR: argument parsing options, use -h option for help\n"); usage(); return EXIT_FAILURE; } } /* 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 ); /* Board reset */ if (com_type == LGW_COM_SPI) { if (system("./reset_lgw.sh start") != 0) { printf("ERROR: failed to reset SX1302, check your reset_lgw.sh script\n"); exit(EXIT_FAILURE); } } printf("Beginning of test for loragw_com.c\n"); x = lgw_com_open(com_type, com_path); if (x != 0) { printf("ERROR: failed to open COM device %s\n", com_path); exit(EXIT_FAILURE); } /* normal R/W test */ /* TODO */ /* burst R/W test, small bursts << LGW_BURST_CHUNK */ /* TODO */ /* burst R/W test, large bursts >> LGW_BURST_CHUNK */ /* TODO */ x = lgw_com_r(LGW_SPI_MUX_TARGET_SX1302, SX1302_REG_COMMON + 6, &data); if (x != 0) { printf("ERROR (%d): failed to read register\n", __LINE__); exit_failure(); } printf("SX1302 version: 0x%02X\n", data); x = lgw_com_r(LGW_SPI_MUX_TARGET_SX1302, SX1302_REG_AGC_MCU + 0, &data); if (x != 0) { printf("ERROR (%d): failed to read register\n", __LINE__); exit_failure(); } x = lgw_com_w(LGW_SPI_MUX_TARGET_SX1302, SX1302_REG_AGC_MCU + 0, 0x06); /* mcu_clear, host_prog */ if (x != 0) { printf("ERROR (%d): failed to write register\n", __LINE__); exit_failure(); } srand(time(NULL)); /* Allocate buffers according to com type capabilities */ max_buff_size = (com_type == LGW_COM_SPI) ? BUFF_SIZE_SPI : BUFF_SIZE_USB; test_buff = (uint8_t*)malloc(max_buff_size * sizeof(uint8_t)); if (test_buff == NULL) { printf("ERROR: failed to allocate memory for test_buff - %s\n", strerror(errno)); exit_failure(); } read_buff = (uint8_t*)malloc(max_buff_size * sizeof(uint8_t)); if (read_buff == NULL) { printf("ERROR: failed to allocate memory for read_buff - %s\n", strerror(errno)); exit_failure(); } /* databuffer R/W stress test */ while ((quit_sig != 1) && (exit_sig != 1)) { /************************************************* * * WRITE BURST TEST * * ***********************************************/ size = rand() % max_buff_size; for (i = 0; i < size; ++i) { test_buff[i] = rand() & 0xFF; } printf("Cycle %i> ", cycle_number); /* Write burst with random data */ x = lgw_com_wb(LGW_SPI_MUX_TARGET_SX1302, SX1302_AGC_MCU_MEM, test_buff, size); if (x != 0) { printf("ERROR (%d): failed to write burst\n", __LINE__); exit_failure(); } /* Read back */ x = lgw_com_rb(LGW_SPI_MUX_TARGET_SX1302, SX1302_AGC_MCU_MEM, read_buff, size); if (x != 0) { printf("ERROR (%d): failed to read burst\n", __LINE__); exit_failure(); } /* Compare read / write buffers */ for (i=0; ((i ", cycle_number); test_buff[0] = rand() & 0xFF; /* Write single byte */ x = lgw_com_w(LGW_SPI_MUX_TARGET_SX1302, SX1302_AGC_MCU_MEM, test_buff[0]); if (x != 0) { printf("ERROR (%d): failed to write burst\n", __LINE__); exit_failure(); } /* Read back */ x = lgw_com_r(LGW_SPI_MUX_TARGET_SX1302, SX1302_AGC_MCU_MEM, &read_buff[0]); if (x != 0) { printf("ERROR (%d): failed to read burst\n", __LINE__); exit_failure(); } /* Compare read / write bytes */ if (test_buff[0] != read_buff[0]) { printf("error during the byte comparison\n"); /* Print what has been written */ printf("Written value: %02X\n", test_buff[0]); /* Print what has been read back */ printf("Read values: %02X\n", read_buff[0]); /* exit */ exit_failure(); } else { printf("did a 1-byte R/W on a data buffer with no error\n"); ++cycle_number; } /************************************************* * * WRITE WITH BULK (USB only mode) * * ***********************************************/ x = lgw_com_set_write_mode(LGW_COM_WRITE_MODE_BULK); if (x != 0) { printf("ERROR (%d): failed to set bulk write mode\n", __LINE__); exit_failure(); } uint16_t num_req = RAND_RANGE(1, 254); /* keep one req for remaining bytes */ size = RAND_RANGE(num_req, max_buff_size / 2); /* TODO: test proper limit */ for (i = 0; i < size; i++) { test_buff[i] = rand() & 0xFF; } uint16_t size_per_req = size / num_req; uint16_t size_remaining = size - (num_req * size_per_req); printf("Cycle %i> ", cycle_number); uint16_t size_written = 0; for (i = 0; i < num_req; i++) { x = lgw_com_wb(LGW_SPI_MUX_TARGET_SX1302, SX1302_AGC_MCU_MEM + size_written, test_buff + size_written, size_per_req); if (x != 0) { printf("ERROR (%d): failed to write burst\n", __LINE__); exit_failure(); } size_written += (size_per_req); } if (size_remaining > 0) { x = lgw_com_wb(LGW_SPI_MUX_TARGET_SX1302, SX1302_AGC_MCU_MEM + size_written, test_buff + size_written, size_remaining); if (x != 0) { printf("ERROR (%d): failed to write burst\n", __LINE__); exit_failure(); } } /* Send data to MCU (UBS mode only) */ x = lgw_com_flush(); if (x != 0) { printf("ERROR (%d): failed to flush write\n", __LINE__); exit_failure(); } /* Read back */ x = lgw_com_rb(LGW_SPI_MUX_TARGET_SX1302, SX1302_AGC_MCU_MEM, read_buff, size); if (x != 0) { printf("ERROR (%d): failed to read burst\n", __LINE__); exit_failure(); } /* Compare read / write buffers */ for (i=0; ((i COM path to be used to connect the concentrator\n"); printf(" => default path (SPI): " COM_PATH_DEFAULT "\n"); } /* --- EOF ------------------------------------------------------------------ */