/*---------------------------------------------------------------------------- * Copyright (c) Fenda Technologies Co., Ltd. 2020. All rights reserved. * * Description: debug user_debug.c * * Author: saimen * * Create: 2020-12-16 *--------------------------------------------------------------------------*/ #include #include "am_util.h" #include "sys_config.h" #include "FreeRTOS.h" #include "task.h" #include "stream_buffer.h" #include "queue.h" #include "semphr.h" #include "debug_port.h" // Type definitions #define AM_DBG_UART_INST 1 #define AM_DBG_UART_DISABLE_BUFFER //#define AM_DBG_UART_FIFO_WARTERMASK (16) #define AM_DBG_UART_FIFO_WARTERMASK (AM_UART_FIFO_SIZE / 2) #define AM_DBG_UART_DEFAULT_BAUDRATE 921600 typedef enum { AM_DEVICES_UART_STATUS_SUCCESS, AM_DEVICES_UART_STATUS_ERROR }am_devices_uart_status_t; typedef void (*pUartIsrCb)(void *pHandle, uint32_t ui32Status); // Type definitions typedef struct { uint32_t pin; am_hal_gpio_pincfg_t pin_config; }uart_pin_config; typedef struct { uint32_t uart_num; void *p_handle; uart_pin_config tx; uart_pin_config rx; uint32_t int_mask; am_hal_uart_config_t* uart_config; pUartIsrCb interrupt_cb; }drv_uart_t; static drv_uart_t g_uart_debug = {0}; #if defined(AM_PART_APOLLO4) #define AM_HAL_GPIO_PIN_DRIVESTRENGTH_2MA AM_HAL_GPIO_PIN_DRIVESTRENGTH_12MA #endif //***************************************************************************** // // UART1_TX pin: This pin is the DBG_UART transmit pin. // //***************************************************************************** #define AM_DBG_UART_TX 53//71 extern const am_hal_gpio_pincfg_t g_AM_DBG_UART_TX; //***************************************************************************** // // UART1_RX pin: This pin is the DBG_UART receive pin. // //***************************************************************************** #define AM_DBG_UART_RX 55 extern const am_hal_gpio_pincfg_t g_AM_DBG_UART_RX; #ifdef BIG_BOARD //***************************************************************************** // // ITM_SWO pin: This pin is the DBG_SWO transmit pin. // //***************************************************************************** #define AM_DBG_ITM_SWO 71 extern const am_hal_gpio_pincfg_t g_AM_DBG_ITM_SWO; //***************************************************************************** // // ITM_SWO2 pin: This pin is the DBG_SWO transmit pin. // //***************************************************************************** #define AM_DBG_ITM_SWO2 50 extern const am_hal_gpio_pincfg_t g_AM_DBG_ITM_SWO2; #else //***************************************************************************** // // ITM_SWO pin: This pin is the DBG_SWO transmit pin. // //***************************************************************************** #define AM_DBG_ITM_SWO 28 //41 extern const am_hal_gpio_pincfg_t g_AM_DBG_ITM_SWO; //***************************************************************************** // // ITM_SWO2 pin: This pin is the DBG_SWO transmit pin. // //***************************************************************************** #define AM_DBG_ITM_SWO2 71 extern const am_hal_gpio_pincfg_t g_AM_DBG_ITM_SWO2; #endif //***************************************************************************** // // SWDCK pin: Cortex Serial Wire DCK. // //***************************************************************************** #define AM_JLINK_SWDCK 20 extern const am_hal_gpio_pincfg_t g_AM_JLINK_SWDCK; extern const am_hal_gpio_pincfg_t g_AM_SWDCK_DISABLE; //***************************************************************************** // // SWDIO pin: Cortex Serial Wire DIO. // //***************************************************************************** #define AM_JLINK_SWDIO 21 extern const am_hal_gpio_pincfg_t g_AM_JLINK_SWDIO; extern const am_hal_gpio_pincfg_t g_AM_SWDIO_DISABLE; //***************************************************************************** // // UART1_TX pin: This pin is the DBG_UART transmit pin. // //***************************************************************************** const am_hal_gpio_pincfg_t g_AM_DBG_UART_TX = { .GP.cfg_b.uFuncSel = AM_HAL_PIN_53_UART1TX, .GP.cfg_b.eDriveStrength = AM_HAL_GPIO_PIN_DRIVESTRENGTH_2MA }; //***************************************************************************** // // UART1_RX pin: This pin is the DBG_UART receive pin. // //***************************************************************************** const am_hal_gpio_pincfg_t g_AM_DBG_UART_RX = { .GP.cfg_b.uFuncSel = AM_HAL_PIN_55_UART1RX, .GP.cfg_b.ePullup = AM_HAL_GPIO_PIN_PULLUP_100K, .GP.cfg_b.eGPInput = AM_HAL_GPIO_PIN_INPUT_ENABLE }; //***************************************************************************** // // ITM_SWO pin: This pin is the DBG_SWO transmit pin. // //***************************************************************************** const am_hal_gpio_pincfg_t g_AM_DBG_ITM_SWO = { .GP.cfg_b.uFuncSel = AM_HAL_PIN_41_SWO, .GP.cfg_b.eDriveStrength = AM_HAL_GPIO_PIN_DRIVESTRENGTH_2MA }; //***************************************************************************** // // ITM_SWO pin: This pin is the DBG_SWO transmit pin. // //***************************************************************************** const am_hal_gpio_pincfg_t g_AM_DBG_ITM_SWO2 = { .GP.cfg_b.uFuncSel = AM_HAL_PIN_44_SWO, .GP.cfg_b.eDriveStrength = AM_HAL_GPIO_PIN_DRIVESTRENGTH_2MA }; //***************************************************************************** // // SWDCK pin: Cortex Serial Wire DCK. // //***************************************************************************** const am_hal_gpio_pincfg_t g_AM_JLINK_SWDCK = { .GP.cfg_b.uFuncSel = AM_HAL_PIN_20_SWDCK }; const am_hal_gpio_pincfg_t g_AM_SWDCK_DISABLE = { .GP.cfg_b.uFuncSel = AM_HAL_PIN_20_GPIO, .GP.cfg_b.eIntDir = AM_HAL_GPIO_PIN_INTDIR_NONE, // .GP.cfg_b.eDriveStrength = AM_HAL_GPIO_PIN_DRIVESTRENGTH_2MA, .GP.cfg_b.eGPInput = AM_HAL_GPIO_PIN_INPUT_NONE }; //***************************************************************************** // // SWDIO pin: Cortex Serial Wire DIO. // //***************************************************************************** const am_hal_gpio_pincfg_t g_AM_JLINK_SWDIO = { .GP.cfg_b.uFuncSel = AM_HAL_PIN_21_SWDIO }; const am_hal_gpio_pincfg_t g_AM_SWDIO_DISABLE = { .GP.cfg_b.uFuncSel = AM_HAL_PIN_21_GPIO, .GP.cfg_b.eIntDir = AM_HAL_GPIO_PIN_INTDIR_NONE, // .GP.cfg_b.eDriveStrength = AM_HAL_GPIO_PIN_DRIVESTRENGTH_2MA, .GP.cfg_b.eGPInput = AM_HAL_GPIO_PIN_INPUT_NONE }; #ifndef AM_DBG_UART_DISABLE_BUFFER //***************************************************************************** // // Default UART configuration settings if using buffers. // //***************************************************************************** #define AM_BSP_UART_BUFFER_SIZE 1024 static uint8_t pui8UartTxBuffer[AM_BSP_UART_BUFFER_SIZE]; static uint8_t pui8UartRxBuffer[AM_BSP_UART_BUFFER_SIZE]; static am_hal_uart_config_t g_debug_uart_config = { // // Standard UART settings: 115200-8-N-1 // .ui32BaudRate = 115200, //max 921600 #if defined(AM_PART_APOLLO4) .eDataBits = AM_HAL_UART_DATA_BITS_8, .eParity = AM_HAL_UART_PARITY_NONE, .eStopBits = AM_HAL_UART_ONE_STOP_BIT, .eFlowControl = AM_HAL_UART_FLOW_CTRL_NONE, #else .ui32DataBits = AM_HAL_UART_DATA_BITS_8, .ui32Parity = AM_HAL_UART_PARITY_NONE, .ui32StopBits = AM_HAL_UART_ONE_STOP_BIT, .ui32FlowControl = AM_HAL_UART_FLOW_CTRL_NONE, #endif // // Set TX and RX FIFOs to interrupt at half-full. // #if defined(AM_PART_APOLLO4) .eTXFifoLevel = AM_HAL_UART_TX_FIFO_1_2, .eRXFifoLevel = AM_HAL_UART_RX_FIFO_1_2, #else .ui32FifoLevels = (AM_HAL_UART_TX_FIFO_1_2 | AM_HAL_UART_RX_FIFO_1_2), #endif // // The default interface will just use polling instead of buffers. // #if !defined(AM_PART_APOLLO4) .pui8TxBuffer = pui8UartTxBuffer, .ui32TxBufferSize = sizeof(pui8UartTxBuffer), .pui8RxBuffer = pui8UartRxBuffer, .ui32RxBufferSize = sizeof(pui8UartRxBuffer), #endif }; #else //***************************************************************************** // // Default UART configuration settings. // //***************************************************************************** static am_hal_uart_config_t g_debug_uart_config = { // // Standard UART settings: 115200-8-N-1 // .ui32BaudRate = AM_DBG_UART_DEFAULT_BAUDRATE, #if defined(AM_PART_APOLLO4) .eDataBits = AM_HAL_UART_DATA_BITS_8, .eParity = AM_HAL_UART_PARITY_NONE, .eStopBits = AM_HAL_UART_ONE_STOP_BIT, .eFlowControl = AM_HAL_UART_FLOW_CTRL_NONE, #else .ui32DataBits = AM_HAL_UART_DATA_BITS_8, .ui32Parity = AM_HAL_UART_PARITY_NONE, .ui32StopBits = AM_HAL_UART_ONE_STOP_BIT, .ui32FlowControl = AM_HAL_UART_FLOW_CTRL_NONE, #endif // // Set TX and RX FIFOs to interrupt at half-full. // #if defined(AM_PART_APOLLO4) .eTXFifoLevel = AM_HAL_UART_FIFO_LEVEL_16, .eRXFifoLevel = AM_HAL_UART_FIFO_LEVEL_16, #else .ui32FifoLevels = (AM_HAL_UART_TX_FIFO_1_2 | AM_HAL_UART_RX_FIFO_1_2), //32bytes X (1 / 2) = 16bytes -- AM_DBG_UART_FIFO_WARTERMASK #endif // // The default interface will just use polling instead of buffers. // #if !defined(AM_PART_APOLLO4) .pui8TxBuffer = NULL, .ui32TxBufferSize = 0, .pui8RxBuffer = NULL, .ui32RxBufferSize = 0, #endif }; #endif // AM_DBG_UART_DISABLE_BUFFER //***************************************************************************** // // @brief Enable printing over ITM. // //***************************************************************************** void debug_port_itm_enable(void) { #if defined(AM_PART_APOLLO4) uint32_t ui32dcuVal; // // Need to make sure that SWO is enabled // { if ((PWRCTRL->DEVPWRSTATUS_b.PWRSTCRYPTO == 1) && (CRYPTO->HOSTCCISIDLE_b.HOSTCCISIDLE == 1)) { am_hal_dcu_get(&ui32dcuVal); // Enable SWO if ( !(ui32dcuVal & AM_HAL_DCU_CPUTRC_TPIU_SWO) && (am_hal_dcu_update(true, AM_HAL_DCU_CPUTRC_TPIU_SWO) != AM_HAL_STATUS_SUCCESS) ) { // Cannot enable SWO // return -1; return; } } else { // If DCU is not accessible, we cannot determine if ITM canbe safely enabled!! // return -1; return; } } // // Enable the ITM interface and the SWO pin. // am_hal_itm_enable(); am_hal_tpiu_enable(AM_HAL_TPIU_BAUD_1M); am_hal_gpio_pinconfig(AM_DBG_ITM_SWO, g_AM_DBG_ITM_SWO); // am_hal_gpio_pinconfig(AM_DBG_ITM_SWO2, g_AM_DBG_ITM_SWO2); #else am_hal_tpiu_config_t TPIUcfg = {0}; // // Enable the ITM interface and the SWO pin. // am_hal_itm_enable(); // // Enable the ITM and TPIU // Set the BAUD clock for 1M // // TPIUcfg.ui32SetItmBaud = AM_HAL_TPIU_BAUD_1M; TPIUcfg.ui32SetItmBaud = AM_HAL_TPIU_BAUD_2M; am_hal_tpiu_enable(&TPIUcfg); am_hal_gpio_pinconfig(AM_DBG_ITM_SWO, g_AM_DBG_ITM_SWO); // am_hal_gpio_pinconfig(AM_DBG_ITM_SWO2, g_AM_DBG_ITM_SWO2); #endif // // Attach the ITM to the STDIO driver. // am_util_stdio_printf_init(am_hal_itm_print); } // debug_port_itm_enable() //***************************************************************************** // // @brief Disable printing over ITM. // //***************************************************************************** void debug_port_itm_disable(void) { #if !defined(AM_PART_APOLLO4) // // Disable the ITM/TPIU // am_hal_itm_disable(); // // Detach the ITM interface from the STDIO driver. // am_util_stdio_printf_init(NULL); // // Disconnect the SWO pin // am_hal_gpio_pinconfig(AM_DBG_ITM_SWO, g_AM_HAL_GPIO_DISABLE); #endif } // debug_port_itm_disable() //***************************************************************************** // // @brief Enable jlink. add hezhao 2020.12.27 // //***************************************************************************** void am_bsp_jlink_pin_enable(void) { am_hal_gpio_pinconfig(AM_JLINK_SWDCK, g_AM_JLINK_SWDCK); am_hal_gpio_pinconfig(AM_JLINK_SWDIO, g_AM_JLINK_SWDIO); } //***************************************************************************** // // @brief Disable jlink. add hezhao 2020.11.27 // //***************************************************************************** void am_bsp_jlink_pin_disable(void) { am_hal_gpio_pinconfig(AM_JLINK_SWDCK, g_AM_SWDCK_DISABLE); am_hal_gpio_pinconfig(AM_JLINK_SWDIO, g_AM_SWDIO_DISABLE); } //***************************************************************************** // //! @brief UART-based string print function. //! //! This function is used for printing a string via the UART, which for some //! MCU devices may be multi-module. //! //! @return None. // //***************************************************************************** void am_bsp_uart_string_print_ext(char *pcString) { uint32_t ui32StrLen = 0; uint32_t ui32BytesWritten = 0; // // Measure the length of the string. // while (pcString[ui32StrLen] != 0) { ui32StrLen++; } // // Print the string via the UART. // const am_hal_uart_transfer_t sUartWrite = { #if defined(AM_PART_APOLLO4) .eType = AM_HAL_UART_NONBLOCKING_WRITE, #else .ui32Direction = AM_HAL_UART_WRITE, #endif .pui8Data = (uint8_t *) pcString, .ui32NumBytes = ui32StrLen, .ui32TimeoutMs = AM_HAL_UART_WAIT_FOREVER, .pui32BytesTransferred = &ui32BytesWritten, }; am_hal_uart_transfer(g_uart_debug.p_handle, &sUartWrite); am_hal_uart_tx_flush(g_uart_debug.p_handle); } // am_bsp_uart_string_print_ext() void am_bsp_uart_tx(const uint8_t *pBuf, uint32_t bufLen) { uint32_t ui32BytesWritten; uint32_t ui32BytesCount = 0; uint8_t ui8BytesBuff[AM_UART_FIFO_SIZE + 4] = {0}; am_hal_uart_transfer_t sUartWrite = { #if defined(AM_PART_APOLLO4) .eType = AM_HAL_UART_NONBLOCKING_WRITE, #else .ui32Direction = AM_HAL_UART_WRITE, #endif .pui8Data = ui8BytesBuff, .ui32NumBytes = 0, .ui32TimeoutMs = 0, // .ui32TimeoutMs = AM_HAL_UART_WAIT_FOREVER, .pui32BytesTransferred = &ui32BytesWritten, }; // // Measure the length of the string. // if ( bufLen > AM_DBG_UART_FIFO_WARTERMASK ) { sUartWrite.ui32NumBytes = AM_DBG_UART_FIFO_WARTERMASK; } else { sUartWrite.ui32NumBytes = bufLen; } while ( ui32BytesCount < bufLen ) { memset(ui8BytesBuff, 0x0, sizeof(ui8BytesBuff)); memcpy(ui8BytesBuff, &pBuf[ui32BytesCount], sUartWrite.ui32NumBytes); // // Print the string via the UART. // am_hal_uart_transfer(g_uart_debug.p_handle, &sUartWrite); am_hal_uart_tx_flush(g_uart_debug.p_handle); ui32BytesCount += ui32BytesWritten; if ( ui32BytesCount + AM_DBG_UART_FIFO_WARTERMASK > bufLen) { sUartWrite.ui32NumBytes = bufLen - ui32BytesCount; } } } void am_bsp_uart_printf(char *pcString) { am_bsp_uart_tx((const uint8_t *)pcString, strlen(pcString)); } //***************************************************************************** // // Short Description. 对串口进行波特率切换 // //***************************************************************************** void am_bsp_uart_config_switch(uint32_t baudrate) { static uint32_t pre_baudrate = AM_DBG_UART_DEFAULT_BAUDRATE; if(g_uart_debug.p_handle == NULL) { return; } if(pre_baudrate == baudrate) { return; } // am_hal_uart_interrupt_disable(g_uart_debug.p_handle, 0xFFFFFFFF); am_hal_uart_interrupt_disable(g_uart_debug.p_handle, (AM_HAL_UART_INT_RX | AM_HAL_UART_INT_RX_TMOUT) | AM_HAL_UART_INT_TXCMP); // // Use the custom configuration if it was provided. Otherwise, just use the default configuration. // g_debug_uart_config.ui32BaudRate = baudrate; g_uart_debug.uart_config = (am_hal_uart_config_t*)&g_debug_uart_config; am_hal_uart_configure(g_uart_debug.p_handle, g_uart_debug.uart_config); am_hal_uart_interrupt_enable(g_uart_debug.p_handle, (AM_HAL_UART_INT_RX | AM_HAL_UART_INT_RX_TMOUT) | AM_HAL_UART_INT_TXCMP); pre_baudrate = baudrate; } //***************************************************************************** // // Short Description. // //***************************************************************************** void* debug_port_uart_get_handle(void) { return g_uart_debug.p_handle; } //***************************************************************************** // // Initialize and configure the UART // //***************************************************************************** void debug_port_uart_enable(void) { drv_uart_t *p_uart_dev = &g_uart_debug; p_uart_dev->uart_num = AM_DBG_UART_INST; p_uart_dev->uart_config = (am_hal_uart_config_t*)&g_debug_uart_config; p_uart_dev->tx.pin = AM_DBG_UART_TX; p_uart_dev->tx.pin_config = g_AM_DBG_UART_TX; p_uart_dev->rx.pin = AM_DBG_UART_RX; p_uart_dev->rx.pin_config = g_AM_DBG_UART_RX; //uart_open(AM_DBG_UART_INST); if ((p_uart_dev->uart_num > AM_REG_UART_NUM_MODULES) || (p_uart_dev == NULL)) { // while(1); return; } am_hal_uart_initialize(p_uart_dev->uart_num, &p_uart_dev->p_handle); am_hal_uart_power_control(p_uart_dev->p_handle, AM_HAL_SYSCTRL_WAKE, false); am_hal_uart_configure(p_uart_dev->p_handle, p_uart_dev->uart_config); am_hal_gpio_pinconfig(p_uart_dev->tx.pin, p_uart_dev->tx.pin_config); am_hal_gpio_pinconfig(p_uart_dev->rx.pin, p_uart_dev->rx.pin_config); // //interrupt config // //uart_intr_config_cb(AM_DBG_UART_INST, debug_port_uart_user_cb); //no use callback function. p_uart_dev->interrupt_cb = debug_port_uart_user_cb; NVIC_SetPriority((IRQn_Type)(UART0_IRQn + AM_DBG_UART_INST), (5 % (1 << __NVIC_PRIO_BITS))); //__NVIC_PRIO_BITS = 3 NVIC_EnableIRQ((IRQn_Type)(UART0_IRQn + AM_DBG_UART_INST)); //am_hal_uart_interrupt_enable(g_uart_dev[AM_DBG_UART_INST].p_handle,(AM_HAL_UART_INT_RX | AM_HAL_UART_INT_RX_TMOUT)); //uart_intr_open(AM_DBG_UART_INST, (AM_HAL_UART_INT_RX | AM_HAL_UART_INT_RX_TMOUT)); am_hal_uart_interrupt_enable(p_uart_dev->p_handle, (AM_HAL_UART_INT_RX | AM_HAL_UART_INT_RX_TMOUT) | AM_HAL_UART_INT_TXCMP); // // Register the BSP print function to the STDIO driver. // // am_util_stdio_printf_init(am_bsp_uart_string_print_ext); am_util_stdio_printf_init(am_bsp_uart_printf); } // debug_port_uart_enable() //***************************************************************************** // // Disable the UART // //***************************************************************************** void debug_port_uart_disable(void) { drv_uart_t *p_uart_dev = &g_uart_debug; if(p_uart_dev->p_handle == NULL) { return; } // // Make sure the UART has finished sending everything it's going to send. // am_hal_uart_tx_flush(p_uart_dev->p_handle); // // Detach the UART from the stdio driver. // am_util_stdio_printf_init(0); //uart_intr_config_cb(AM_DBG_UART_INST, 0); p_uart_dev->interrupt_cb = NULL; //uart_intr_close(AM_DBG_UART_INST, (AM_HAL_UART_INT_RX | AM_HAL_UART_INT_RX_TMOUT)); am_hal_uart_interrupt_disable(p_uart_dev->p_handle, (AM_HAL_UART_INT_RX | AM_HAL_UART_INT_RX_TMOUT) | AM_HAL_UART_INT_TXCMP); //uart_close(AM_DBG_UART_INST); if ((p_uart_dev->uart_num > AM_REG_UART_NUM_MODULES) || (p_uart_dev == NULL)) { return; } // // Power down the UART, and surrender the handle. // am_hal_uart_power_control(p_uart_dev->p_handle, AM_HAL_SYSCTRL_DEEPSLEEP, false); am_hal_uart_deinitialize(p_uart_dev->p_handle); // // 降低功耗,否则,关闭串口0仍有轻微漏电. // // 下方代码如不注释掉,在关闭了串口1以后,关闭串口0时执行下方代码会引起重启 -- hes 2021.11.24 /* if(uart_num == 0) { UARTn(uart_num)->CR = 0; } */ // // Disable the UART pins. // am_hal_gpio_pinconfig(p_uart_dev->tx.pin, am_hal_gpio_pincfg_disabled); am_hal_gpio_pinconfig(p_uart_dev->rx.pin, am_hal_gpio_pincfg_disabled); p_uart_dev->p_handle = NULL; } // debug_port_uart_disable() void debug_port_uart_user_cb(void *pHandle, uint32_t ui32Status) { //uart_user_cb } void debug_port_uart_user_callback_register(debug_port_uart_isr_cb cb) { g_uart_debug.interrupt_cb = cb; } //no modify void am_uart1_isr(void) { #if defined(AM_PART_APOLLO4) uint32_t ui32Status; #else uint32_t ui32Status, ui32Idle; #endif // // Service the FIFOs as necessary, and clear the interrupts. // am_hal_uart_interrupt_status_get(g_uart_debug.p_handle, &ui32Status, true); am_hal_uart_interrupt_clear(g_uart_debug.p_handle, ui32Status); #if defined(AM_PART_APOLLO4) am_hal_uart_interrupt_service(g_uart_debug.p_handle, ui32Status); #else am_hal_uart_interrupt_service(g_uart_dev[1].p_handle, ui32Status, &ui32Idle); #endif // am_util_stdio_printf("am_uart_isr... ui32Status: 0x%x \n", ui32Status); // // If there's an RX interrupt, handle it in a way that preserves the // timeout interrupt on gaps between packets. // if (g_uart_debug.interrupt_cb) { g_uart_debug.interrupt_cb(g_uart_debug.p_handle, ui32Status); } } //***************************************************************************** // // End Doxygen group. //! @} // //*****************************************************************************