Nordic DTM(Direct Test Mode)

226 阅读2分钟

问题要点

Direct Test Mode工程修改串口无效

默认串口

#define RX_PIN_NUMBER  8
#define TX_PIN_NUMBER  6
#define CTS_PIN_NUMBER 7
#define RTS_PIN_NUMBER 5

而我的开发板上只能引出P0.08和P0.10GPIO, 配置之后,通过TX发送信号失败,即使单独设置P0.10 GPIO配置为Output, 拉高或者拉低都无效。电平始终是在1.1V左右

解决方法

Bootloader + application的方式,再配置TX_PIN_NUMBER为10,串口可正常工作

时序问题

int main(void)
{
    uint32_t    current_time;
    uint8_t     rx_byte;
    ret_code_t err_code;
    bool        is_msb_read       = false;
    uint32_t    msb_time          = 0;
    uint16_t    dtm_cmd_from_uart = 0;
    dtm_event_t result;                    // Result of a DTM operation.
    
    uint32_t    dtm_error_code;

    uart_init();
    dtm_error_code = dtm_init();
    SEGGER_RTT_WriteString(0, "test-------------\n");

    if (dtm_error_code != DTM_SUCCESS)
    {
        SEGGER_RTT_WriteString(0, "test++++++\n");
        // If DTM cannot be correctly initialized, then we just return.
        return -1;
    }

    for (;;)
    {
        // Will return every timeout, 625 us.
        // current_time = dtm_wait();
        if (app_uart_get(&rx_byte) != NRF_SUCCESS)
        {
            // Nothing read from the UART.
            continue;
        }
        SEGGER_RTT_printf(0, "Hello, RX:0x%x!\n", rx_byte);
        if (!is_msb_read)
        {
            // This is first byte of two-byte command.
            is_msb_read       = true;
            dtm_cmd_from_uart = ((dtm_cmd_t)rx_byte) << 8;
            msb_time          = current_time;
            SEGGER_RTT_printf(0, "is_msb_read, TX:0x%x!\n", dtm_cmd_from_uart);
            // Go back and wait for 2nd byte of command word.
            continue;
        }
        SEGGER_RTT_printf(0, "++++++++++++is_msb_read, TX:0x%x!\n", dtm_cmd_from_uart);

        if (current_time > (msb_time + MAX_ITERATIONS_NEEDED_FOR_NEXT_BYTE) * 3)
        {
            // More than ~5mS after msb: Drop old byte, take the new byte as MSB.
            // The variable is_msb_read will remains true.
            // Go back and wait for 2nd byte of the command word.
            SEGGER_RTT_printf(0, "MAX_ITERATIONS_NEEDED_FOR_NEXT_BYTE current time:0x%x, msb_time + %d\n", current_time, (msb_time + MAX_ITERATIONS_NEEDED_FOR_NEXT_BYTE));
            dtm_cmd_from_uart = ((dtm_cmd_t)rx_byte) << 8;
            msb_time          = current_time;
            continue;
        }
        is_msb_read        = false;
        
        dtm_cmd_from_uart |= (dtm_cmd_t)rx_byte;
        SEGGER_RTT_printf(0, "33333333333333333333333 dmt cmd:0x%x --- real cmd:%d\n", dtm_cmd_from_uart, ((dtm_cmd_from_uart >> 14) & 0x03));
        if (dtm_cmd(dtm_cmd_from_uart) != DTM_SUCCESS)
        {
            // Extended error handling may be put here.
            // Default behavior is to return the event on the UART (see below);
            // the event report will reflect any lack of success.
            SEGGER_RTT_printf(0, "444444444444444444444444444\n");
        }

        // Retrieve result of the operation. This implementation will busy-loop
        // for the duration of the byte transmissions on the UART.
        if (dtm_event_get(&result))
        {
            SEGGER_RTT_printf(0, "55555555555555555:0x%x\n", result);
            // Report command status on the UART.
            // Transmit MSB of the result.
            while (app_uart_put((result >> 8) & 0xFF));
            // Transmit LSB of the result.
            while (app_uart_put(result & 0xFF));
        }
    }
}