diff --git a/ExampleProjects/CMakeLists.txt b/ExampleProjects/CMakeLists.txt index 24065980f..9f0d827f3 100644 --- a/ExampleProjects/CMakeLists.txt +++ b/ExampleProjects/CMakeLists.txt @@ -24,6 +24,8 @@ add_subdirectory(Ascii) add_subdirectory(Bootloader) add_subdirectory(Communications) add_subdirectory(IS_firmwareUpdate_v2) +# add_subdirectory(InertialSense_log_reader) +add_subdirectory(InertialSense_log_reader_RegCmp) add_subdirectory(ISLogger_read) add_subdirectory(ISLogger_write) add_subdirectory(InertialSense_logger) diff --git a/ExampleProjects/InertialSense_log_reader_RegCmp/LogReader_RegCmp.cpp b/ExampleProjects/InertialSense_log_reader_RegCmp/LogReader_RegCmp.cpp index a25d329b9..2798c1316 100644 --- a/ExampleProjects/InertialSense_log_reader_RegCmp/LogReader_RegCmp.cpp +++ b/ExampleProjects/InertialSense_log_reader_RegCmp/LogReader_RegCmp.cpp @@ -19,12 +19,11 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI #define SCRATCH_SIZE 2048 - typedef struct { - uint32_t CR1; /*!< USART Control register 1, Address offset: 0x00 */ - uint32_t CR2; /*!< USART Control register 2, Address offset: 0x04 */ - uint32_t CR3; /*!< USART Control register 3, Address offset: 0x08 */ + uint32_t _CR1; /*!< USART Control register 1, Address offset: 0x00 */ + uint32_t _CR2; /*!< USART Control register 2, Address offset: 0x04 */ + uint32_t _CR3; /*!< USART Control register 3, Address offset: 0x08 */ uint32_t BRR; /*!< USART Baud rate register, Address offset: 0x0C */ uint32_t GTPR; /*!< USART Guard time and prescaler register, Address offset: 0x10 */ uint32_t RTOR; /*!< USART Receiver Time Out register, Address offset: 0x14 */ @@ -37,7 +36,7 @@ typedef struct uint32_t AUTOCR; /*!< USART Autonomous mode control register Address offset: 0x30 */ } USART_TypeDef; -typedef enum +enum class IRQn_Type : int8_t { /* ======================================= ARM Cortex-M33 Specific Interrupt Numbers ======================================= */ Reset_IRQn = -15, /*!< -15 Reset Vector, invoked on Power up and warm reset */ @@ -175,7 +174,7 @@ typedef enum MDF1_FLT5_IRQn = 122, /*!< MDF1 Filter 5 global interrupt */ CORDIC_IRQn = 123, /*!< CORDIC global interrupt */ FMAC_IRQn = 124, /*!< FMAC global interrupt */ -} IRQn_Type; +}; typedef struct { @@ -206,17 +205,34 @@ typedef void(*dma_callback_function)(void*); typedef struct { - void* parent; // Pointer to parent peripheral management struct - uint8_t mode; // DMA_MODE_... - dma_callback_function tc_handler; // If non-null, this function pointer is called from within transfer complete interrupt handler when all data including queued data has been transferred. - IRQn_Type interrupt; - uint8_t interrupt_priority; - uint8_t priority; // DMA priority (DMA_PRIO_...) - uint8_t request_num; // DMA request ID, links channel to peripheral (DMA_IDX_... for index) - uint32_t periph_reg; // target 8-bit peripheral register (DMA_IDX_... for index) - uint8_t* buf; - uint16_t buf_len; // Actual usable buffer length is one less (buf_len - 1) -} dma_config_t; + uint32_t parent; // Pointer to parent peripheral management struct + uint8_t mode; // DMA_MODE_... + uint32_t tc_handler; // If non-null, this function pointer is called from within transfer complete interrupt handler when all data including queued data has been transferred. + uint8_t interrupt; + uint8_t interrupt_priority; + uint8_t priority; // DMA priority (DMA_PRIO_...) + uint8_t request_num; // DMA request ID, links channel to peripheral (DMA_IDX_... for index) + uint32_t periph_reg; // target 8-bit peripheral register (DMA_IDX_... for index) + uint32_t buf; + uint16_t buf_len; // Actual usable buffer length is one less (buf_len - 1) +} dma_config_t_GPX; + +typedef struct +{ + bool dir; // DMA_RX or DMA_TX + bool circular; // DMA_CIRC_ON or DMA_CIRC_OFF + uint8_t priority; // DMA_PRIO_LOW, DMA_PRIO_MEDIUM, DMA_PRIO_HIGH, DMA_PRIO_VERY_HIGH + uint8_t interrupt; + uint8_t interrupt_priority; // 0 to 15, 15 is low + uint8_t dma_channel_select; // 0 to 7. See RM0394 11.6.7 + uint8_t parent_type; // DMA_PARENT_USART, ... + uint32_t parent; // Pointer to parent init base + uint32_t periph_reg; // Pointer to peripheral register + uint32_t buf; + uint16_t buf_len; // This doesn't correspond to the length register, it is just however big the buffer is + bool linear_buf; // If true, the buffer is user-specified and we treat it like a non-circular buffer. + uint32_t tcie_handler; // If non-null on init, transfer complete irq will be enabled, and this fn called by the IRQ +} dma_config_t_IMX; typedef struct { @@ -240,23 +256,23 @@ typedef union typedef struct { - volatile uint16_t active_tx_len; - dma_tx_lli_t* lli_head; // Linked list output to dma - dma_tx_lli_t* lli_tail; // Linked list input from dma_buffer_write() - volatile bool dma_running; + volatile uint16_t active_tx_len; + uint32_t lli_head; // Linked list output to dma + uint32_t lli_tail; // Linked list input from dma_buffer_write() + volatile bool dma_running; } dma_tx_state_t; typedef struct dma_channel_ { - DMA_Channel_TypeDef* instance; - volatile uint8_t* ptr_start; - volatile uint8_t* ptr_end; - dma_config_t cfg; - dma_lli_u lli; // Linked list memory. DMA_MODE_TX_LLI uses 6, DMA_MODE_RX_CIRC uses 1. - dma_tx_state_t txState; - int lastDmaUsed; - uint8_t overflow; // Buffer overflow -} dma_ch_t; + uint32_t instance; + volatile uint32_t ptr_start; + volatile uint32_t ptr_end; + dma_config_t_GPX cfg; + dma_lli_u lli; // Linked list memory. DMA_MODE_TX_LLI uses 6, DMA_MODE_RX_CIRC uses 1. + dma_tx_state_t txState; + int lastDmaUsed; + uint8_t overflow; // Buffer overflow +} dma_ch_t_GPX; typedef struct { @@ -299,21 +315,21 @@ typedef struct typedef struct { - DMA_Channel_TypeDef* instance; - uint8_t* ptr_start; - uint8_t* ptr_end; - uint16_t active_tx_len; - bool done; // Currently only used in TX - dma_config_t cfg; - int lastDmaUsed; // Number of bytes in the buffer minus bytes last read. This is used to identify buffer overflow. - uint8_t overflow; // Buffer overflow + uint32_t instance; + uint32_t ptr_start; + uint32_t ptr_end; + uint16_t active_tx_len; + bool done; // Currently only used in TX + dma_config_t_IMX cfg; + int lastDmaUsed; // Number of bytes in the buffer minus bytes last read. This is used to identify buffer overflow. + uint8_t overflow; // Buffer overflow } dma_ch_t_IMX; typedef struct { - uint32_t CR1; /*!< USART Control register 1, Address offset: 0x00 */ - uint32_t CR2; /*!< USART Control register 2, Address offset: 0x04 */ - uint32_t CR3; /*!< USART Control register 3, Address offset: 0x08 */ + uint32_t _CR1; /*!< USART Control register 1, Address offset: 0x00 */ + uint32_t _CR2; /*!< USART Control register 2, Address offset: 0x04 */ + uint32_t _CR3; /*!< USART Control register 3, Address offset: 0x08 */ uint32_t BRR; /*!< USART Baud rate register, Address offset: 0x0C */ uint16_t GTPR; /*!< USART Guard time and prescaler register, Address offset: 0x10 */ uint16_t RESERVED2; /*!< Reserved, 0x12 */ @@ -328,17 +344,42 @@ typedef struct uint16_t RESERVED5; /*!< Reserved, 0x2A */ } USART_TypeDef_IMX; - -DMA_Channel_TypeDef tmpUartDmaReg; -USART_TypeDef tmpUartReg; -usart_cfg_t tmpUartCfg; -dma_ch_t tmpUartDmaChan; -GPIO_TypeDef tmpUartGpio; - -eventImxDmaTxInst_t tmpIMXUartDmaInst; -USART_TypeDef_IMX tmpIMXUartReg; -dma_ch_t_IMX tmpIMXUartDmaChan; -GPIO_TypeDef_IMX tmpIMXUartGpio; +PUSH_PACK_1 + +typedef struct{ + uint32_t inst_CCR; /*!< DMA channel x configuration register */ + uint32_t inst_CNDTR; /*!< DMA channel x number of data register */ + uint32_t inst_CPAR; /*!< DMA channel x peripheral address register */ + uint32_t inst_CMAR; /*!< DMA channel x memory address register */ + + uint32_t ptr_start; + uint32_t ptr_end; + uint16_t active_tx_len; + uint8_t done; // Currently only used in TX + + uint8_t cfg_dir; // DMA_RX or DMA_TX + uint8_t cfg_circular; // DMA_CIRC_ON or DMA_CIRC_OFF + uint8_t cfg_priority; // DMA_PRIO_LOW, DMA_PRIO_MEDIUM, DMA_PRIO_HIGH, DMA_PRIO_VERY_HIGH + uint8_t cfg_interrupt; + uint8_t cfg_interrupt_priority; // 0 to 15, 15 is low + uint8_t cfg_dma_channel_select; // 0 to 7. See RM0394 11.6.7 + uint8_t cfg_parent_type; // DMA_PARENT_USART, ... + uint32_t cfg_parent; // Pointer to parent init base + uint32_t cfg_periph_reg; // Pointer to peripheral register + uint32_t cfg_buf; + uint16_t cfg_buf_len; // This doesn't correspond to the length register, it is just however big the buffer is + uint8_t cfg_linear_buf; // If true, the buffer is user-specified and we treat it like a non-circular buffer. + uint32_t cfg_tcie_handler; // If n + + int lastDmaUsed; // Number of bytes in the buffer minus bytes last read. This is used to identify buffer overflow. + uint8_t overflow; // Buffer overflow +} eventImxDmaTxInst_local_t; + +POP_PACK + +std::string s_fileName; +std::string s_deviceFolder; +uint8_t s_evScratch[SCRATCH_SIZE + DID_EVENT_HEADER_SIZE] = {0}; int printCurString(char* c) { @@ -348,558 +389,265 @@ int printCurString(char* c) return result.length(); } -void event_outputEvToFile(std::string fileName, uint8_t* data, int len) +void event_outputEvToFile(uint8_t* data, int len) { std::ofstream outfile; - outfile.open(fileName, std::ios_base::app | std::ios_base::binary); // append instead of overwrite + outfile.open(s_fileName, std::ios_base::app | std::ios_base::binary); // append instead of overwrite outfile.write((const char*)data, len); outfile.close(); } -void writeIMXGpioReg(uint8_t* evScratch, std::string fileName) +void sprintfLab(const char* label) { - sprintf((char*)evScratch, "------------Start IMX GPIP Tx0 Reg-------------\r\n"); - event_outputEvToFile(fileName, evScratch, printCurString((char*)evScratch)); - - sprintf((char*)evScratch, "AFR[0]:\t\t0x%08x\r\n", tmpIMXUartGpio.AFR[0]); - event_outputEvToFile(fileName, evScratch, printCurString((char*)evScratch)); - - sprintf((char*)evScratch, "AFR[1]:\t\t0x%08x\r\n", tmpIMXUartGpio.AFR[1]); - event_outputEvToFile(fileName, evScratch, printCurString((char*)evScratch)); - - sprintf((char*)evScratch, "BRR:\t\t0x%08x\r\n", tmpIMXUartGpio.BRR); - event_outputEvToFile(fileName, evScratch, printCurString((char*)evScratch)); - - sprintf((char*)evScratch, "BSRR:\t\t0x%08x\r\n", tmpIMXUartGpio.BSRR); - event_outputEvToFile(fileName, evScratch, printCurString((char*)evScratch)); - - sprintf((char*)evScratch, "IDR:\t\t0x%08x\r\n", tmpIMXUartGpio.IDR); - event_outputEvToFile(fileName, evScratch, printCurString((char*)evScratch)); - - sprintf((char*)evScratch, "LCKR:\t\t0x%08x\r\n", tmpIMXUartGpio.LCKR); - event_outputEvToFile(fileName, evScratch, printCurString((char*)evScratch)); - - sprintf((char*)evScratch, "MODER:\t\t0x%08x\r\n", tmpIMXUartGpio.MODER); - event_outputEvToFile(fileName, evScratch, printCurString((char*)evScratch)); - - sprintf((char*)evScratch, "ODR:\t\t0x%08x\r\n", tmpIMXUartGpio.ODR); - event_outputEvToFile(fileName, evScratch, printCurString((char*)evScratch)); - - sprintf((char*)evScratch, "OSPEEDR:\t0x%08x\r\n", tmpIMXUartGpio.OSPEEDR); - event_outputEvToFile(fileName, evScratch, printCurString((char*)evScratch)); - - sprintf((char*)evScratch, "OTYPER:\t\t0x%08x\r\n", tmpIMXUartGpio.OTYPER); - event_outputEvToFile(fileName, evScratch, printCurString((char*)evScratch)); - - sprintf((char*)evScratch, "PUPDR:\t\t0x%08x\r\n", tmpIMXUartGpio.PUPDR); - event_outputEvToFile(fileName, evScratch, printCurString((char*)evScratch)); - - sprintf((char*)evScratch, "\r\n------------End IMX GPIP Tx0 Reg-------------\r\n\r\n"); - event_outputEvToFile(fileName, evScratch, printCurString((char*)evScratch)); + sprintf((char*)s_evScratch, "%s\r\n", label); + event_outputEvToFile(s_evScratch, printCurString((char*)s_evScratch)); } -void writeIMXDmaTx0Chan(uint8_t* evScratch, std::string fileName) +void sprintfU32(const char* label, const uint32_t value) { - sprintf((char*)evScratch, "------------Start IMX Dma Tx0 Channel-------------\r\n"); - event_outputEvToFile(fileName, evScratch, printCurString((char*)evScratch)); - - sprintf((char*)evScratch, "active_tx_len:\t\t\t0x%08x\r\n", tmpIMXUartDmaChan.active_tx_len); - event_outputEvToFile(fileName, evScratch, printCurString((char*)evScratch)); - - sprintf((char*)evScratch, "cfg.buf:\t\t\t\t0x%08x\r\n", tmpIMXUartDmaChan.cfg.buf); - event_outputEvToFile(fileName, evScratch, printCurString((char*)evScratch)); - - sprintf((char*)evScratch, "cfg.buf_len:\t\t\t0x%08x\r\n", tmpIMXUartDmaChan.cfg.buf_len); - event_outputEvToFile(fileName, evScratch, printCurString((char*)evScratch)); - - sprintf((char*)evScratch, "cfg.interrupt:\t\t\t0x%08x\r\n", tmpIMXUartDmaChan.cfg.interrupt); - event_outputEvToFile(fileName, evScratch, printCurString((char*)evScratch)); - - sprintf((char*)evScratch, "cfg.interrupt_priority:\t0x%08x\r\n", tmpIMXUartDmaChan.cfg.interrupt_priority); - event_outputEvToFile(fileName, evScratch, printCurString((char*)evScratch)); - - sprintf((char*)evScratch, "cfg.mode:\t\t\t\t0x%08x\r\n", tmpIMXUartDmaChan.cfg.mode); - event_outputEvToFile(fileName, evScratch, printCurString((char*)evScratch)); - - sprintf((char*)evScratch, "cfg.parent:\t\t\t\t0x%08x\r\n", tmpIMXUartDmaChan.cfg.parent); - event_outputEvToFile(fileName, evScratch, printCurString((char*)evScratch)); - - sprintf((char*)evScratch, "cfg.periph_reg:\t\t\t0x%08x\r\n", tmpIMXUartDmaChan.cfg.periph_reg); - event_outputEvToFile(fileName, evScratch, printCurString((char*)evScratch)); - - sprintf((char*)evScratch, "cfg.priority:\t\t\t0x%08x\r\n", tmpIMXUartDmaChan.cfg.priority); - event_outputEvToFile(fileName, evScratch, printCurString((char*)evScratch)); - - sprintf((char*)evScratch, "cfg.request_num:\t\t0x%08x\r\n", tmpIMXUartDmaChan.cfg.request_num); - event_outputEvToFile(fileName, evScratch, printCurString((char*)evScratch)); - - sprintf((char*)evScratch, "cfg.tc_handler:\t\t\t0x%08x\r\n", tmpIMXUartDmaChan.cfg.tc_handler); - event_outputEvToFile(fileName, evScratch, printCurString((char*)evScratch)); - - sprintf((char*)evScratch, "done:\t\t\t\t\t0x%08x\r\n", tmpIMXUartDmaChan.done); - event_outputEvToFile(fileName, evScratch, printCurString((char*)evScratch)); - - sprintf((char*)evScratch, "instance:\t\t\t\t0x%08x\r\n", tmpIMXUartDmaChan.instance); - event_outputEvToFile(fileName, evScratch, printCurString((char*)evScratch)); - - sprintf((char*)evScratch, "lastDmaUsed:\t\t\t0x%08x\r\n", tmpIMXUartDmaChan.lastDmaUsed); - event_outputEvToFile(fileName, evScratch, printCurString((char*)evScratch)); - - sprintf((char*)evScratch, "overflow:\t\t\t\t0x%08x\r\n", tmpIMXUartDmaChan.overflow); - event_outputEvToFile(fileName, evScratch, printCurString((char*)evScratch)); - - sprintf((char*)evScratch, "ptr_end:\t\t\t\t0x%08x\r\n", tmpIMXUartDmaChan.ptr_end); - event_outputEvToFile(fileName, evScratch, printCurString((char*)evScratch)); - - sprintf((char*)evScratch, "ptr_start:\t\t\t\t0x%08x\r\n", tmpIMXUartDmaChan.ptr_start); - event_outputEvToFile(fileName, evScratch, printCurString((char*)evScratch)); - - sprintf((char*)evScratch, "\r\n------------End IMX Dma Tx0 Channel-------------\r\n\r\n"); - event_outputEvToFile(fileName, evScratch, printCurString((char*)evScratch)); - + sprintf((char*)s_evScratch, "%s0x%08x\r\n", label, value); + event_outputEvToFile(s_evScratch, printCurString((char*)s_evScratch)); } -void writeIMXSer0TxCfg(uint8_t* evScratch, std::string fileName) +void writeIMXGpioReg(did_event_t* ev) { - sprintf((char*)evScratch, "------------Start IMX Ser0 Cfg-------------\r\n"); - event_outputEvToFile(fileName, evScratch, printCurString((char*)evScratch)); - - sprintf((char*)evScratch, "coding.baud:\t\t0x%08x\r\n", tmpUartCfg.coding.baudRate); - event_outputEvToFile(fileName, evScratch, printCurString((char*)evScratch)); - - sprintf((char*)evScratch, "coding.parity:\t\t0x%08x\r\n", tmpUartCfg.coding.parity); - event_outputEvToFile(fileName, evScratch, printCurString((char*)evScratch)); - - sprintf((char*)evScratch, "coding.stopBits:\t0x%08x\r\n", tmpUartCfg.coding.stopBits); - event_outputEvToFile(fileName, evScratch, printCurString((char*)evScratch)); - - sprintf((char*)evScratch, "interrupt:\t\t\t0x%08x\r\n", tmpUartCfg.interrupt); - event_outputEvToFile(fileName, evScratch, printCurString((char*)evScratch)); - - sprintf((char*)evScratch, "\r\n------------End IMX Ser0 Cfg-------------\r\n\r\n"); - event_outputEvToFile(fileName, evScratch, printCurString((char*)evScratch)); - + s_fileName = s_deviceFolder + "/IMX_GPIO.txt"; + assert(ev->length == sizeof(GPIO_TypeDef_IMX)); + if (ev->length > sizeof(GPIO_TypeDef_IMX)) return; + GPIO_TypeDef_IMX tmpIMXUartGpio = {}; + memcpy(&tmpIMXUartGpio, ev->data, ev->length); + sprintfLab("------------Start IMX GPIO Tx0 Reg-------------"); + sprintfU32("AFR[0]:\t\t", tmpIMXUartGpio.AFR[0]); + sprintfU32("AFR[1]:\t\t", tmpIMXUartGpio.AFR[1]); + sprintfU32("BRR:\t\t", tmpIMXUartGpio.BRR); + sprintfU32("BSRR:\t\t", tmpIMXUartGpio.BSRR); + sprintfU32("IDR:\t\t", tmpIMXUartGpio.IDR); + sprintfU32("LCKR:\t\t", tmpIMXUartGpio.LCKR); + sprintfU32("MODER:\t\t", tmpIMXUartGpio.MODER); + sprintfU32("ODR:\t\t", tmpIMXUartGpio.ODR); + sprintfU32("OSPEEDR:\t", tmpIMXUartGpio.OSPEEDR); + sprintfU32("OTYPER:\t\t", tmpIMXUartGpio.OTYPER); + sprintfU32("PUPDR:\t\t", tmpIMXUartGpio.PUPDR); + sprintfLab("------------End IMX GPIO Tx0 Reg-------------\r\n"); } -void writeIMXSer0TxReg(uint8_t* evScratch, std::string fileName) +void writeIMXDmaTx0Chan(did_event_t* ev) { - sprintf((char*)evScratch, "------------Start IMX Ser0 Reg-------------\r\n"); - event_outputEvToFile(fileName, evScratch, printCurString((char*)evScratch)); - - sprintf((char*)evScratch, "BRR:\t\t0x%08x\r\n", tmpIMXUartReg.BRR); - event_outputEvToFile(fileName, evScratch, printCurString((char*)evScratch)); - - sprintf((char*)evScratch, "CR1:\t\t0x%08x\r\n", tmpIMXUartReg.CR1); - event_outputEvToFile(fileName, evScratch, printCurString((char*)evScratch)); - - sprintf((char*)evScratch, "CR2:\t\t0x%08x\r\n", tmpIMXUartReg.CR2); - event_outputEvToFile(fileName, evScratch, printCurString((char*)evScratch)); - - sprintf((char*)evScratch, "CR3:\t\t0x%08x\r\n", tmpIMXUartReg.CR3); - event_outputEvToFile(fileName, evScratch, printCurString((char*)evScratch)); - - sprintf((char*)evScratch, "GTPR:\t\t0x%08x\r\n", tmpIMXUartReg.GTPR); - event_outputEvToFile(fileName, evScratch, printCurString((char*)evScratch)); - - sprintf((char*)evScratch, "ICR:\t\t0x%08x\r\n", tmpIMXUartReg.ICR); - event_outputEvToFile(fileName, evScratch, printCurString((char*)evScratch)); - - sprintf((char*)evScratch, "ISR:\t\t0x%08x\r\n", tmpIMXUartReg.ISR); - event_outputEvToFile(fileName, evScratch, printCurString((char*)evScratch)); - - sprintf((char*)evScratch, "RDR:\t\t0x%08x\r\n", tmpIMXUartReg.RDR); - event_outputEvToFile(fileName, evScratch, printCurString((char*)evScratch)); - - sprintf((char*)evScratch, "RQR:\t\t0x%08x\r\n", tmpIMXUartReg.RQR); - event_outputEvToFile(fileName, evScratch, printCurString((char*)evScratch)); - - sprintf((char*)evScratch, "RTOR:\t\t0x%08x\r\n", tmpIMXUartReg.RTOR); - event_outputEvToFile(fileName, evScratch, printCurString((char*)evScratch)); - - sprintf((char*)evScratch, "TDR:\t\t0x%08x\r\n", tmpIMXUartReg.TDR); - event_outputEvToFile(fileName, evScratch, printCurString((char*)evScratch)); - - sprintf((char*)evScratch, "RESERVED2:\t0x%08x\r\n", tmpIMXUartReg.RESERVED2); - event_outputEvToFile(fileName, evScratch, printCurString((char*)evScratch)); - - sprintf((char*)evScratch, "RESERVED3:\t0x%08x\r\n", tmpIMXUartReg.RESERVED3); - event_outputEvToFile(fileName, evScratch, printCurString((char*)evScratch)); - - sprintf((char*)evScratch, "RESERVED4:\t0x%08x\r\n", tmpIMXUartReg.RESERVED4); - event_outputEvToFile(fileName, evScratch, printCurString((char*)evScratch)); - - sprintf((char*)evScratch, "RESERVED5:\t0x%08x\r\n", tmpIMXUartReg.RESERVED5); - event_outputEvToFile(fileName, evScratch, printCurString((char*)evScratch)); - - sprintf((char*)evScratch, "\r\n------------End IMX Ser0 Reg-------------\r\n\r\n"); - event_outputEvToFile(fileName, evScratch, printCurString((char*)evScratch)); - + s_fileName = s_deviceFolder + "/IMX_DMA0_chan.txt"; + assert(ev->length == sizeof(dma_ch_t_IMX)); + if (ev->length > sizeof(dma_ch_t_IMX)) return; + dma_ch_t_IMX tmpIMXUartDmaChan = {}; + memcpy(&tmpIMXUartDmaChan, ev->data, ev->length); + sprintfLab("------------Start IMX Dma Tx0 Channel-------------"); + sprintfU32("instance:\t\t\t\t", tmpIMXUartDmaChan.instance); + sprintfU32("ptr_end:\t\t\t\t", tmpIMXUartDmaChan.ptr_end); + sprintfU32("ptr_start:\t\t\t\t", tmpIMXUartDmaChan.ptr_start); + sprintfU32("active_tx_len:\t\t\t", tmpIMXUartDmaChan.active_tx_len); + sprintfU32("done:\t\t\t\t\t", tmpIMXUartDmaChan.done); + sprintfU32("cfg.dir:\t\t\t\t", tmpIMXUartDmaChan.cfg.dir); + sprintfU32("cfg.circular:\t\t\t", tmpIMXUartDmaChan.cfg.circular); + sprintfU32("cfg.priority:\t\t\t", tmpIMXUartDmaChan.cfg.priority); + sprintfU32("cfg.interrupt:\t\t\t", static_cast(tmpIMXUartDmaChan.cfg.interrupt)); + sprintfU32("cfg.interrupt_priority:\t", tmpIMXUartDmaChan.cfg.interrupt_priority); + sprintfU32("cfg.dma_channel_select:\t", tmpIMXUartDmaChan.cfg.dma_channel_select); + sprintfU32("cfg.parent_type:\t\t", tmpIMXUartDmaChan.cfg.parent_type); + sprintfU32("cfg.parent:\t\t\t\t", tmpIMXUartDmaChan.cfg.parent); + sprintfU32("cfg.periph_reg:\t\t\t", tmpIMXUartDmaChan.cfg.periph_reg); + sprintfU32("cfg.buf:\t\t\t\t", tmpIMXUartDmaChan.cfg.buf); + sprintfU32("cfg.buf_len:\t\t\t", tmpIMXUartDmaChan.cfg.buf_len); + sprintfU32("cfg.linear_buf:\t\t\t", tmpIMXUartDmaChan.cfg.linear_buf); + sprintfU32("cfg.tcie_handler:\t\t", tmpIMXUartDmaChan.cfg.tcie_handler); + sprintfU32("lastDmaUsed:\t\t\t", tmpIMXUartDmaChan.lastDmaUsed); + sprintfU32("overflow:\t\t\t\t", tmpIMXUartDmaChan.overflow); + sprintfLab("------------End IMX Dma Tx0 Channel-------------\r\n"); } -void dataToImxDmaInst(uint8_t* inBuf, int len) +void writeSer0Cfg(did_event_t* ev, std::string name) { - int startIndex; - int endIndex; - - // do inital copy - memcpy(&tmpIMXUartDmaInst, inBuf, ((uint32_t)&tmpIMXUartDmaInst.ptr_start) - ((uint32_t)&tmpIMXUartDmaInst)); - - // now fix things - startIndex = 0x10; - tmpIMXUartDmaInst.ptr_start = (uint8_t*)((((uint32_t)inBuf[startIndex + 3]) << 24) | - (((uint32_t)inBuf[startIndex + 2]) << 16) | - (((uint16_t)inBuf[startIndex + 1]) << 8) | inBuf[startIndex]); - - startIndex = 0x14; - tmpIMXUartDmaInst.ptr_end = (uint8_t*)((((uint32_t)inBuf[startIndex+3]) << 24) | - (((uint32_t)inBuf[startIndex+2]) << 16) | - (((uint16_t)inBuf[startIndex+1]) << 8) | inBuf[startIndex]); - - startIndex = 0x18; - endIndex = 0x22; - memcpy(&tmpIMXUartDmaInst.active_tx_len, &inBuf[startIndex], endIndex - startIndex); - - startIndex = 0x22; - tmpIMXUartDmaInst.cfg_parent = (uint8_t*)((((uint32_t)inBuf[startIndex + 3]) << 24) | - (((uint32_t)inBuf[startIndex + 2]) << 16) | - (((uint16_t)inBuf[startIndex + 1]) << 8) | inBuf[startIndex]); - - startIndex = 0x26; - tmpIMXUartDmaInst.cfg_periph_reg = (uint32_t*)((((uint32_t)inBuf[startIndex + 3]) << 24) | - (((uint32_t)inBuf[startIndex + 2]) << 16) | - (((uint16_t)inBuf[startIndex + 1]) << 8) | inBuf[startIndex]); - - startIndex = 0x2a; - tmpIMXUartDmaInst.cfg_buf = (uint8_t*)((((uint32_t)inBuf[startIndex + 3]) << 24) | - (((uint32_t)inBuf[startIndex + 2]) << 16) | - (((uint16_t)inBuf[startIndex + 1]) << 8) | inBuf[startIndex]); - - startIndex = 0x2e; - endIndex = 0x31; - memcpy(&tmpIMXUartDmaInst.cfg_buf_len, &inBuf[startIndex], endIndex - startIndex); - - startIndex = 0x31; - tmpIMXUartDmaInst.cfg_tcie_handler = (uint8_t*)((((uint32_t)inBuf[startIndex + 3]) << 24) | - (((uint32_t)inBuf[startIndex + 2]) << 16) | - (((uint16_t)inBuf[startIndex + 1]) << 8) | inBuf[startIndex]); - - startIndex = 0x35; - endIndex = 0x3a; - memcpy(&tmpIMXUartDmaInst.lastDmaUsed, &inBuf[startIndex], endIndex - startIndex); - + s_fileName = s_deviceFolder + "/" + name + (name.size() ? "_" : "") + "Ser0_cfg.txt"; + assert(ev->length == sizeof(usart_cfg_t)); + if (ev->length > sizeof(usart_cfg_t)) return; + usart_cfg_t tmpUartCfg = {}; + memcpy(&tmpUartCfg, ev->data, ev->length); + name = std::string("------------Start ") + name + std::string(" Ser0 Cfg-------------"); + sprintfLab(name.c_str()); + sprintfU32("coding.baud:\t\t", tmpUartCfg.coding.baudRate); + sprintfU32("coding.parity:\t\t", tmpUartCfg.coding.parity); + sprintfU32("coding.stopBits:\t", tmpUartCfg.coding.stopBits); + sprintfU32("interrupt:\t\t\t", static_cast(tmpUartCfg.interrupt)); + sprintfLab("------------End Ser0 Cfg-------------\r\n"); } -void writeIMXDmaTx0Reg(uint8_t* evScratch, std::string fileName) +void writeIMXSer0TxReg(did_event_t* ev) { - sprintf((char*)evScratch, "------------Start IMX Dma Tx0 Inst-------------\r\n"); - event_outputEvToFile(fileName, evScratch, printCurString((char*)evScratch)); - - sprintf((char*)evScratch, "inst.CCR:\t\t\t\t0x%08x\r\n", tmpIMXUartDmaInst.inst_CCR); - event_outputEvToFile(fileName, evScratch, printCurString((char*)evScratch)); - - sprintf((char*)evScratch, "inst.CNDTR:\t\t\t\t0x%08x\r\n", tmpIMXUartDmaInst.inst_CNDTR); - event_outputEvToFile(fileName, evScratch, printCurString((char*)evScratch)); - - sprintf((char*)evScratch, "inst.CPAR:\t\t\t\t0x%08x\r\n", tmpIMXUartDmaInst.inst_CPAR); - event_outputEvToFile(fileName, evScratch, printCurString((char*)evScratch)); - - sprintf((char*)evScratch, "inst.CMAR:\t\t\t\t0x%08x\r\n", tmpIMXUartDmaInst.inst_CMAR); - event_outputEvToFile(fileName, evScratch, printCurString((char*)evScratch)); - - sprintf((char*)evScratch, "ptr_start:\t\t\t\t0x%08x\r\n", tmpIMXUartDmaInst.ptr_start); - event_outputEvToFile(fileName, evScratch, printCurString((char*)evScratch)); - - sprintf((char*)evScratch, "ptr_end:\t\t\t\t0x%08x\r\n", tmpIMXUartDmaInst.ptr_end); - event_outputEvToFile(fileName, evScratch, printCurString((char*)evScratch)); - - sprintf((char*)evScratch, "active_tx_len:\t\t\t0x%08x\r\n", tmpIMXUartDmaInst.active_tx_len); - event_outputEvToFile(fileName, evScratch, printCurString((char*)evScratch)); - - sprintf((char*)evScratch, "done:\t\t\t\t\t0x%08x\r\n", tmpIMXUartDmaInst.done); - event_outputEvToFile(fileName, evScratch, printCurString((char*)evScratch)); - - sprintf((char*)evScratch, "cfg.dir:\t\t\t\t0x%08x\r\n", tmpIMXUartDmaInst.cfg_dir); - event_outputEvToFile(fileName, evScratch, printCurString((char*)evScratch)); - - sprintf((char*)evScratch, "cfg.circular:\t\t\t0x%08x\r\n", tmpIMXUartDmaInst.cfg_circular); - event_outputEvToFile(fileName, evScratch, printCurString((char*)evScratch)); - - sprintf((char*)evScratch, "cfg.priority:\t\t\t0x%08x\r\n", tmpIMXUartDmaInst.cfg_priority); - event_outputEvToFile(fileName, evScratch, printCurString((char*)evScratch)); - - sprintf((char*)evScratch, "cfg.interrupt:\t\t\t0x%08x\r\n", tmpIMXUartDmaInst.cfg_interrupt); - event_outputEvToFile(fileName, evScratch, printCurString((char*)evScratch)); - - sprintf((char*)evScratch, "cfg.interrupt_priority:\t0x%08x\r\n", tmpIMXUartDmaInst.cfg_interrupt_priority); - event_outputEvToFile(fileName, evScratch, printCurString((char*)evScratch)); - - sprintf((char*)evScratch, "cfg.dma_chan_sel:\t\t0x%08x\r\n", tmpIMXUartDmaInst.cfg_dma_channel_select); - event_outputEvToFile(fileName, evScratch, printCurString((char*)evScratch)); - - sprintf((char*)evScratch, "cfg.parent_type:\t\t0x%08x\r\n", tmpIMXUartDmaInst.cfg_parent_type); - event_outputEvToFile(fileName, evScratch, printCurString((char*)evScratch)); - - sprintf((char*)evScratch, "cfg.parent:\t\t\t\t0x%08x\r\n", tmpIMXUartDmaInst.cfg_parent); - event_outputEvToFile(fileName, evScratch, printCurString((char*)evScratch)); - - sprintf((char*)evScratch, "cfg.periph_reg:\t\t\t0x%08x\r\n", tmpIMXUartDmaInst.cfg_periph_reg); - event_outputEvToFile(fileName, evScratch, printCurString((char*)evScratch)); - - sprintf((char*)evScratch, "cfg.buf:\t\t\t\t0x%08x\r\n", tmpIMXUartDmaInst.cfg_buf); - event_outputEvToFile(fileName, evScratch, printCurString((char*)evScratch)); - - sprintf((char*)evScratch, "cfg.buf_len:\t\t\t0x%08x\r\n", tmpIMXUartDmaInst.cfg_buf_len); - event_outputEvToFile(fileName, evScratch, printCurString((char*)evScratch)); - - sprintf((char*)evScratch, "cfg.linear_buf:\t\t\t0x%08x\r\n", tmpIMXUartDmaInst.cfg_linear_buf); - event_outputEvToFile(fileName, evScratch, printCurString((char*)evScratch)); - - sprintf((char*)evScratch, "cfg_tcie_handler:\t\t0x%08x\r\n", tmpIMXUartDmaInst.cfg_tcie_handler); - event_outputEvToFile(fileName, evScratch, printCurString((char*)evScratch)); - - sprintf((char*)evScratch, "lastDmaUsed:\t\t\t0x%08x\r\n", tmpIMXUartDmaInst.lastDmaUsed); - event_outputEvToFile(fileName, evScratch, printCurString((char*)evScratch)); - - sprintf((char*)evScratch, "overflow:\t\t\t\t0x%08x\r\n", tmpIMXUartDmaInst.overflow); - event_outputEvToFile(fileName, evScratch, printCurString((char*)evScratch)); - - sprintf((char*)evScratch, "\r\n------------End IMX Dma Rx0 Inst-------------\r\n\r\n"); - event_outputEvToFile(fileName, evScratch, printCurString((char*)evScratch)); + s_fileName = s_deviceFolder + "/IMX_Ser0_reg.txt"; + assert(ev->length == sizeof(USART_TypeDef_IMX)); + if (ev->length > sizeof(USART_TypeDef_IMX)) return; + USART_TypeDef_IMX tmpIMXUartReg = {}; + memcpy(&tmpIMXUartReg, ev->data, ev->length); + sprintfLab("------------Start IMX Ser0 Reg-------------"); + sprintfU32("BRR:\t\t", tmpIMXUartReg.BRR); + sprintfU32("CR1:\t\t", tmpIMXUartReg._CR1); + sprintfU32("CR2:\t\t", tmpIMXUartReg._CR2); + sprintfU32("CR3:\t\t", tmpIMXUartReg._CR3); + sprintfU32("GTPR:\t\t", tmpIMXUartReg.GTPR); + sprintfU32("ICR:\t\t", tmpIMXUartReg.ICR); + sprintfU32("ISR:\t\t", tmpIMXUartReg.ISR); + sprintfU32("RDR:\t\t", tmpIMXUartReg.RDR); + sprintfU32("RQR:\t\t", tmpIMXUartReg.RQR); + sprintfU32("RTOR:\t\t", tmpIMXUartReg.RTOR); + sprintfU32("TDR:\t\t", tmpIMXUartReg.TDR); + sprintfU32("RESERVED2:\t", tmpIMXUartReg.RESERVED2); + sprintfU32("RESERVED3:\t", tmpIMXUartReg.RESERVED3); + sprintfU32("RESERVED4:\t", tmpIMXUartReg.RESERVED4); + sprintfU32("RESERVED5:\t", tmpIMXUartReg.RESERVED5); + sprintfLab("------------End IMX Ser0 Reg-------------\r\n"); } -void writeDmaRx0Reg(uint8_t* evScratch, std::string fileName) +void writeIMXDmaTx0Reg(did_event_t* ev) { - sprintf((char*)evScratch, "------------Start Dma Rx0 Reg-------------\r\n"); - event_outputEvToFile(fileName, evScratch, printCurString((char*)evScratch)); - - sprintf((char*)evScratch, "CBR1:\t0x%08x\r\n", tmpUartDmaReg.CBR1); - event_outputEvToFile(fileName, evScratch, printCurString((char*)evScratch)); - - sprintf((char*)evScratch, "CBR2:\t0x%08x\r\n", tmpUartDmaReg.CBR2); - event_outputEvToFile(fileName, evScratch, printCurString((char*)evScratch)); - - sprintf((char*)evScratch, "CCR:\t0x%08x\r\n", tmpUartDmaReg.CCR); - event_outputEvToFile(fileName, evScratch, printCurString((char*)evScratch)); - - sprintf((char*)evScratch, "CDAR:\t0x%08x\r\n", tmpUartDmaReg.CDAR); - event_outputEvToFile(fileName, evScratch, printCurString((char*)evScratch)); - - sprintf((char*)evScratch, "CFCR:\t0x%08x\r\n", tmpUartDmaReg.CFCR); - event_outputEvToFile(fileName, evScratch, printCurString((char*)evScratch)); - - sprintf((char*)evScratch, "CLBAR:\t0x%08x\r\n", tmpUartDmaReg.CLBAR); - event_outputEvToFile(fileName, evScratch, printCurString((char*)evScratch)); - - sprintf((char*)evScratch, "CLLR:\t0x%08x\r\n", tmpUartDmaReg.CLLR); - event_outputEvToFile(fileName, evScratch, printCurString((char*)evScratch)); - - sprintf((char*)evScratch, "CSAR:\t0x%08x\r\n", tmpUartDmaReg.CSAR); - event_outputEvToFile(fileName, evScratch, printCurString((char*)evScratch)); - - sprintf((char*)evScratch, "CSR:\t0x%08x\r\n", tmpUartDmaReg.CSR); - event_outputEvToFile(fileName, evScratch, printCurString((char*)evScratch)); - - sprintf((char*)evScratch, "CTR1:\t0x%08x\r\n", tmpUartDmaReg.CTR1); - event_outputEvToFile(fileName, evScratch, printCurString((char*)evScratch)); - - sprintf((char*)evScratch, "CTR2:\t0x%08x\r\n", tmpUartDmaReg.CTR2); - event_outputEvToFile(fileName, evScratch, printCurString((char*)evScratch)); - - sprintf((char*)evScratch, "CTR3:\t0x%08x\r\n", tmpUartDmaReg.CTR3); - event_outputEvToFile(fileName, evScratch, printCurString((char*)evScratch)); - - sprintf((char*)evScratch, "\r\n------------End Dma Rx0 Reg-------------\r\n\r\n"); - event_outputEvToFile(fileName, evScratch, printCurString((char*)evScratch)); + s_fileName = s_deviceFolder + "/IMX_DMA0_inst.txt"; + assert(ev->length == sizeof(eventImxDmaTxInst_local_t)); + if (ev->length > sizeof(eventImxDmaTxInst_local_t)) return; + eventImxDmaTxInst_local_t tmpIMXUartDmaInst = {}; + memcpy(&tmpIMXUartDmaInst, ev->data, ev->length); + sprintfLab("------------Start IMX Dma Tx0 Inst-------------"); + sprintfU32("inst.CCR:\t\t\t\t", tmpIMXUartDmaInst.inst_CCR); + sprintfU32("inst.CNDTR:\t\t\t\t", tmpIMXUartDmaInst.inst_CNDTR); + sprintfU32("inst.CPAR:\t\t\t\t", tmpIMXUartDmaInst.inst_CPAR); + sprintfU32("inst.CMAR:\t\t\t\t", tmpIMXUartDmaInst.inst_CMAR); + sprintfU32("ptr_start:\t\t\t\t", tmpIMXUartDmaInst.ptr_start); + sprintfU32("ptr_end:\t\t\t\t", tmpIMXUartDmaInst.ptr_end); + sprintfU32("active_tx_len:\t\t\t", tmpIMXUartDmaInst.active_tx_len); + sprintfU32("done:\t\t\t\t\t", tmpIMXUartDmaInst.done); + sprintfU32("cfg.dir:\t\t\t\t", tmpIMXUartDmaInst.cfg_dir); + sprintfU32("cfg.circular:\t\t\t", tmpIMXUartDmaInst.cfg_circular); + sprintfU32("cfg.priority:\t\t\t", tmpIMXUartDmaInst.cfg_priority); + sprintfU32("cfg.interrupt:\t\t\t", tmpIMXUartDmaInst.cfg_interrupt); + sprintfU32("cfg.interrupt_priority:\t", tmpIMXUartDmaInst.cfg_interrupt_priority); + sprintfU32("cfg.dma_chan_sel:\t\t", tmpIMXUartDmaInst.cfg_dma_channel_select); + sprintfU32("cfg.parent_type:\t\t", tmpIMXUartDmaInst.cfg_parent_type); + sprintfU32("cfg.parent:\t\t\t\t", tmpIMXUartDmaInst.cfg_parent); + sprintfU32("cfg.periph_reg:\t\t\t", tmpIMXUartDmaInst.cfg_periph_reg); + sprintfU32("cfg.buf:\t\t\t\t", tmpIMXUartDmaInst.cfg_buf); + sprintfU32("cfg.buf_len:\t\t\t", tmpIMXUartDmaInst.cfg_buf_len); + sprintfU32("cfg.linear_buf:\t\t\t", tmpIMXUartDmaInst.cfg_linear_buf); + sprintfU32("cfg_tcie_handler:\t\t", tmpIMXUartDmaInst.cfg_tcie_handler); + sprintfU32("lastDmaUsed:\t\t\t", tmpIMXUartDmaInst.lastDmaUsed); + sprintfU32("overflow:\t\t\t\t", tmpIMXUartDmaInst.overflow); + sprintfLab("------------End IMX Dma Rx0 Inst-------------\r\n"); } -void writeSer0RxReg(uint8_t* evScratch, std::string fileName) +void writeGpxDmaRx0Reg(did_event_t* ev) { - sprintf((char*)evScratch, "------------Start Ser0 Reg-------------\r\n"); - event_outputEvToFile(fileName, evScratch, printCurString((char*)evScratch)); - - sprintf((char*)evScratch, "CR1:\t0x%08x\r\n", tmpUartReg.CR1); - event_outputEvToFile(fileName, evScratch, printCurString((char*)evScratch)); - - sprintf((char*)evScratch, "CR2:\t0x%08x\r\n", tmpUartReg.CR2); - event_outputEvToFile(fileName, evScratch, printCurString((char*)evScratch)); - - sprintf((char*)evScratch, "CR3:\t0x%08x\r\n", tmpUartReg.CR3); - event_outputEvToFile(fileName, evScratch, printCurString((char*)evScratch)); - - sprintf((char*)evScratch, "BRR:\t0x%08x\r\n", tmpUartReg.BRR); - event_outputEvToFile(fileName, evScratch, printCurString((char*)evScratch)); - - sprintf((char*)evScratch, "GTPR:\t0x%08x\r\n", tmpUartReg.GTPR); - event_outputEvToFile(fileName, evScratch, printCurString((char*)evScratch)); - - sprintf((char*)evScratch, "RTOR:\t0x%08x\r\n", tmpUartReg.RTOR); - event_outputEvToFile(fileName, evScratch, printCurString((char*)evScratch)); - - sprintf((char*)evScratch, "RQR:\t0x%08x\r\n", tmpUartReg.RQR); - event_outputEvToFile(fileName, evScratch, printCurString((char*)evScratch)); - - sprintf((char*)evScratch, "ISR:\t0x%08x\r\n", tmpUartReg.ISR); - event_outputEvToFile(fileName, evScratch, printCurString((char*)evScratch)); - - sprintf((char*)evScratch, "ICR:\t0x%08x\r\n", tmpUartReg.ICR); - event_outputEvToFile(fileName, evScratch, printCurString((char*)evScratch)); - - sprintf((char*)evScratch, "RDR:\t0x%08x\r\n", tmpUartReg.RDR); - event_outputEvToFile(fileName, evScratch, printCurString((char*)evScratch)); - - sprintf((char*)evScratch, "TDR:\t0x%08x\r\n", tmpUartReg.TDR); - event_outputEvToFile(fileName, evScratch, printCurString((char*)evScratch)); - - sprintf((char*)evScratch, "PRESC:\t0x%08x\r\n", tmpUartReg.PRESC); - event_outputEvToFile(fileName, evScratch, printCurString((char*)evScratch)); - - sprintf((char*)evScratch, "AUTOCR:\t0x%08x\r\n", tmpUartReg.AUTOCR); - event_outputEvToFile(fileName, evScratch, printCurString((char*)evScratch)); - - sprintf((char*)evScratch, "\r\n------------End Ser0 Reg-------------\r\n\r\n"); - event_outputEvToFile(fileName, evScratch, printCurString((char*)evScratch)); + s_fileName = s_deviceFolder + "/GPX_DMA0_reg.txt"; + assert(ev->length == sizeof(DMA_Channel_TypeDef)); + if (ev->length > sizeof(DMA_Channel_TypeDef)) return; + DMA_Channel_TypeDef tmpUartDmaReg = {}; + memcpy(&tmpUartDmaReg, ev->data, ev->length); + sprintfLab("------------Start Dma Rx0 Reg-------------"); + sprintfU32("CBR1:\t", tmpUartDmaReg.CBR1); + sprintfU32("CBR2:\t", tmpUartDmaReg.CBR2); + sprintfU32("CCR:\t", tmpUartDmaReg.CCR); + sprintfU32("CDAR:\t", tmpUartDmaReg.CDAR); + sprintfU32("CFCR:\t", tmpUartDmaReg.CFCR); + sprintfU32("CLBAR:\t", tmpUartDmaReg.CLBAR); + sprintfU32("CLLR:\t", tmpUartDmaReg.CLLR); + sprintfU32("CSAR:\t", tmpUartDmaReg.CSAR); + sprintfU32("CSR:\t", tmpUartDmaReg.CSR); + sprintfU32("CTR1:\t", tmpUartDmaReg.CTR1); + sprintfU32("CTR2:\t", tmpUartDmaReg.CTR2); + sprintfU32("CTR3:\t", tmpUartDmaReg.CTR3); + sprintfLab("------------End Dma Rx0 Reg-------------\r\n"); } -void writeSer0RxCfg(uint8_t* evScratch, std::string fileName) +void writeGpxSer0RxReg(did_event_t* ev) { - sprintf((char*)evScratch, "------------Start Ser0 Cfg-------------\r\n"); - event_outputEvToFile(fileName, evScratch, printCurString((char*)evScratch)); - - sprintf((char*)evScratch, "coding.baud:\t\t0x%08x\r\n", tmpUartCfg.coding.baudRate); - event_outputEvToFile(fileName, evScratch, printCurString((char*)evScratch)); - - sprintf((char*)evScratch, "coding.parity:\t\t0x%08x\r\n", tmpUartCfg.coding.parity); - event_outputEvToFile(fileName, evScratch, printCurString((char*)evScratch)); - - sprintf((char*)evScratch, "coding.stopBits:\t0x%08x\r\n", tmpUartCfg.coding.stopBits); - event_outputEvToFile(fileName, evScratch, printCurString((char*)evScratch)); - - sprintf((char*)evScratch, "interrupt:\t\t\t0x%08x\r\n", tmpUartCfg.interrupt); - event_outputEvToFile(fileName, evScratch, printCurString((char*)evScratch)); - - sprintf((char*)evScratch, "\r\n------------End Ser0 Cfg-------------\r\n\r\n"); - event_outputEvToFile(fileName, evScratch, printCurString((char*)evScratch)); + s_fileName = s_deviceFolder + "/GPX_Ser0_reg.txt"; + assert(ev->length == sizeof(USART_TypeDef)); + if (ev->length > sizeof(USART_TypeDef)) return; + USART_TypeDef tmpUartReg = {}; + memcpy(&tmpUartReg, ev->data, ev->length); + sprintfLab("------------Start Ser0 Reg-------------"); + sprintfU32("CR1:\t", tmpUartReg._CR1); + sprintfU32("CR2:\t", tmpUartReg._CR2); + sprintfU32("CR3:\t", tmpUartReg._CR3); + sprintfU32("BRR:\t", tmpUartReg.BRR); + sprintfU32("GTPR:\t", tmpUartReg.GTPR); + sprintfU32("RTOR:\t", tmpUartReg.RTOR); + sprintfU32("RQR:\t", tmpUartReg.RQR); + sprintfU32("ISR:\t", tmpUartReg.ISR); + sprintfU32("ICR:\t", tmpUartReg.ICR); + sprintfU32("RDR:\t", tmpUartReg.RDR); + sprintfU32("TDR:\t", tmpUartReg.TDR); + sprintfU32("PRESC:\t", tmpUartReg.PRESC); + sprintfU32("AUTOCR:\t", tmpUartReg.AUTOCR); + sprintfLab("------------End Ser0 Reg-------------\r\n"); } -void writeDma0RxChan(uint8_t* evScratch, std::string fileName) +void writeGpxDma0RxChan(did_event_t* ev) { - sprintf((char*)evScratch, "------------Start Dma Rx0 Channel-------------\r\n"); - event_outputEvToFile(fileName, evScratch, printCurString((char*)evScratch)); - - sprintf((char*)evScratch, "cfg.buf:\t\t\t\t0x%08x\r\n", tmpUartDmaChan.cfg.buf); - event_outputEvToFile(fileName, evScratch, printCurString((char*)evScratch)); - - sprintf((char*)evScratch, "cfg.buf_len:\t\t\t0x%08x\r\n", tmpUartDmaChan.cfg.buf_len); - event_outputEvToFile(fileName, evScratch, printCurString((char*)evScratch)); - - sprintf((char*)evScratch, "cfg.interrupt:\t\t\t0x%08x\r\n", tmpUartDmaChan.cfg.interrupt); - event_outputEvToFile(fileName, evScratch, printCurString((char*)evScratch)); - - sprintf((char*)evScratch, "cfg.interrupt_priority:\t0x%08x\r\n", tmpUartDmaChan.cfg.interrupt_priority); - event_outputEvToFile(fileName, evScratch, printCurString((char*)evScratch)); - - sprintf((char*)evScratch, "cfg.mode:\t\t\t\t0x%08x\r\n", tmpUartDmaChan.cfg.mode); - event_outputEvToFile(fileName, evScratch, printCurString((char*)evScratch)); - - sprintf((char*)evScratch, "cfg.parent:\t\t\t\t0x%08x\r\n", tmpUartDmaChan.cfg.parent); - event_outputEvToFile(fileName, evScratch, printCurString((char*)evScratch)); - - sprintf((char*)evScratch, "cfg.periph_reg:\t\t\t0x%08x\r\n", tmpUartDmaChan.cfg.periph_reg); - event_outputEvToFile(fileName, evScratch, printCurString((char*)evScratch)); - - sprintf((char*)evScratch, "cfg.priority:\t\t\t0x%08x\r\n", tmpUartDmaChan.cfg.priority); - event_outputEvToFile(fileName, evScratch, printCurString((char*)evScratch)); - - sprintf((char*)evScratch, "cfg.request_num:\t\t0x%08x\r\n", tmpUartDmaChan.cfg.request_num); - event_outputEvToFile(fileName, evScratch, printCurString((char*)evScratch)); - - sprintf((char*)evScratch, "cfg.tc_handler:\t\t\t0x%08x\r\n", tmpUartDmaChan.cfg.tc_handler); - event_outputEvToFile(fileName, evScratch, printCurString((char*)evScratch)); - - sprintf((char*)evScratch, "instance:\t\t\t\t0x%08x\r\n", tmpUartDmaChan.instance); - event_outputEvToFile(fileName, evScratch, printCurString((char*)evScratch)); - - sprintf((char*)evScratch, "lastDmaUsed:\t\t\t0x%08x\r\n", tmpUartDmaChan.lastDmaUsed); - event_outputEvToFile(fileName, evScratch, printCurString((char*)evScratch)); - - sprintf((char*)evScratch, "lli.rx:\t\t\t\t\t0x%08x\r\n", tmpUartDmaChan.lli.rx); - event_outputEvToFile(fileName, evScratch, printCurString((char*)evScratch)); - - sprintf((char*)evScratch, "lli.tx:\t\t\t\t\t0x%08x\r\n", tmpUartDmaChan.lli.tx); - event_outputEvToFile(fileName, evScratch, printCurString((char*)evScratch)); - - sprintf((char*)evScratch, "overflow:\t\t\t\t0x%08x\r\n", tmpUartDmaChan.overflow); - event_outputEvToFile(fileName, evScratch, printCurString((char*)evScratch)); - - sprintf((char*)evScratch, "ptr_end:\t\t\t\t0x%08x\r\n", tmpUartDmaChan.ptr_end); - event_outputEvToFile(fileName, evScratch, printCurString((char*)evScratch)); - - sprintf((char*)evScratch, "ptr_start:\t\t\t\t0x%08x\r\n", tmpUartDmaChan.ptr_start); - event_outputEvToFile(fileName, evScratch, printCurString((char*)evScratch)); - - sprintf((char*)evScratch, "txState.active_tx_len:\t0x%08x\r\n", tmpUartDmaChan.txState.active_tx_len); - event_outputEvToFile(fileName, evScratch, printCurString((char*)evScratch)); - - sprintf((char*)evScratch, "txState.dma_running:\t0x%08x\r\n", tmpUartDmaChan.txState.dma_running); - event_outputEvToFile(fileName, evScratch, printCurString((char*)evScratch)); - - sprintf((char*)evScratch, "txState.lli_head:\t\t0x%08x\r\n", tmpUartDmaChan.txState.lli_head); - event_outputEvToFile(fileName, evScratch, printCurString((char*)evScratch)); - - sprintf((char*)evScratch, "txState.lli_tail:\t\t0x%08x\r\n", tmpUartDmaChan.txState.lli_tail); - event_outputEvToFile(fileName, evScratch, printCurString((char*)evScratch)); - - sprintf((char*)evScratch, "\r\n------------End Dma Rx0 Channel-------------\r\n\r\n"); - event_outputEvToFile(fileName, evScratch, printCurString((char*)evScratch)); + s_fileName = s_deviceFolder + "/GPX_DMA0_chan.txt"; + assert(ev->length == sizeof(dma_ch_t_GPX)); + if (ev->length > sizeof(dma_ch_t_GPX)) return; + dma_ch_t_GPX tmpUartDmaChan = {}; + memcpy(&tmpUartDmaChan, ev->data, ev->length); + sprintfLab("------------Start Dma Rx0 Channel-------------"); + sprintfU32("cfg.buf:\t\t\t\t", tmpUartDmaChan.cfg.buf); + sprintfU32("cfg.buf_len:\t\t\t", tmpUartDmaChan.cfg.buf_len); + sprintfU32("cfg.interrupt:\t\t\t", static_cast(tmpUartDmaChan.cfg.interrupt)); + sprintfU32("cfg.interrupt_priority:\t", tmpUartDmaChan.cfg.interrupt_priority); + sprintfU32("cfg.mode:\t\t\t\t", tmpUartDmaChan.cfg.mode); + sprintfU32("cfg.parent:\t\t\t\t", tmpUartDmaChan.cfg.parent); + sprintfU32("cfg.periph_reg:\t\t\t", tmpUartDmaChan.cfg.periph_reg); + sprintfU32("cfg.priority:\t\t\t", tmpUartDmaChan.cfg.priority); + sprintfU32("cfg.request_num:\t\t", tmpUartDmaChan.cfg.request_num); + sprintfU32("cfg.tc_handler:\t\t\t", tmpUartDmaChan.cfg.tc_handler); + sprintfU32("instance:\t\t\t\t", tmpUartDmaChan.instance); + sprintfU32("lastDmaUsed:\t\t\t", tmpUartDmaChan.lastDmaUsed); + sprintfU32("lli.rx:\t\t\t\t\t", tmpUartDmaChan.lli.rx.cdar); + sprintfU32("lli.tx[0].br1:\t\t\t", tmpUartDmaChan.lli.tx[0].br1); + sprintfU32("lli.tx[0].sar:\t\t\t", tmpUartDmaChan.lli.tx[0].sar); + sprintfU32("lli.tx[0].llr:\t\t\t", tmpUartDmaChan.lli.tx[0].llr); + sprintfU32("lli.tx[1].br1:\t\t\t", tmpUartDmaChan.lli.tx[1].br1); + sprintfU32("lli.tx[1].sar:\t\t\t", tmpUartDmaChan.lli.tx[1].sar); + sprintfU32("lli.tx[1].llr:\t\t\t", tmpUartDmaChan.lli.tx[1].llr); + sprintfU32("lli.tx[2].br1:\t\t\t", tmpUartDmaChan.lli.tx[2].br1); + sprintfU32("lli.tx[2].sar:\t\t\t", tmpUartDmaChan.lli.tx[2].sar); + sprintfU32("lli.tx[2].llr:\t\t\t", tmpUartDmaChan.lli.tx[2].llr); + sprintfU32("overflow:\t\t\t\t", tmpUartDmaChan.overflow); + sprintfU32("ptr_end:\t\t\t\t", tmpUartDmaChan.ptr_end); + sprintfU32("ptr_start:\t\t\t\t", tmpUartDmaChan.ptr_start); + sprintfU32("txState.active_tx_len:\t", tmpUartDmaChan.txState.active_tx_len); + sprintfU32("txState.dma_running:\t", tmpUartDmaChan.txState.dma_running); + sprintfU32("txState.lli_head:\t\t", tmpUartDmaChan.txState.lli_head); + sprintfU32("txState.lli_tail:\t\t", tmpUartDmaChan.txState.lli_tail); + sprintfLab("------------End Dma Rx0 Channel-------------\r\n"); } -void writeGpioRxReg(uint8_t* evScratch, std::string fileName) +void writeGpxGpioRxReg(did_event_t* ev) { - sprintf((char*)evScratch, "------------Start GPIP Rx0 Reg-------------\r\n"); - event_outputEvToFile(fileName, evScratch, printCurString((char*)evScratch)); - - sprintf((char*)evScratch, "AFR[0]:\t\t0x%08x\r\n", tmpUartGpio.AFR[0]); - event_outputEvToFile(fileName, evScratch, printCurString((char*)evScratch)); - - sprintf((char*)evScratch, "AFR[1]:\t\t0x%08x\r\n", tmpUartGpio.AFR[1]); - event_outputEvToFile(fileName, evScratch, printCurString((char*)evScratch)); - - sprintf((char*)evScratch, "BRR:\t\t0x%08x\r\n", tmpUartGpio.BRR); - event_outputEvToFile(fileName, evScratch, printCurString((char*)evScratch)); - - sprintf((char*)evScratch, "BSRR:\t\t0x%08x\r\n", tmpUartGpio.BSRR); - event_outputEvToFile(fileName, evScratch, printCurString((char*)evScratch)); - - sprintf((char*)evScratch, "HSLVR:\t\t0x%08x\r\n", tmpUartGpio.HSLVR); - event_outputEvToFile(fileName, evScratch, printCurString((char*)evScratch)); - - sprintf((char*)evScratch, "IDR:\t\t0x%08x\r\n", tmpUartGpio.IDR); - event_outputEvToFile(fileName, evScratch, printCurString((char*)evScratch)); - - sprintf((char*)evScratch, "LCKR:\t\t0x%08x\r\n", tmpUartGpio.LCKR); - event_outputEvToFile(fileName, evScratch, printCurString((char*)evScratch)); - - sprintf((char*)evScratch, "MODER:\t\t0x%08x\r\n", tmpUartGpio.MODER); - event_outputEvToFile(fileName, evScratch, printCurString((char*)evScratch)); - - sprintf((char*)evScratch, "ODR:\t\t0x%08x\r\n", tmpUartGpio.ODR); - event_outputEvToFile(fileName, evScratch, printCurString((char*)evScratch)); - - sprintf((char*)evScratch, "OSPEEDR:\t0x%08x\r\n", tmpUartGpio.OSPEEDR); - event_outputEvToFile(fileName, evScratch, printCurString((char*)evScratch)); - - sprintf((char*)evScratch, "OTYPER:\t\t0x%08x\r\n", tmpUartGpio.OTYPER); - event_outputEvToFile(fileName, evScratch, printCurString((char*)evScratch)); - - sprintf((char*)evScratch, "PUPDR:\t\t0x%08x\r\n", tmpUartGpio.PUPDR); - event_outputEvToFile(fileName, evScratch, printCurString((char*)evScratch)); - - sprintf((char*)evScratch, "SECCFGR:\t0x%08x\r\n", tmpUartGpio.SECCFGR); - event_outputEvToFile(fileName, evScratch, printCurString((char*)evScratch)); - - sprintf((char*)evScratch, "\r\n------------End GPIP Rx0 Reg-------------\r\n\r\n"); - event_outputEvToFile(fileName, evScratch, printCurString((char*)evScratch)); + s_fileName = s_deviceFolder + "/GPX_GPIO_Rx0_reg.txt"; + assert(ev->length == sizeof(GPIO_TypeDef)); + if (ev->length > sizeof(GPIO_TypeDef)) return; + GPIO_TypeDef tmpUartGpio = {}; + memcpy(&tmpUartGpio, ev->data, ev->length); + sprintfLab("------------Start GPIO Rx0 Reg-------------"); + sprintfU32("AFR[0]:\t\t", tmpUartGpio.AFR[0]); + sprintfU32("AFR[1]:\t\t", tmpUartGpio.AFR[1]); + sprintfU32("BRR:\t\t", tmpUartGpio.BRR); + sprintfU32("BSRR:\t\t", tmpUartGpio.BSRR); + sprintfU32("HSLVR:\t\t", tmpUartGpio.HSLVR); + sprintfU32("IDR:\t\t", tmpUartGpio.IDR); + sprintfU32("LCKR:\t\t", tmpUartGpio.LCKR); + sprintfU32("MODER:\t\t", tmpUartGpio.MODER); + sprintfU32("ODR:\t\t", tmpUartGpio.ODR); + sprintfU32("OSPEEDR:\t", tmpUartGpio.OSPEEDR); + sprintfU32("OTYPER:\t\t", tmpUartGpio.OTYPER); + sprintfU32("PUPDR:\t\t", tmpUartGpio.PUPDR); + sprintfU32("SECCFGR:\t", tmpUartGpio.SECCFGR); + sprintfLab("------------End GPIO Rx0 Reg-------------\r\n"); } static void msgHandlerIsb(InertialSense* i, p_data_t* data, int pHandle) @@ -911,8 +659,7 @@ static void msgHandlerIsb(InertialSense* i, p_data_t* data, int pHandle) int main(int argc, char* argv[]) { is_comm_instance_t c; - uint8_t evScratch[SCRATCH_SIZE + DID_EVENT_HEADER_SIZE]; - c.rxBuf.start = evScratch; + c.rxBuf.start = s_evScratch; c.rxBuf.size = SCRATCH_SIZE + DID_EVENT_HEADER_SIZE; std::time_t logTime = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now()); std::string outDir = "out/";// + logTime; @@ -938,10 +685,10 @@ int main(int argc, char* argv[]) if (stat(outDir.c_str(), &info) == 0) { if (info.st_mode & S_IFDIR) - printf("Found output dir: %s\r\n", outDir); + std::cout << "Found output dir: " << outDir << std::endl; else { - printf("Output dir not a folder: %s\r\n", outDir); + std::cout << "Output dir not a folder: " << outDir << std::endl; return false; } } @@ -954,7 +701,6 @@ int main(int argc, char* argv[]) #else if (mkdir(outDir.c_str(), 0777)) #endif - std::cout << "Created output dir: " << outDir << std::endl; else { @@ -970,13 +716,13 @@ int main(int argc, char* argv[]) for (auto dl : logger.DeviceLogs()) { - std::string deviceFolder = outDir + "/SN-" + std::to_string(dl->SerialNumber()); + s_deviceFolder = outDir + "/SN-" + std::to_string(dl->SerialNumber()); - if (stat(deviceFolder.c_str(), &info) == 0) + if (stat(s_deviceFolder.c_str(), &info) == 0) { if (!(info.st_mode & S_IFDIR)) { - std::cout << "Output dir not a folder skipping: " << deviceFolder << std::endl; + std::cout << "Output dir not a folder skipping: " << s_deviceFolder << std::endl; continue; } } @@ -985,14 +731,14 @@ int main(int argc, char* argv[]) // the folder does not exist try to create it // creating output files #if PLATFORM_IS_WINDOWS - if (mkdir(deviceFolder.c_str()) == 0) + if (mkdir(s_deviceFolder.c_str()) == 0) #else - if (mkdir(deviceFolder.c_str(), 0777)) + if (mkdir(s_deviceFolder.c_str(), 0777)) #endif - std::cout << "Created output dir: " << deviceFolder << std::endl; + std::cout << "Created output dir: " << s_deviceFolder << std::endl; else { - std::cout << "Failed to created output dir: " << deviceFolder << std::endl; + std::cout << "Failed to created output dir: " << s_deviceFolder << std::endl; continue; } } @@ -1008,107 +754,84 @@ int main(int argc, char* argv[]) if (d.hdr.id == DID_EVENT) { did_event_t* ev = (did_event_t*)data->buf; - memset(evScratch, 0, SCRATCH_SIZE + DID_EVENT_HEADER_SIZE); - memcpy(evScratch, ev->data, ev->length); - memcpy(&tmpUartReg, evScratch, ev->length); - memcpy(&tmpUartCfg, evScratch, ev->length); - memcpy(&tmpUartDmaReg, evScratch, ev->length); - memcpy(&tmpUartDmaChan, evScratch, ev->length); - memcpy(&tmpUartGpio, evScratch, ev->length); - - memcpy(&tmpIMXUartReg, evScratch, ev->length); - memcpy(&tmpIMXUartDmaChan, evScratch, ev->length); - memcpy(&tmpIMXUartGpio, evScratch, ev->length); - - std::string fileName; + memset(s_evScratch, 0, SCRATCH_SIZE + DID_EVENT_HEADER_SIZE); + memcpy(s_evScratch, ev->data, _MIN(ev->length, sizeof(s_evScratch))); switch (ev->msgTypeID) { - case EVENT_MSG_TYPE_ID_RAW: fileName = deviceFolder + "/out.raw"; break; - case EVENT_MSG_TYPE_ID_ASCII: fileName = deviceFolder + "/out.txt"; break; + case EVENT_MSG_TYPE_ID_RAW: s_fileName = s_deviceFolder + "/out.raw"; break; + case EVENT_MSG_TYPE_ID_ASCII: s_fileName = s_deviceFolder + "/out.txt"; break; case EVENT_MSG_TYPE_ID_RTMC3_RCVR1: - fileName = deviceFolder + "/rcvr1.rtcm"; + s_fileName = s_deviceFolder + "/rcvr1.rtcm"; c.rxBuf.size = ev->length; - c.rxBuf.head = evScratch; - c.rxBuf.end = evScratch + ev->length; - c.rxBuf.tail = evScratch + ev->length; - c.rxBuf.scan = evScratch; + c.rxBuf.head = s_evScratch; + c.rxBuf.end = s_evScratch + ev->length; + c.rxBuf.tail = s_evScratch + ev->length; + c.rxBuf.scan = s_evScratch; c.processPkt = nullptr; is_comm_parse_timeout(&c, 0); break; - case EVENT_MSG_TYPE_ID_RTMC3_RCVR2: fileName = deviceFolder + "/rcvr2.rtcm"; break; - case EVENT_MSG_TYPE_ID_RTMC3_EXT: fileName = deviceFolder + "/rcvr_ext.rtcm"; break; - case EVENT_MSG_TYPE_ID_SONY_BIN_RCVR1: fileName = deviceFolder + "/rcvr1.sbp"; break; - case EVENT_MSG_TYPE_ID_SONY_BIN_RCVR2: fileName = deviceFolder + "/rcvr2.sbp"; break; + case EVENT_MSG_TYPE_ID_RTMC3_RCVR2: s_fileName = s_deviceFolder + "/rcvr2.rtcm"; break; + case EVENT_MSG_TYPE_ID_RTMC3_EXT: s_fileName = s_deviceFolder + "/rcvr_ext.rtcm"; break; + case EVENT_MSG_TYPE_ID_SONY_BIN_RCVR1: s_fileName = s_deviceFolder + "/rcvr1.sbp"; break; + case EVENT_MSG_TYPE_ID_SONY_BIN_RCVR2: s_fileName = s_deviceFolder + "/rcvr2.sbp"; break; case EVENT_MSG_TYPE_ID_IMX_DMA_TX_0_INST: - fileName = deviceFolder + "/IMX_DMA0_inst.txt"; - dataToImxDmaInst(ev->data, ev->length); - writeIMXDmaTx0Reg(evScratch, fileName); + writeIMXDmaTx0Reg(ev); logged = true; break; case EVENT_MSG_TYPE_ID_IMX_SER0_REG: - fileName = deviceFolder + "/IMX_SER0_reg.txt"; - writeIMXSer0TxReg(evScratch, fileName); + writeIMXSer0TxReg(ev); logged = true; break; case EVENT_MSG_TYPE_ID_IMX_SER0_CFG: - fileName = deviceFolder + "/IMX_SER0_chan.txt"; - writeIMXSer0TxCfg(evScratch, fileName); + writeSer0Cfg(ev, "IMX"); logged = true; break; case EVENT_MSG_TYPE_ID_IMX_DMA_TX_0_CHAN: - fileName = deviceFolder + "/IMX_DMA0_chan.txt"; - writeIMXDmaTx0Chan(evScratch, fileName); + writeIMXDmaTx0Chan(ev); logged = true; break; case EVENT_MSG_TYPE_ID_IMX_GPIO_TX_0_REG: - fileName = deviceFolder + "/IMX_GPIO.txt"; - writeIMXGpioReg(evScratch, fileName); + writeIMXGpioReg(ev); logged = true; break; - case EVENT_MSG_TYPE_ID_DMA_RX_0_INST: - fileName = deviceFolder + "/DMA0_reg.txt"; - writeDmaRx0Reg(evScratch, fileName); + case EVENT_MSG_TYPE_ID_GPX_DMA_RX_0_INST: + writeGpxDmaRx0Reg(ev); logged = true; break; - case EVENT_MSG_TYPE_ID_SER0_REG: - fileName = deviceFolder + "/Ser0_reg.txt"; - writeSer0RxReg(evScratch, fileName); + case EVENT_MSG_TYPE_ID_GPX_SER0_REG: + writeGpxSer0RxReg(ev); logged = true; break; - case EVENT_MSG_TYPE_ID_SER0_CFG: - fileName = deviceFolder + "/Ser0_cfg.txt"; - writeSer0RxCfg(evScratch, fileName); + case EVENT_MSG_TYPE_ID_GPX_SER0_CFG: + writeSer0Cfg(ev, "GPX"); logged = true; break; - case EVENT_MSG_TYPE_ID_DMA_RX_0_CHAN: - fileName = deviceFolder + "/DMA0_chan.txt"; - writeDma0RxChan(evScratch, fileName); + case EVENT_MSG_TYPE_ID_GPX_DMA_RX_0_CHAN: + writeGpxDma0RxChan(ev); logged = true; break; - - case EVENT_MSG_TYPE_ID_GPIO_RX_0_REG: - fileName = deviceFolder + "/GPIO_Rx0_reg.txt"; - writeGpioRxReg(evScratch, fileName); + case EVENT_MSG_TYPE_ID_GPX_GPIO_RX_0_REG: + writeGpxGpioRxReg(ev); logged = true; break; default: - fileName = deviceFolder + "/UNKNOWN_" + std::to_string(ev->msgTypeID) + ".Bin"; - printf("Event type %d found but is not supported. Output at: %s\n", ev->msgTypeID, fileName.c_str()); + s_fileName = s_deviceFolder + "/UNKNOWN_" + std::to_string(ev->msgTypeID) + ".Bin"; + printf("Event type %d found but is not supported. Output at: %s\n", ev->msgTypeID, s_fileName.c_str()); break; } if (!logged) - event_outputEvToFile(fileName, evScratch, ev->length); + event_outputEvToFile(s_evScratch, ev->length); logged = false; } diff --git a/ExampleProjects/InertialSense_log_reader_RegCmp/setup_debug.sh b/ExampleProjects/InertialSense_log_reader_RegCmp/setup_debug.sh new file mode 100755 index 000000000..cc6dd15fb --- /dev/null +++ b/ExampleProjects/InertialSense_log_reader_RegCmp/setup_debug.sh @@ -0,0 +1,11 @@ +#!/bin/bash + +pushd "$(dirname "$(realpath $0)")" > /dev/null + +mkdir -p build +rm -rf build/* +cd build +cmake -DCMAKE_BUILD_TYPE=Debug .. +make -j 7 + +popd > /dev/null diff --git a/python/inertialsense/logInspector/logInspector.py b/python/inertialsense/logInspector/logInspector.py index 12566ea51..43f0cd6cf 100644 --- a/python/inertialsense/logInspector/logInspector.py +++ b/python/inertialsense/logInspector/logInspector.py @@ -451,6 +451,9 @@ def createListGps(self): self.addListItem('GPS LLA', 'gpsLLA') self.addListItem('GPS 1 Stats', 'gpsStats') self.addListItem('GPS 2 Stats', 'gps2Stats') + self.addListItem('GPS Time', 'gpsTime') + self.addListItem('GPX Status', 'gpxStatus') + self.addListItem('GPX HDW Status', 'gpxHdwStatus') self.addListItem('RTK Pos Stats', 'rtkPosStats') self.addListItem('RTK Cmp Stats', 'rtkCmpStats') self.addListItem('RTK Cmp BaseVector', 'rtkBaselineVector') diff --git a/python/inertialsense/logInspector/logPlotter.py b/python/inertialsense/logInspector/logPlotter.py index 54daca654..72e152679 100644 --- a/python/inertialsense/logInspector/logPlotter.py +++ b/python/inertialsense/logInspector/logPlotter.py @@ -2923,27 +2923,31 @@ def deltatime(self, fig=None, axs=None): if np.any(timeRef): refImuPresent = True - N = 4 + N = 5 if refImuPresent: N = N + 2 ax = fig.subplots(N, 1, sharex=True) fig.suptitle('Timestamps - ' + os.path.basename(os.path.normpath(self.log.directory))) self.configureSubplot(ax[0], 'INS dt', 's') - self.configureSubplot(ax[1], 'GPS dt', 's') - self.configureSubplot(ax[2], 'IMU Integration Period', 's') - self.configureSubplot(ax[3], 'IMU Delta Timestamp', 's') + self.configureSubplot(ax[1], 'GPS1 dt', 's') + self.configureSubplot(ax[2], 'GPS2 dt', 's') + self.configureSubplot(ax[3], 'IMU Integration Period', 's') + self.configureSubplot(ax[4], 'IMU Delta Timestamp', 's', xlabel = 'Message Index' if self.xAxisSample else 'Time of Week' ) for d in self.active_devs_no_ref: dtIns = self.getData(d, DID_INS_2, 'timeOfWeek')[1:] - self.getData(d, DID_INS_2, 'timeOfWeek')[0:-1] dtIns = dtIns / self.d timeIns = getTimeFromGpsTow(self.getData(d, DID_INS_2, 'timeOfWeek')[1:], True) - towMsGps = self.getData(d, DID_GPS1_POS, 'timeOfWeekMs')[1:] - weekGps = self.getData(d, DID_GPS1_POS, 'week')[1:] - dtGps = 0.001*(towMsGps - self.getData(d, DID_GPS1_POS, 'timeOfWeekMs')[0:-1]) - dtGps = dtGps / self.d - timeGps = getTimeFromGpsTowMs(towMsGps) + towMsGps1 = self.getData(d, DID_GPS1_POS, 'timeOfWeekMs')[1:] + towMsGps2 = self.getData(d, DID_GPS2_POS, 'timeOfWeekMs')[1:] + dtGps1 = 0.001*(towMsGps1 - self.getData(d, DID_GPS1_POS, 'timeOfWeekMs')[0:-1]) + dtGps2 = 0.001*(towMsGps2 - self.getData(d, DID_GPS2_POS, 'timeOfWeekMs')[0:-1]) + dtGps1 = dtGps1 / self.d + dtGps2 = dtGps2 / self.d + timeGps1 = getTimeFromGpsTowMs(towMsGps1) + timeGps2 = getTimeFromGpsTowMs(towMsGps2) dtPimu = self.getData(d, DID_PIMU, 'dt') if dtPimu.size: @@ -2975,20 +2979,39 @@ def deltatime(self, fig=None, axs=None): deltaTimestamp = deltaTimestamp / self.d timeImu = getTimeFromGpsTow(timeImu3[1:] + towOffset) +<<<<<<< HEAD:python/inertialsense/logInspector/logPlotter.py ax[0].plot(timeIns, dtIns, label=self.log.serials[d]) ax[1].plot(timeGps, dtGps) if integrationPeriod.size: ax[2].plot(timeImu, integrationPeriod) ax[3].plot(timeImu, deltaTimestamp) +======= + if self.xAxisSample: + xIns = np.arange(0, np.shape(dtIns)[0]) + xGps1 = np.arange(0, np.shape(dtGps1)[0]) + xGps2 = np.arange(0, np.shape(dtGps2)[0]) + xImu = np.arange(0, np.shape(deltaTimestamp)[0]) + else: + xIns = timeIns + xGps1 = timeGps1 + xGps2 = timeGps2 + xImu = timeImu + + ax[0].plot(xIns, dtIns, label=self.log.serials[d]) + ax[1].plot(xGps1, dtGps1) + ax[2].plot(xGps2, dtGps2) + if integrationPeriod.size: + ax[3].plot(xImu, integrationPeriod) + ax[4].plot(xImu, deltaTimestamp) +>>>>>>> origin/2.2.2-rc:python/logInspector/logPlotter.py - self.setPlotYSpanMin(ax[0], 0.005) - self.setPlotYSpanMin(ax[1], 0.005) - self.setPlotYSpanMin(ax[2], 0.005) - self.setPlotYSpanMin(ax[3], 0.005) + # Don't zoom in closer than 0.005s so we can easily see that the delta time is clean + for i in range(len(ax)): + self.setPlotYSpanMin(ax[i], 0.005) if refImuPresent: - self.configureSubplot(ax[4], 'Reference IMU Integration Period', 's') - self.configureSubplot(ax[5], 'Reference IMU Delta Timestamp', 's') + self.configureSubplot(ax[5], 'Reference IMU Integration Period', 's') + self.configureSubplot(ax[6], 'Reference IMU Delta Timestamp', 's') for d in self.active_devs: deltaTimestampRef = 0 timeImuRef = 0 @@ -2998,10 +3021,63 @@ def deltatime(self, fig=None, axs=None): deltaTimestampRef = timeRef[1:] - timeRef[0:-1] deltaTimestampRef = deltaTimestampRef / self.d timeImuRef = getTimeFromGpsTow(timeRef[1:] + towOffset) - ax[4].plot(timeImuRef, integrationPeriodRef) - ax[5].plot(timeImuRef, deltaTimestampRef) - self.setPlotYSpanMin(ax[4], 0.005) - self.setPlotYSpanMin(ax[5], 0.005) + ax[5].plot(timeImuRef, integrationPeriodRef) + ax[6].plot(timeImuRef, deltaTimestampRef) + + self.legends_add(ax[0].legend(ncol=2)) + for a in ax: + a.grid(True) + + self.setup_and_wire_legend() + return self.saveFigJoinAxes(ax, axs, fig, 'deltatime') + + def gpsTime(self, fig=None, axs=None): + if fig is None: + fig = plt.figure() + + refImuPresent = False + for d in self.active_devs: + timeRef = self.getData(d, DID_REFERENCE_PIMU, 'time') + if np.any(timeRef): + refImuPresent = True + + N = 4 + ax = fig.subplots(N, 1, sharex=(self.xAxisSample==0)) + + fig.suptitle('Timestamps - ' + os.path.basename(os.path.normpath(self.log.directory))) + self.configureSubplot(ax[0], 'GPS1 dt', 's') + self.configureSubplot(ax[1], 'GPS2 dt', 's') + self.configureSubplot(ax[2], 'GPS1 TOW Offset', 's') + self.configureSubplot(ax[3], 'GPS2 TOW Offset', 's') + + for d in self.active_devs_no_ref: + towMsGps1 = self.getData(d, DID_GPS1_POS, 'timeOfWeekMs')[1:] + towMsGps2 = self.getData(d, DID_GPS2_POS, 'timeOfWeekMs')[1:] + dtGps1 = 0.001*(towMsGps1 - self.getData(d, DID_GPS1_POS, 'timeOfWeekMs')[0:-1]) + dtGps2 = 0.001*(towMsGps2 - self.getData(d, DID_GPS2_POS, 'timeOfWeekMs')[0:-1]) + dtGps1 = dtGps1 / self.d + dtGps2 = dtGps2 / self.d + timeGps1 = getTimeFromGpsTowMs(towMsGps1) + timeGps2 = getTimeFromGpsTowMs(towMsGps2) + + towOffsetGps1 = self.getData(d, DID_GPS1_POS, 'towOffset')[1:] + towOffsetGps2 = self.getData(d, DID_GPS2_POS, 'towOffset')[1:] + + if self.xAxisSample: + xGps1 = np.arange(0, np.shape(dtGps1)[0]) + xGps2 = np.arange(0, np.shape(dtGps2)[0]) + else: + xGps1 = timeGps1 + xGps2 = timeGps2 + + ax[0].plot(xGps1, dtGps1) + ax[1].plot(xGps2, dtGps2) + ax[2].plot(xGps1, towOffsetGps1) + ax[3].plot(xGps2, towOffsetGps2) + + # Don't zoom in closer than 0.005s so we can easily see that the delta time is clean + for i in range(len(ax)): + self.setPlotYSpanMin(ax[i], 0.005) self.legends_add(ax[0].legend(ncol=2)) for a in ax: diff --git a/scripts/build_manager.py b/scripts/build_manager.py index 1789e6f16..1df163ffe 100644 --- a/scripts/build_manager.py +++ b/scripts/build_manager.py @@ -138,18 +138,19 @@ def test_footer(self, exit_code): print("") def print_summary(self): - if self.run_clean: - action = "CLEAN" - else: - action = "BUILD" - self.print_blu(f"==========================================") - self.print_blu(f" {action} SUMMARY:") - self.print_blu(f"==========================================") - if self.build_success: - self.print_grn(f"[PASSED]: " + ", ".join(self.build_success)) - if self.build_failure: - self.print_red(f"[FAILED]: " + ", ".join(self.build_failure)) - print("") + if self.run_build: + if self.run_clean: + action = "CLEAN" + else: + action = "BUILD" + self.print_blu(f"==========================================") + self.print_blu(f" {action} SUMMARY:") + self.print_blu(f"==========================================") + if self.build_success: + self.print_grn(f"[PASSED]: " + ", ".join(self.build_success)) + if self.build_failure: + self.print_red(f"[FAILED]: " + ", ".join(self.build_failure)) + print("") if self.run_test: self.print_cyn(f"==========================================") self.print_cyn(f" TEST SUMMARY:") @@ -162,6 +163,8 @@ def print_summary(self): self.print_release_info() def build_callback(self, project_name, callback): + if not self.run_build: + return result = 0 self.build_header(project_name) result = callback(self.args) @@ -181,6 +184,8 @@ def test_callback(self, project_name, callback): return result def build_script(self, project_name, script_path, args=[]): + if not self.run_build: + return if self.is_windows: command = ["cmd", "/c", str(script_path)] else: @@ -205,6 +210,8 @@ def build_script(self, project_name, script_path, args=[]): return result def build_cmake(self, project_name, project_dir): + if not self.run_build: + return project_dir = Path(project_dir) self.build_header(project_name) diff --git a/src/ISConstants.h b/src/ISConstants.h index 9c936d505..7b246611b 100644 --- a/src/ISConstants.h +++ b/src/ISConstants.h @@ -313,8 +313,12 @@ extern "C" { #define _LIMIT2(x, xmin, xmax) { if ((x) < (xmin)) { (x) = (xmin); } else { if ((x) > (xmax)) { (x) = (xmax); } } } #endif +#ifndef _ROUND_NEAREST +#define _ROUND_NEAREST(number, multiple) ((((number) + ((multiple)/2)) / (multiple)) * (multiple)) +#endif + #ifndef _ROUND_CLOSEST -#define _ROUND_CLOSEST(dividend, divisor) (((dividend) + ((divisor)/2)) / (divisor)) +#define _ROUND_CLOSEST(number, multiple) (((number) + ((multiple)/2)) / (multiple)) #endif #ifndef _ROUNDUP diff --git a/src/data_sets.h b/src/data_sets.h index 00382bfc8..91e64fb30 100644 --- a/src/data_sets.h +++ b/src/data_sets.h @@ -1473,8 +1473,13 @@ enum eGenFaultCodes GFC_INIT_I2C = 0x00800000, /*! Fault: Chip erase line toggled but did not meet required hold time. This is caused by noise/transient on chip erase pin. */ GFC_CHIP_ERASE_INVALID = 0x01000000, - /*! Fault: GPS time fault */ - GFC_GNSS_TIME_FAULT = 0x02000000, + /*! Fault: EKF GPS time fault */ + GFC_EKF_GNSS_TIME_FAULT = 0x02000000, + /*! Fault: GPS receiver time fault */ + GFC_GNSS_RECEIVER_TIME = 0x04000000, + + /*! IMX GFC flags that relate to GPX status flags */ + GFC_GPX_STATUS_COMMON_MASK = GFC_GNSS1_INIT | GFC_GNSS2_INIT | GFC_GNSS_TX_LIMITED | GFC_GNSS_RX_OVERRUN | GFC_GNSS_SYS_FAULT | GFC_GNSS_RECEIVER_TIME, }; @@ -1603,7 +1608,7 @@ typedef struct PACKED nmeaBroadcastMsgPair_t nmeaBroadcastMsgs[MAX_nmeaBroadcastMsgPairs]; /* Example usage: - * If you are setting message GGA (6) at 1Hz and GGL (7) at 5Hz with the default DID_FLASH_CONFIG.startupGpsDtMs = 200 (5Hz) + * If you are setting message GGA (6) at 1Hz and GGL (7) at 5Hz with the default DID_FLASH_CONFIG.startupGPSDtMs = 200 (5Hz) * nmeaBroadcastMsgs[0].msgID = 6, nmeaBroadcastMsgs[0].msgPeriod = 5 * nmeaBroadcastMsgs[1].msgID = 7, nmeaBroadcastMsgs[1].msgPeriod = 1 */ @@ -1743,7 +1748,7 @@ typedef struct PACKED #define RMC_BITS_MAGNETOMETER 0x0000000000000080 // ~10ms // #define RMC_BITS_UNUSED 0x0000000000000100 // #define RMC_BITS_UNUSED 0x0000000000000200 -#define RMC_BITS_GPS1_POS 0x0000000000000400 // DID_FLASH_CONFIG.startupGpsDtMs (200ms default) +#define RMC_BITS_GPS1_POS 0x0000000000000400 // DID_FLASH_CONFIG.startupGPSDtMs (200ms default) #define RMC_BITS_GPS2_POS 0x0000000000000800 // " #define RMC_BITS_GPS1_RAW 0x0000000000001000 // " #define RMC_BITS_GPS2_RAW 0x0000000000002000 // " @@ -1753,7 +1758,7 @@ typedef struct PACKED #define RMC_BITS_STROBE_IN_TIME 0x0000000000020000 // On strobe input event #define RMC_BITS_DIAGNOSTIC_MESSAGE 0x0000000000040000 #define RMC_BITS_IMU3_UNCAL 0x0000000000080000 // DID_FLASH_CONFIG.startupImuDtMs (1ms default) -#define RMC_BITS_GPS1_VEL 0x0000000000100000 // DID_FLASH_CONFIG.startupGpsDtMs (200ms default) +#define RMC_BITS_GPS1_VEL 0x0000000000100000 // DID_FLASH_CONFIG.startupGPSDtMs (200ms default) #define RMC_BITS_GPS2_VEL 0x0000000000200000 // " #define RMC_BITS_GPS1_UBX_POS 0x0000000000400000 // " #define RMC_BITS_GPS1_RTK_POS 0x0000000000800000 // " @@ -1768,7 +1773,7 @@ typedef struct PACKED // #define RMC_BITS_UNUSED 0x0000000200000000 #define RMC_BITS_IMU_MAG 0x0000000400000000 #define RMC_BITS_PIMU_MAG 0x0000000800000000 -#define RMC_BITS_GPS1_RTK_HDG_REL 0x0000001000000000 // DID_FLASH_CONFIG.startupGpsDtMs (200ms default) +#define RMC_BITS_GPS1_RTK_HDG_REL 0x0000001000000000 // DID_FLASH_CONFIG.startupGPSDtMs (200ms default) #define RMC_BITS_GPS1_RTK_HDG_MISC 0x0000002000000000 // " #define RMC_BITS_REFERENCE_IMU 0x0000004000000000 // DID_FLASH_CONFIG.startupNavDtMs #define RMC_BITS_REFERENCE_PIMU 0x0000008000000000 // " @@ -1815,11 +1820,13 @@ typedef struct PACKED #define RMC_PRESET_IMX_PPD (RMC_PRESET_IMX_PPD_NO_IMU \ | RMC_BITS_PIMU \ | RMC_BITS_REFERENCE_PIMU) +#define RMC_PRESET_IMX_PPD_IMU3_RAW (RMC_PRESET_IMX_PPD_NO_IMU \ + | RMC_BITS_IMU3_RAW) +#define RMC_PRESET_IMX_PPD_IMU3_UNCAL (RMC_PRESET_IMX_PPD_NO_IMU \ + | RMC_BITS_IMU3_UNCAL) #define RMC_PRESET_INS (RMC_BITS_INS2 \ | RMC_BITS_GPS1_POS \ | RMC_BITS_PRESET) -#define RMC_PRESET_IMX_PPD_IMU3 (RMC_PRESET_IMX_PPD_NO_IMU \ - | RMC_BITS_IMU3_UNCAL) #define RMC_PRESET_IMX_PPD_RTK_DBG (RMC_PRESET_IMX_PPD \ | RMC_BITS_RTK_STATE \ | RMC_BITS_RTK_CODE_RESIDUAL \ @@ -4475,6 +4482,9 @@ enum eGpxStatus /** Reserved */ GPX_STATUS_RESERVED_1 = (int)0x00010000, + /** GNSS receiver time fault **/ + GPX_STATUS_GNSS_RCVR_TIME_FAULT = (int)0x00100000, + /** DMA Fault detected **/ GPX_STATUS_DMA_FAULT = (int)0x00800000, @@ -5040,11 +5050,11 @@ enum eEventMsgTypeID EVENT_MSG_TYPE_ID_IMX_DMA_TX_0_CHAN = 25, EVENT_MSG_TYPE_ID_IMX_GPIO_TX_0_REG = 26, - EVENT_MSG_TYPE_ID_DMA_RX_0_INST = 27, - EVENT_MSG_TYPE_ID_SER0_REG = 28, - EVENT_MSG_TYPE_ID_SER0_CFG = 29, - EVENT_MSG_TYPE_ID_DMA_RX_0_CHAN = 30, - EVENT_MSG_TYPE_ID_GPIO_RX_0_REG = 31, + EVENT_MSG_TYPE_ID_GPX_DMA_RX_0_INST = 27, + EVENT_MSG_TYPE_ID_GPX_SER0_REG = 28, + EVENT_MSG_TYPE_ID_GPX_SER0_CFG = 29, + EVENT_MSG_TYPE_ID_GPX_DMA_RX_0_CHAN = 30, + EVENT_MSG_TYPE_ID_GPX_GPIO_RX_0_REG = 31, EVENT_MSG_TYPE_ID_FILTER_RESPONSE = (uint16_t)-4, EVENT_MSG_TYPE_ID_ENA_GNSS1_FILTER = (uint16_t)-3, diff --git a/src/protocol_nmea.cpp b/src/protocol_nmea.cpp index 96be1130f..10fbad674 100644 --- a/src/protocol_nmea.cpp +++ b/src/protocol_nmea.cpp @@ -743,47 +743,16 @@ void nmea_GPSTimeToUTCTimeMsPrecision(char* a, int aSize, int &offset, gps_pos_t // TODO: Remove after ZDA issue is resolved. #if defined(IMX_5) || defined(SDK_UNIT_TEST) -extern uint32_t g_time_msec; +extern uint32_t g_cpu_msec; extern sys_params_t g_sysParams; extern debug_array_t g_debug; #endif +// TODO: Remove after ZDA issue is resolved. int millisecondsToSeconds(int milliseconds) { - return (milliseconds + 500) / 1000; -} - -void nmea_report_fault(int fault_code) -{ -#if defined(IMX_5) || defined(SDK_UNIT_TEST) - g_sysParams.genFaultCode |= GFC_GNSS_TIME_FAULT; -#if PLATFORM_IS_EMBEDDED - g_gnssTimeFaultTimeMs = g_timeMs; -#endif - g_debug.i[6] |= 1< maxMs) - { - nmea_report_fault(fault_code); - debug = (float)dtMs; - } -#else - if (dtMs < minMs) - { // Less than 1s - nmea_report_fault(-fault_code); - debug = (float)dtMs; - } - if (dtMs > maxMs) - { // More than 1s - nmea_report_fault(fault_code); - debug = (float)dtMs; - } -#endif + if (milliseconds >= 0) { return (milliseconds + 500) / 1000; } + else { return (milliseconds - 500) / 1000; } } // TODO: Remove after ZDA issue is resolved. @@ -801,7 +770,7 @@ void nmea_GPSTimeToUTCTimeMsPrecision_ZDA_debug(char* a, int aSize, int &offset, #if defined(IMX_5) int32_t cpuMs = (int32_t)time_msec(); #else - int32_t cpuMs = (int32_t)g_time_msec; + int32_t cpuMs = (int32_t)g_cpu_msec; #endif int32_t utcMs = t.hour*C_MILLISECONDS_PER_HOUR + @@ -817,64 +786,53 @@ void nmea_GPSTimeToUTCTimeMsPrecision_ZDA_debug(char* a, int aSize, int &offset, static int32_t lastCpuMs = cpuMs - 1000; static int32_t lastUtcMs = utcMs - 1000; static int lastUtcHour = t.hour; - // static int lastGpsMs = gpsMs - 1000; - // static uint32_t lastWeek = pos.week; static int32_t utcOffsetSec = 0; // Check for irregular update timing int32_t cpuDtMs = cpuMs - lastCpuMs; - bool cpuDtMsGood = cpuDtMs < C_MILLISECONDS_PER_WEEK/2; - if (cpuDtMsGood) - { // No time wrap - check_dt_skip(cpuDtMs, 750, 1250, 1, g_debug.f[5]); - } + bool cpuDtMsGood = _ABS(cpuDtMs) < 5000; // Check for skip in ZDA time int32_t utcDtMs = utcMs - lastUtcMs; - bool utcDtMsGood = t.hour >= lastUtcHour; - if (utcDtMsGood) - { // No time wrap - check_dt_skip(utcDtMs, 1000, 1000, 2, g_debug.f[6]); - } - - // Check for skip in GPS time of week - // int32_t gpsDtMs = gpsMs - lastGpsMs; - // bool gpsDtMsGood = lastWeek == pos.week; - // if (gpsDtMsGood) - // { // No time wrap - // check_dt_skip(gpsDtMs, 1000, 1000, 3, g_debug.f[7]); - // } + bool utcDtMsGood = (t.hour >= lastUtcHour) && (_ABS(utcDtMs) < 5000); // Ensure time increments linearly int32_t ddtMs = utcDtMs - cpuDtMs; if (cpuDtMsGood && utcDtMsGood) { // No time wrap - utcOffsetSec = millisecondsToSeconds(ddtMs); - g_debug.i[3] = ddtMs; - // g_debug.i[4] = utcOffsetSec; - if (_ABS(utcOffsetSec) > 2) - { // Offset exceeded limit - utcOffsetSec = 0; - nmea_report_fault(5); + g_debug.i[3] = utcDtMs; + g_debug.i[4] = cpuDtMs; + int adjOffsetSec = millisecondsToSeconds(ddtMs); + if (adjOffsetSec) + { + utcOffsetSec += adjOffsetSec; + + g_sysParams.genFaultCode |= GFC_GNSS_RECEIVER_TIME; +#if PLATFORM_IS_EMBEDDED + g_gnssTimeFaultTimeMs = g_timeMs; +#endif + g_debug.i[5] = utcMs; + g_debug.i[6] = gpsMs; + g_debug.f[5] = utcDtMs; + g_debug.f[6] = cpuDtMs; + g_debug.f[8] += 1.0f; + if (_ABS(utcOffsetSec) > 2) + { // Offset exceeded limit + utcOffsetSec = 0; + } } - g_debug.i[5] = utcOffsetSec; } - -#if 1 + g_debug.f[7] = utcOffsetSec; // Update history lastCpuMs = cpuMs; lastUtcMs = utcMs; lastUtcHour = t.hour; - // lastGpsMs = gpsMs; - // lastWeek = pos.week; - // Apply correction offset +#if 0 // Apply correction offset if (utcOffsetSec) { - // nmea_report_fault(4); - - t.second += utcOffsetSec; + t.second -= utcOffsetSec; if (t.second >= 60) { // Wrap t.second -= 60; @@ -896,10 +854,10 @@ void nmea_GPSTimeToUTCTimeMsPrecision_ZDA_debug(char* a, int aSize, int &offset, } } } +#endif // TODO: (WHJ) End of debug section /////////////////////////////////////////////////////////////////////// -#endif #endif offset += ssnprintf(a, aSize, ",%02u%02u%02u.%03u", t.hour, t.minute, t.second, t.millisecond); @@ -2911,15 +2869,15 @@ int nmea_parse_zda(const char a[], int aSize, uint32_t &gpsTowMs, uint32_t &gpsW float second; ptr = ASCII_to_hours_minutes_seconds(&time.hour, &time.minute, &second, ptr); time.second = (int)second; - time.millisecond = ((int)(second*1000.0f))%1000; + time.millisecond = (int)(second*1000.0f) - 1000*time.second; // 2,3,4 - dd,mm,yyy (Day,Month,Year) ptr = ASCII_to_i32((int32_t*)&(date.day), ptr); ptr = ASCII_to_i32((int32_t*)&(date.month), ptr); ptr = ASCII_to_i32((int32_t*)&(date.year), ptr); - // Convert UTC date and time to GPS time of week and number of weeks - double datetime[6] = { (double)date.year, (double)date.month, (double)date.day, (double)time.hour, (double)time.minute, (double)second }; // year,month,day,hour,min,sec + // Convert UTC date and time to GPS time of week and number of weeks + int datetime[7] = { date.year, date.month, date.day, time.hour, time.minute, time.second, time.millisecond }; // year,month,day,hour,min,sec,msec UtcDateTimeToGpsTime(datetime, leapS, gpsTowMs, gpsWeek); date.weekday = gpsTowMsToUtcWeekday(gpsTowMs, leapS); diff --git a/src/protocol_nmea.h b/src/protocol_nmea.h index 264e6f748..1fddd3d5f 100644 --- a/src/protocol_nmea.h +++ b/src/protocol_nmea.h @@ -7,6 +7,10 @@ #include "data_sets.h" #include "time_conversion.h" +#if !defined(GPX_1) && !defined(IMX_5) && !defined(NAV_POST_PROCESS) +extern uint32_t g_cpu_msec; +#endif + #define NMEA_CMD_QUERY_DEVICE_INFO "$INFO*0E\r\n" #define NMEA_CMD_STOP_ALL_BROADCASTS_ALL_PORTS "$STPB*15\r\n" #define NMEA_CMD_STOP_ALL_BROADCASTS_CUR_PORT "$STPC*14\r\n" diff --git a/src/time_conversion.cpp b/src/time_conversion.cpp index d5ec9301a..15f842c42 100644 --- a/src/time_conversion.cpp +++ b/src/time_conversion.cpp @@ -33,15 +33,29 @@ void gpsTowMsToUtcTime(uint32_t gpsTimeOfWeekMs, int gpsLeapS, utc_time_t *time) time->millisecond = todayMs % 1000; } +void gpsWeekTowMsToUtcDateTime(uint32_t gpsWeek, uint32_t gpsTowMs, int gpsLeapS, utc_date_t *date, utc_time_t *time, uint32_t *milliseconds) +{ + double julian = gpsToJulian(gpsWeek, gpsTowMs, gpsLeapS); + julianToDate(julian, + (uint32_t*)&date->year, + (uint32_t*)&date->month, + (uint32_t*)&date->day, + (uint32_t*)&time->hour, + (uint32_t*)&time->minute, + (uint32_t*)&time->second, + (uint32_t*)milliseconds); + date->weekday = gpsTowMsToUtcWeekday(gpsTowMs, gpsLeapS); +} + void utcTimeToGpsTowMs(utc_time_t *time, int utcWeekday, uint32_t *gpsTimeOfWeekMs, int gpsLeapS) { int towMs = + utcWeekday * C_MILLISECONDS_PER_DAY + time->hour * C_MILLISECONDS_PER_HOUR + time->minute * C_MILLISECONDS_PER_MINUTE + time->second * C_MILLISECONDS_PER_SECOND + time->millisecond + - gpsLeapS * 1000 + - utcWeekday * C_MILLISECONDS_PER_DAY; + gpsLeapS * 1000; // Handle week wrap if (towMs >= C_MILLISECONDS_PER_WEEK) @@ -145,23 +159,30 @@ void stdUtcDateTimeToGpsTime(const std::tm &utcTime, int leapSeconds, uint32_t & /* convert calendar day/time to time ------------------------------------------- * convert calendar day/time to gtime_t struct -* args : double *ep I day/time {year,month,day,hour,min,sec} +* args : int *ep I day/time {year,month,day,hour,min,sec,msec} * return : gtime_t struct * notes : proper in 1970-2037 or 1970-2099 (64bit time_t) *-----------------------------------------------------------------------------*/ -gtime_t epochToTime(const double *ep) +gtime_t epochToTime(const int *ep) { const int doy[] = { 1,32,60,91,121,152,182,213,244,274,305,335 }; gtime_t time = { 0 }; - int days, sec, year = (int)ep[0], mon = (int)ep[1], day = (int)ep[2]; - - if (year < 1970 || 2099 < year || mon < 1 || 12 < mon) return time; + int days; + int year = ep[0]; + int mon = ep[1]; + int day = ep[2]; + int hour = ep[3]; + int minute = ep[4]; + int sec = ep[5]; + int msec = ep[6]; + + if (year < 1970 || 2099 < year || mon < 1 || 12 < mon) + return time; /* leap year if year%4==0 in 1901-2099 */ days = (year - 1970) * 365 + (year - 1969) / 4 + doy[mon - 1] + day - 2 + (year % 4 == 0 && mon >= 3 ? 1 : 0); - sec = (int)floor(ep[5]); - time.time = (time_t)days * 86400 + (int)ep[3] * 3600 + (int)ep[4] * 60 + sec; - time.sec = ep[5] - sec; + time.time = (time_t)days * 86400 + hour * 3600 + minute * 60 + sec; + time.sec = msec * 0.001; return time; } @@ -182,13 +203,20 @@ double timeToGpst(gtime_t t, int *week) return (double)(sec - (double)w * C_SECONDS_PER_WEEK) + t.sec; } -void UtcDateTimeToGpsTime(const double datetime[6], int leapSeconds, uint32_t &gpsTowMs, uint32_t &gpsWeek) +void UtcDateTimeToGpsTime(const int dateTime[6], int leapSeconds, uint32_t &gpsTowMs, uint32_t &gpsWeek, double *debugGtm) { - gtime_t gtm = epochToTime(datetime); + gtime_t gtm = epochToTime(dateTime); + + // TODO: Remove debug later (WHJ) + if (debugGtm) + { + *debugGtm = (double)gtm.time + gtm.sec; + } + int week; gtm.time += leapSeconds; double iTOWd = timeToGpst(gtm, &week); - gpsTowMs = (uint32_t)((iTOWd + 0.00001) * 1000.0); + gpsTowMs = (uint32_t)((iTOWd * 1000.0) + 0.5); // Ensure double rounds properly to nearest integer millisecond gpsWeek = week; } diff --git a/src/time_conversion.h b/src/time_conversion.h index 36f6dad21..1213b284d 100644 --- a/src/time_conversion.h +++ b/src/time_conversion.h @@ -43,6 +43,9 @@ void RevertUtcTimeZone(); /** Convert GPS time of week in milliseconds to UTC time */ void gpsTowMsToUtcTime(uint32_t gpsTimeOfWeekMs, int gpsLeapS, utc_time_t *time); +/** Convert GPS week and time of week in milliseconds to UTC date and time */ +void gpsWeekTowMsToUtcDateTime(uint32_t gpsWeek, uint32_t gpsTowMs, int gpsLeapS, utc_date_t *date, utc_time_t *time, uint32_t *milliseconds); + /** Convert UTC time to GPS time of week in milliseconds */ void utcTimeToGpsTowMs(utc_time_t *time, int utcWeekday, uint32_t *gpsTimeOfWeekMs, int gpsLeapS); @@ -74,12 +77,12 @@ void stdUtcDateTimeToGpsTime(const std::tm &utcTime, int leapSeconds, uint32_t & * @brief Convert UTC date and time to GPS time in time of week in milliseconds and number of weeks. * This function is equivalent to and computationally faster than stdUtcDateTimeToGpsTime(). * - * @param datetime[6] input double array of UTC time at GMT time zone {year,month,day,hour,min,sec} + * @param datetime[7] input int array of UTC time at GMT time zone {year,month,day,hour,min,sec,msec} * @param gpsLeapSeconds input number GPS leap seconds to convert to UTC time * @param gpsTowMs output GPS time of week in milliseconds * @param gpsWeek output GPS week number */ -void UtcDateTimeToGpsTime(const double datetime[6], int leapSeconds, uint32_t &gpsTowMs, uint32_t &gpsWeek); +void UtcDateTimeToGpsTime(const int datetime[7], int leapSeconds, uint32_t &gpsTowMs, uint32_t &gpsWeek, double *debugGtm=NULL); /** Convert Julian Date to calendar date. */ void julianToDate(double julian, uint32_t* year, uint32_t* month, uint32_t* day, uint32_t* hour, uint32_t* minute, uint32_t* second, uint32_t* millisecond); diff --git a/tests/runtime/device_runtime_tests.cpp b/tests/runtime/device_runtime_tests.cpp index 78826e7e1..46148ebfa 100644 --- a/tests/runtime/device_runtime_tests.cpp +++ b/tests/runtime/device_runtime_tests.cpp @@ -1,5 +1,3 @@ -#include -// #include #include #include #include @@ -10,30 +8,26 @@ #include "ISDataMappings.h" -#define LOG_DIRECTORY "realtime_logs" +#define LOG_DIRECTORY "realtime_logs" /** * @brief This class provides realtime evaluation conditions or errors in data streaming from the Inertial Sense products. - * + * */ DeviceRuntimeTests::DeviceRuntimeTests() { - m_gps1Pos.leapS = C_GPS_LEAP_SECONDS; - ISFileManager::CreateDirectory(LOG_DIRECTORY); m_filename = CreateLogFilename(LOG_DIRECTORY); - - LogEvent("Realtime tests started..."); } std::string DeviceRuntimeTests::CreateLogFilename(const std::string path, int serialNumber) { // Get current time - auto now = std::chrono::system_clock::now(); - auto in_time_t = std::chrono::system_clock::to_time_t(now); + auto now = SYS_TIME_NOW; + auto in_time = std::chrono::system_clock::to_time_t(now); // Convert to local time - std::tm bt = *localtime(&in_time_t); + std::tm bt = *localtime(&in_time); // Create a stringstream filename std::stringstream ss; @@ -45,12 +39,12 @@ std::string DeviceRuntimeTests::CreateLogFilename(const std::string path, int se return filename; } -std::string charArrayToHex(uint8_t* arr, int arrSize) +std::string charArrayToHex(uint8_t* arr, int arrSize) { std::stringstream ss; ss << "0x" << std::hex << std::setfill('0'); // Set to output hex values, padded with 0 - for (int i = 0; i < arrSize; ++i) + for (int i = 0; i < arrSize; ++i) { // Static cast to unsigned int to handle negative char values correctly ss << std::setw(2) << static_cast(arr[i]); @@ -65,15 +59,15 @@ void DeviceRuntimeTests::ProcessParseError(is_comm_instance_t &comm) { return; } - + int size = comm.rxBuf.scanPrior - comm.rxBuf.head; std::string parser; switch (comm.rxBuf.head[0]) { - case PSC_ISB_PREAMBLE_BYTE1: + case PSC_ISB_PREAMBLE_BYTE1: parser = std::string("ISB id ") + std::to_string(comm.rxPkt.dataHdr.id) + " " + std::string(cISDataMappings::DataName(comm.rxPkt.dataHdr.id)); - parser += ", size " + std::to_string(comm.rxPkt.dataHdr.size); + parser += ", size " + std::to_string(comm.rxPkt.dataHdr.size); break; case PSC_NMEA_START_BYTE: parser = std::string("NMEA ") + std::string((char*)comm.rxBuf.head, _MIN(size, MAX_MSG_LENGTH_NMEA)); break; case UBLOX_START_BYTE1: parser = std::string("UBX"); break; @@ -83,9 +77,9 @@ void DeviceRuntimeTests::ProcessParseError(is_comm_instance_t &comm) // default: parser = charArrayToHex(comm.rxBuf.head, 4); break; default: parser = std::string("Unknown"); break; } - + m_errorCount.parse = comm.rxErrorCount; - LogEvent("Parse Error #%d, size %d: %s", comm.rxErrorCount, size, parser.c_str()); + LogEvent(SYS_TIME_NOW, "Parse Error #%d, size %d: %s", comm.rxErrorCount, size, parser.c_str()); } void DeviceRuntimeTests::ProcessISB(const p_data_hdr_t &dataHdr, const uint8_t *dataBuf) @@ -94,8 +88,8 @@ void DeviceRuntimeTests::ProcessISB(const p_data_hdr_t &dataHdr, const uint8_t * { return; } - - // printf("ISB: ID %d Size %d\n", dataHdr.id, dataHdr.size); + + // WriteStatus("ISB: ID %d Size %d (%s)\n", dataHdr.id, dataHdr.size, cISDataMappings::DataName(dataHdr.id)); switch(dataHdr.id) { @@ -113,19 +107,23 @@ void DeviceRuntimeTests::ProcessISB(const p_data_hdr_t &dataHdr, const uint8_t * } } -void DeviceRuntimeTests::TestIsbGps(const p_data_hdr_t &dataHdr, const uint8_t *dataBuf) +std::deque& DeviceRuntimeTests::AddMsgHistory(std::deque &hist, DeviceRuntimeTests::msg_history_t msgHist) { - msg_history_t &hist = m_hist.isb.gps1Pos; - - copyDataPToStructP2(&m_gps1Pos, &dataHdr, dataBuf, sizeof(gps_pos_t)); + hist.push_front(msgHist); + if (hist.size() > 3) { hist.pop_back(); } // Keep 2, newest at front + return hist; +} - // printf("ISB GpsPos1 (%d ms, %d wkday): %.*s", m_gps1Pos.timeOfWeekMs, utcWeekday, msgSize, msg); +/** + * @brief Test messages for duplicates, reversed order, or irregular timestamps. + */ +void DeviceRuntimeTests::TestIsbGps(const p_data_hdr_t &dataHdr, const uint8_t *dataBuf) +{ + std::deque &hist = AddMsgHistory(m_hist.isb.gps1Pos, msg_history_t((gps_pos_t*)dataBuf)); - CheckGpsDuplicate ("ISB GpsPos1 Error", m_errorCount.nmeaGgaTime, m_gps1Pos.timeOfWeekMs, m_gps1Pos.week, NULL, 0, hist); - CheckGpsTimeReverse("ISB GpsPos1 Error", m_errorCount.nmeaGgaTime, m_gps1Pos.timeOfWeekMs, m_gps1Pos.week, NULL, 0, hist); + WriteStatus("ISB GpsPos1 (%d towMs, %d week)\n", hist[0].gpsTowMs, hist[0].gpsWeek); - // Update history - hist.update(m_gps1Pos.timeOfWeekMs, m_gps1Pos.week, NULL, 0); + CheckGpsTime("ISB Gps1Pos Error", m_errorCount.isbGpsTime, hist); } void DeviceRuntimeTests::ProcessNMEA(const uint8_t* msg, int msgSize) @@ -135,8 +133,8 @@ void DeviceRuntimeTests::ProcessNMEA(const uint8_t* msg, int msgSize) return; } - // printf("NMEA (%d): %.*s", msgSize, msgSize, msg); - + WriteStatus("NMEA (%d): %.*s", msgSize, msgSize, msg); + int id = getNmeaMsgId(msg, msgSize); switch(id) { @@ -145,43 +143,40 @@ void DeviceRuntimeTests::ProcessNMEA(const uint8_t* msg, int msgSize) } } +/** + * @brief Test messages for duplicates, reversed order, or irregular timestamps. + */ void DeviceRuntimeTests::TestNmeaGga(const uint8_t* msg, int msgSize) { - msg_history_t &hist = m_hist.nmea.gga; + int utcWeekday = m_hist.nmea.gga.size() ? gpsTowMsToUtcWeekday(m_hist.nmea.gga[0].gpsTowMs, C_GPS_LEAP_SECONDS) : 0; gps_pos_t gpsPos = {}; - utc_time_t t; - int utcWeekday = gpsTowMsToUtcWeekday(gpsPos.timeOfWeekMs, m_gps1Pos.leapS); nmea_parse_gga((const char *)msg, msgSize, gpsPos, t, utcWeekday); + std::deque &hist = AddMsgHistory(m_hist.nmea.gga, msg_history_t(gpsPos.timeOfWeekMs, gpsPos.week, (uint8_t*)msg, msgSize)); - // printf("NMEA GGA (%d ms, %d wkday): %.*s", gpsPos.timeOfWeekMs, utcWeekday, msgSize, msg); - - CheckGpsDuplicate ("NMEA GGA Error", m_errorCount.nmeaGgaTime, gpsPos.timeOfWeekMs, gpsPos.week, msg, msgSize, hist); - CheckGpsTimeReverse("NMEA GGA Error", m_errorCount.nmeaGgaTime, gpsPos.timeOfWeekMs, gpsPos.week, msg, msgSize, hist); + // WriteStatus("NMEA GGA (%d ms, %d wkday): %.*s", gpsPos.timeOfWeekMs, utcWeekday, msgSize, msg); - // Update history - hist.update(gpsPos.timeOfWeekMs, gpsPos.week, (uint8_t*)msg, msgSize); + CheckGpsTime("NMEA GGA Error", m_errorCount.nmeaGgaTime, hist); } +/** + * @brief Test messages for duplicates, reversed order, or irregular timestamps. + */ void DeviceRuntimeTests::TestNmeaZda(const uint8_t* msg, int msgSize) { - msg_history_t &hist = m_hist.nmea.zda; uint32_t gpsTowMs; uint32_t gpsWeek; - utc_date_t utcDate; + utc_date_t utcDate; utc_time_t utcTime; nmea_parse_zda((char*)msg, msgSize, gpsTowMs, gpsWeek, utcDate, utcTime, C_GPS_LEAP_SECONDS); + std::deque &hist = AddMsgHistory(m_hist.nmea.zda, msg_history_t(gpsTowMs, gpsWeek, (uint8_t*)msg, msgSize)); - // printf("NMEA ZDA (%d ms): %.*s", gpsTowMs, msgSize, msg); + // WriteStatus("NMEA ZDA (%d ms): %.*s", gpsTowMs, msgSize, msg); - CheckGpsDuplicate ("NMEA ZDA Error", m_errorCount.nmeaZdaTime, gpsTowMs, gpsWeek, msg, msgSize, hist); - CheckGpsTimeReverse("NMEA ZDA Error", m_errorCount.nmeaZdaTime, gpsTowMs, gpsWeek, msg, msgSize, hist); - - // Update history - hist.update(gpsTowMs, gpsWeek, (uint8_t*)msg, msgSize); + CheckGpsTime("NMEA ZDA Error", m_errorCount.nmeaZdaTime, hist); } -std::string printfToString(const char* format, ...) +std::string printfToString(const char* format, ...) { va_list args; va_start(args, format); @@ -193,12 +188,12 @@ std::string printfToString(const char* format, ...) unsigned int needed = std::vsnprintf(&str[0], str.size(), format, args); // If the string was not big enough, resize and try again - if (needed >= str.size()) + if (needed >= str.size()) { str.resize(needed + 1); std::vsnprintf(&str[0], str.size(), format, args); - } - else + } + else { str.resize(needed); // Resize to actual needed size } @@ -208,18 +203,28 @@ std::string printfToString(const char* format, ...) return str; } -bool DeviceRuntimeTests::CheckGpsDuplicate(const char* description, int &count, uint32_t towMs, uint32_t gpsWeek, const uint8_t* msg, int msgSize, msg_history_t &hist) +bool DeviceRuntimeTests::CheckGpsTime(const char* description, int &count, std::deque &hist) { - int64_t toyMs = towMs + gpsWeek * C_MILLISECONDS_PER_WEEK; - int64_t histToyMs = hist.gpsTowMs + hist.gpsWeek * C_MILLISECONDS_PER_WEEK; + return CheckGpsTimeIrregular (description, count, hist) || + CheckGpsTimeDuplicate (description, count, hist) || + CheckGpsTimeReversed (description, count, hist); +} + +bool DeviceRuntimeTests::CheckGpsTimeDuplicate(const char* description, int &count, std::deque &hist) +{ + if (hist.size()<2) return false; + + int64_t toyMs[2]; + for (int i=0; i<2; i++) + toyMs[i] = hist[i].gpsTowMs + hist[i].gpsWeek * C_MILLISECONDS_PER_WEEK; // newest at front - if (toyMs == histToyMs) + if (toyMs[0] == toyMs[1]) { // Duplicate time - LogEvent("NMEA Error: %s: Duplicate time (#%d): %d ms %d week >> %d ms %d week", description, ++count, hist.gpsTowMs, hist.gpsWeek, towMs, gpsWeek); - if (msg) + LogEvent(SYS_TIME_NOW, "Error: %s: Duplicate time (#%d): %d ms %d week >> %d ms %d week", description, ++count, hist[1].gpsTowMs, hist[1].gpsWeek, hist[0].gpsTowMs, hist[0].gpsWeek); + if (hist[0].msgSize) { - LogEvent(" 1: %.*s", hist.msgSize-2, (char*)hist.msg); - LogEvent(" 2: %.*s", msgSize-2, (char*)msg); + for (int i=1; i>=0; i--) + LogEvent(hist[i].localTime, " %d: %.*s", i+1, hist[i].msgSize-2, (char*)hist[i].msg); } return true; } @@ -227,18 +232,72 @@ bool DeviceRuntimeTests::CheckGpsDuplicate(const char* description, int &count, return false; } -bool DeviceRuntimeTests::CheckGpsTimeReverse(const char* description, int &count, uint32_t towMs, uint32_t gpsWeek, const uint8_t* msg, int msgSize, msg_history_t &hist) +bool DeviceRuntimeTests::CheckGpsTimeReversed(const char* description, int &count, std::deque &hist) { - int64_t toyMs = towMs + gpsWeek * C_MILLISECONDS_PER_WEEK; - int64_t histToyMs = hist.gpsTowMs + hist.gpsWeek * C_MILLISECONDS_PER_WEEK; + if (hist.size()<2) return false; - if (toyMs < histToyMs) + int64_t toyMs[2]; + for (int i=0; i<2; i++) + toyMs[i] = hist[i].gpsTowMs + hist[i].gpsWeek * C_MILLISECONDS_PER_WEEK; // newest at front + + if (toyMs[0] < toyMs[1]) { // Reversed time - LogEvent("NMEA Error: %s: Reversed time (#%d): %d ms %d week >> %d ms %d week", description, ++count, hist.gpsTowMs, hist.gpsWeek, towMs, gpsWeek); - if (msg) + LogEvent(SYS_TIME_NOW, "Error: %s: Reversed time (#%d): %d ms %d week >> %d ms %d week", description, ++count, hist[1].gpsTowMs, hist[1].gpsWeek, hist[0].gpsTowMs, hist[0].gpsWeek); + if (hist[0].msgSize) + { + for (int i=1; i>=0; i--) + LogEvent(hist[i].localTime, " %d: %.*s", i+1, hist[i].msgSize-2, (char*)hist[i].msg); + } + return true; + } + + return false; +} + +/** + * @brief Detects irregular timestamps in a message stream and reports cause as either dropped message(s) or irregular timestamps. + */ +bool DeviceRuntimeTests::CheckGpsTimeIrregular(const char* description, int &count, std::deque &hist) +{ + if (hist.size()<3) return false; + + if (hist[1].timeIrregular) return false; // Prevent displaying irregular period twice + + int64_t toyMs[3]; + for (int i=0; i<3; i++) + toyMs[i] = hist[i].gpsTowMs + hist[i].gpsWeek * C_MILLISECONDS_PER_WEEK; // newest at front + + int64_t rxDtMs[2]; + int64_t dtMs[2]; + for (int i=0; i<2; i++) + { + dtMs[i] = toyMs[i] - toyMs[i+1]; + auto delta = hist[i].localTime - hist[i+1].localTime; + rxDtMs[i] = std::chrono::duration_cast(delta).count(); + } + + double dtRatio = (double)rxDtMs[0] / (double)rxDtMs[1]; + + if (dtMs[0] != dtMs[1]) + { // Irregular timestamps + hist[0].timeIrregular = true; + + // Check if the interval between received messages changed by more than 50% + std::string causeStr; + if (dtRatio < 0.75 || dtRatio > 1.5) + { // Dropped message + causeStr = "Dropped message"; + } + else + { // Irregular timestamp + causeStr = "Irregular time"; + } + + LogEvent(SYS_TIME_NOW, "Error: %s: %s (#%d): %d ms %d week >> %d ms %d week", description, causeStr.c_str(), ++count, hist[1].gpsTowMs, hist[1].gpsWeek, hist[0].gpsTowMs, hist[0].gpsWeek); + if (hist[0].msgSize) { - LogEvent(" 1: %.*s", hist.msgSize-2, (char*)hist.msg); - LogEvent(" 2: %.*s", msgSize-2, (char*)msg); + for (int i=2; i>=0; i--) + LogEvent(hist[i].localTime, " %d: %.*s", 3-i, hist[i].msgSize-2, (char*)hist[i].msg); } return true; } @@ -246,19 +305,17 @@ bool DeviceRuntimeTests::CheckGpsTimeReverse(const char* description, int &count return false; } -std::string DeviceRuntimeTests::Timestamp() +std::string DeviceRuntimeTests::Timestamp(system_time_t time) { - // Get current time as a high-resolution time_point - auto now = std::chrono::system_clock::now(); // Convert time_point to time_t for easier formatting of date and time - auto in_time_t = std::chrono::system_clock::to_time_t(now); + auto in_time = std::chrono::system_clock::to_time_t(time); // To add milliseconds, subtract time_t from time_point, then cast to milliseconds - auto milliseconds = std::chrono::duration_cast(now.time_since_epoch()) % 1000; + auto milliseconds = std::chrono::duration_cast(time.time_since_epoch()) % 1000; std::stringstream ss; // Use put_time to format the date and time part - ss << std::put_time(std::localtime(&in_time_t), "%Y%m%d %H:%M:%S"); + ss << std::put_time(std::localtime(&in_time), "%Y%m%d %H:%M:%S"); // Manually add the formatted milliseconds ss << '.' << std::setfill('0') << std::setw(3) << milliseconds.count(); @@ -271,8 +328,8 @@ std::string DeviceRuntimeTests::Timestamp() return timestamp; } -void DeviceRuntimeTests::LogEvent(std::string str) -{ +void DeviceRuntimeTests::LogEvent(system_time_t time, std::string str) +{ // Add serial number if non-zero if (m_devInfo.serialNumber) { @@ -281,14 +338,13 @@ void DeviceRuntimeTests::LogEvent(std::string str) str += "\n"; // Prepend timestamp - str = Timestamp() + str; + str = Timestamp(time) + str; -#define MAX_LOG_SIZE 500000 // Prevent logging too much data - if (m_log.size() + str.size() > MAX_LOG_SIZE) + if (m_log.size() + str.size() > RUNTIME_TEST_MAX_LOG_SIZE) { // If appending would exceed maxSize, trim the existing content first - m_log = m_log.substr(0, MAX_LOG_SIZE - str.size()); + m_log = m_log.substr(0, RUNTIME_TEST_MAX_LOG_SIZE - str.size()); } m_log += str; @@ -296,7 +352,7 @@ void DeviceRuntimeTests::LogEvent(std::string str) std::cout << str; #endif - // Log to file + // Log to file FILE *file = fopen(m_filename.c_str(), "a"); if (file != NULL) { @@ -305,13 +361,28 @@ void DeviceRuntimeTests::LogEvent(std::string str) } } -std::string formatString(const char* format, va_list args) +void DeviceRuntimeTests::WriteStatus(std::string str) +{ + // Prevent logging too much data + if (m_status.size() + str.size() > RUNTIME_TEST_MAX_LOG_SIZE) + { + // If appending would exceed maxSize, trim the existing content first + m_status = m_status.substr(0, RUNTIME_TEST_MAX_LOG_SIZE - str.size()); + } + m_status += str; + +#if 0 // Print to display + std::cout << str; +#endif +} + +std::string formatString(const char* format, va_list args) { // Starting with a guess for the required length size_t size = MAX_MSG_LENGTH_NMEA; std::vector buffer(size); - while (true) + while (true) { va_list args_copy; va_copy(args_copy, args); // Make a copy of args to use @@ -323,7 +394,7 @@ std::string formatString(const char* format, va_list args) va_end(args_copy); // Check if the buffer was large enough - if (needed < 0) + if (needed < 0) { // Formatting error return ""; } @@ -339,10 +410,18 @@ std::string formatString(const char* format, va_list args) } } -void DeviceRuntimeTests::LogEvent(const char *format, ...) +void DeviceRuntimeTests::LogEvent(system_time_t time, const char *format, ...) +{ + va_list args; + va_start(args, format); + LogEvent(time, formatString(format, args)); + va_end(args); +} + +void DeviceRuntimeTests::WriteStatus(const char *format, ...) { va_list args; va_start(args, format); - LogEvent(formatString(format, args)); + WriteStatus(formatString(format, args)); va_end(args); } diff --git a/tests/runtime/device_runtime_tests.h b/tests/runtime/device_runtime_tests.h index b4e1d9a87..4a9621158 100644 --- a/tests/runtime/device_runtime_tests.h +++ b/tests/runtime/device_runtime_tests.h @@ -1,7 +1,14 @@ #include +#include +#include +#include #include "ISComm.h" #include "time_conversion.h" +#define RUNTIME_TEST_MAX_LOG_SIZE 500000 +#define SYS_TIME_NOW std::chrono::system_clock::now() + +typedef std::chrono::time_point system_time_t; class RuntimeTest { @@ -20,30 +27,40 @@ class DeviceRuntimeTests { typedef struct sMsgHistory { - void update(uint32_t gpsTowMs_, uint32_t gpsWeek_, uint8_t *msg_, int msgSize_) + sMsgHistory(uint32_t gpsTowMs_, uint32_t gpsWeek_, uint8_t *msg_ = NULL, int msgSize_ = 0) { + localTime = SYS_TIME_NOW; gpsTowMs = gpsTowMs_; gpsWeek = gpsWeek_; msgSize = msgSize_; - memset(&dataHdr, 0, sizeof(p_data_hdr_t)); memcpy(msg, msg_, _MIN(msgSize_, MAX_MSG_LENGTH_NMEA)); } - void update(uint32_t gpsTowMs_, uint32_t gpsWeek_, p_data_hdr_t &dataHdr_, const uint8_t *dataBuf_) + sMsgHistory(gps_pos_t *gps, uint8_t *msg_ = NULL, int msgSize_ = 0) + { + localTime = SYS_TIME_NOW; + gpsTowMs = gps->timeOfWeekMs; + gpsWeek = gps->week; + msgSize = msgSize_; + memcpy(msg, msg_, _MIN(msgSize_, MAX_MSG_LENGTH_NMEA)); + } + sMsgHistory(uint32_t gpsTowMs_, uint32_t gpsWeek_, p_data_hdr_t &dataHdr_, const uint8_t *dataBuf_) { + localTime = SYS_TIME_NOW; gpsTowMs = gpsTowMs_; gpsWeek = gpsWeek_; - msgSize = 0; dataHdr = dataHdr_; memcpy(msg, dataBuf_, _MIN(dataHdr.size, MAX_MSG_LENGTH_NMEA)); } - utc_date_t date; - utc_time_t time; - uint32_t gpsTowMs; - uint32_t gpsWeek; - uint8_t msg[MAX_MSG_LENGTH_NMEA]; - int msgSize; - p_data_hdr_t dataHdr; + system_time_t localTime; + utc_date_t date; + utc_time_t time; + uint32_t gpsTowMs; + uint32_t gpsWeek; + uint8_t msg[MAX_MSG_LENGTH_NMEA]; + int msgSize = 0; + p_data_hdr_t dataHdr = {}; + bool timeIrregular = false; // used to prevent redundant error logging } msg_history_t; public: @@ -59,35 +76,55 @@ class DeviceRuntimeTests m_errorCount.nmeaZdaTime; } bool HasLog(){ return m_log.size() != 0; } + bool HasStatus(){ return m_status.size() != 0; } std::string Log() { std::string log = m_log; m_log.clear(); return log; } + std::string Status() + { + std::string status = m_status; + m_status.clear(); + return status; + } void SetPortName(std::string portName){ m_portName = portName; }; - void Enable(bool enable=true){ m_enable = enable; } + void Enable(bool enable=true) + { + m_enable = enable; + LogEvent(SYS_TIME_NOW, (enable ? "Tests enabled..." : "Tests disabled...")); + } + void Verbose(bool enable=true){ m_verbose = enable; }; struct error_count { int parse; + int isbGpsTime; int nmeaGgaTime; int nmeaZdaTime; } m_errorCount = {}; private: + std::deque& AddMsgHistory(std::deque &hist, DeviceRuntimeTests::msg_history_t msgHist); void TestIsbGps(const p_data_hdr_t &dataHdr, const uint8_t *dataBuf); void TestNmeaGga(const uint8_t* msg, int msgSize); void TestNmeaZda(const uint8_t* msg, int msgSize); - bool CheckGpsDuplicate(const char* description, int &count, uint32_t towMs, uint32_t gpsWeek, const uint8_t* msg, int msgSize, msg_history_t &hist); - bool CheckGpsTimeReverse(const char* description, int &count, uint32_t towMs, uint32_t gpsWeek, const uint8_t* msg, int msgSize, msg_history_t &hist); - void LogEvent(std::string str); - void LogEvent(const char *format, ...); - std::string Timestamp(); + bool CheckGpsTime(const char* description, int &count, std::deque &hist); + bool CheckGpsTimeDuplicate(const char* description, int &count, std::deque &hist); + bool CheckGpsTimeReversed(const char* description, int &count, std::deque &hist); + bool CheckGpsTimeIrregular(const char* description, int &count, std::deque &hist); + void LogEvent(system_time_t time, std::string str); + void LogEvent(system_time_t time, const char *format, ...); + void WriteStatus(std::string str); + void WriteStatus(const char *format, ...); + std::string Timestamp(system_time_t time); std::string m_filename; std::string m_log; + std::string m_status; bool m_enable = false; + bool m_verbose = false; dev_info_t m_devInfo = {}; std::string m_portName; @@ -95,20 +132,19 @@ class DeviceRuntimeTests RuntimeTest m_testZdaDuplicate{"ZDA Duplicate"}; RuntimeTest m_testGgaTimeReverse{"GGA Time Reverse"}; RuntimeTest m_testZdaTimeReverse{"ZDA Time Reverse"}; - - gps_pos_t m_gps1Pos; + RuntimeTest m_testZdaTimeJump{"ZDA Time Jump"}; struct { struct { - msg_history_t gps1Pos; + std::deque gps1Pos; } isb; struct { - msg_history_t zda; - msg_history_t gga; + std::deque zda; + std::deque gga; } nmea; } m_hist = {}; diff --git a/tests/test_protocol_nmea.cpp b/tests/test_protocol_nmea.cpp index 38adcd16e..609dfd277 100644 --- a/tests/test_protocol_nmea.cpp +++ b/tests/test_protocol_nmea.cpp @@ -64,68 +64,146 @@ void compareGpsVel(gps_vel_t &g1, gps_vel_t &g2) EXPECT_EQ(g1.status, g2.status); } -sys_params_t g_sysParams = {}; -uint32_t g_time_msec = {}; -debug_array_t g_debug = {}; +uint32_t g_cpu_msec; +sys_params_t g_sysParams; +debug_array_t g_debug; + +void initGlobals() +{ + memset(&g_sysParams, 0, sizeof(g_sysParams)); + g_cpu_msec = 0; + memset(&g_debug, 0, sizeof(g_debug)); +} bool timeWithin(uint32_t timeSec, uint32_t startSec, uint32_t durationSec) { return (timeSec >= startSec) && (timeSec < (startSec + durationSec)); } -#if 0 TEST(protocol_nmea, zda_gps_time_skip) { + GTEST_SKIP(); // This test must be run manually as the statically SDK build does not include the ZDA TOD work around code + +#ifdef _WIN32 + GTEST_SKIP() << "Skipping test on Windows."; +#endif + printf("DESCRIPTION: Test that ZDA time skip detect code works correctly for 1-2 second jumps in the ZDA UTC time due to jumps in GPS time of week.\n"); + initGlobals(); char buf[1024]; gps_pos_t pos = {}; pos.leapS = 18; pos.week = 2345; bool faultLast = false; + int simulatedOffsetMs = 0; for (int timeSec=0; timeSec2000) { simulatedOffsetMs = 0; } + } } if (fault) - { - pos.timeOfWeekMs += 1000; + { // Simulate offset in GPS tow + pos.timeOfWeekMs += simulatedOffsetMs; } - bool toggle = fault != faultLast; - faultLast = fault; int n = nmea_zda(buf, sizeof(buf), pos); + ASSERT_EQ((g_sysParams.genFaultCode&GFC_GNSS_RECEIVER_TIME) != 0, toggle) << "genFaultCode failed at timeSec: " << timeSec; + ASSERT_EQ(g_debug.f[8] != 0, toggle) << "Correction offset failed at timeSec: " << timeSec; + ASSERT_EQ(g_debug.f[7], (fault ? simulatedOffsetMs/1000 : 0)) << "Correction offset failed at timeSec: " << timeSec; + uint32_t gpsTowMs; uint32_t gpsWeek; utc_date_t utcDate; utc_time_t utcTime; nmea_parse_zda(buf, n, gpsTowMs, gpsWeek, utcDate, utcTime, pos.leapS); +#if 0 + // if (toggle) + { + printf("timeSec: %d ", timeSec); + printf("gpsTowMs: %d ", pos.timeOfWeekMs); + if (fault) printf("(fault on) "); + else printf("(fault off) "); + PrintUtcDateTime(utcDate, utcTime); + } +#endif + // ASSERT_EQ(gpsTowMs, timeSec*1000) << "Continuous at timeSec: " << timeSec; + // ASSERT_EQ(gpsTowMs, pos.timeOfWeekMs - (fault?simulatedOffsetMs:0)) << "GPS tow failed at timeSec: " << timeSec; -#if 1 - printf("timeSec: %d ", timeSec); - PrintUtcDateTime(utcDate, utcTime); + g_debug.i[6] = 0; + g_debug.f[8] = 0; + g_sysParams.genFaultCode = 0; + } +} +TEST(protocol_nmea, zda_cpu_time_skip) +{ +#ifdef _WIN32 + GTEST_SKIP() << "Skipping test on Windows."; #endif + printf("DESCRIPTION: Test that ZDA work around will pregress linearly and not apply incorrectly apply offset when GPS update is missing.\n"); + initGlobals(); + char buf[1024]; + gps_pos_t pos = {}; + pos.leapS = 18; + pos.week = 2345; + bool faultLast = false; - ASSERT_EQ((g_sysParams.genFaultCode&GFC_GNSS_TIME_FAULT) != 0, toggle) << "Failed at timeSec: " << timeSec; - ASSERT_EQ((g_debug.i[6]) != 0, toggle) << "Failed at timeSec: " << timeSec; - ASSERT_EQ(pos.timeOfWeekMs - (fault?1000:0), gpsTowMs) << "Failed at timeSec: " << timeSec; - ASSERT_EQ(pos.week, gpsWeek) << "Failed at timeSec: " << timeSec; + for (int timeSec=0; timeSec