Почему мой модуль ядра UART не отправляет последние 8 символов моего сообщения? - PullRequest
0 голосов
/ 19 апреля 2020

Я строю модуль ядра UART с API RTDM. Для таблицы данных AUART я работал с главой 30 следующей ссылки: Ссылка на таблицу данных

Драйвер очень базовый c, ему нужно только отправить буфер, который передается ему в пространстве пользователя с функцией write. Это работает так:

  1. В функции open, активируйте UART с помощью UARTEN бита регистра управления UART
  2. В write функции, я активирую преобразователь с помощью бита TXE регистра управления UART
  3. Затем начните отправку символов с:
static void rt_mxs_auart_tx_chars(struct rt_mxs_auart_ctx *ctx)

{
    int ch;
    pr_info("Start transmitting\n");

    while (ctx->out_npend > 0 &&
           !(mxs_read(ctx->port, REG_STAT) & AUART_STAT_TXFF)) {

        ch = ctx->out_buf[ctx->out_head++];
        mxs_write(ch, ctx->port, REG_DATA);
        ctx->out_head &= (OUT_BUFFER_SIZE - 1);
        ctx->out_npend--;
    }

    if (mxs_read(ctx->port, REG_STAT) & AUART_STAT_TXFF){
        pr_info("We've stopped transmitting because FIFO is full, remains: %d to be sent (bytes pending)\n", ctx->out_npend);
    }
    if(ctx->out_npend > 0 ) {
        mxs_set(AUART_INTR_TXIEN, ctx->port, REG_INTR);
        pr_info("%d bytes pending, setting AUART_INTR_TXIEN\n", ctx->out_npend);
    }
    else {
        mxs_clr(AUART_INTR_TXIEN, ctx->port, REG_INTR);
        pr_info("%d bytes pending, clearing AUART_INTR_TXIEN\n", ctx->out_npend);
    }
}

TXIEN соответствует Transmit Interrupt Enable, а AUART_STAT_TXFF означает, что FIFO передачи заполнен. Вот структура ctx:

struct rt_mxs_auart_ctx {
    struct rtser_config config; /* current device configuration */

    rtdm_irq_t irq_handle;      /* device IRQ handle */
    rtdm_lock_t lock;       /* lock to protect context struct */

    int in_head;            /* RX ring buffer, head pointer */
    int in_tail;            /* RX ring buffer, tail pointer */
    size_t in_npend;        /* pending bytes in RX ring */
    int in_nwait;           /* bytes the user waits for */
    rtdm_event_t in_event;      /* raised to unblock reader */
    char in_buf[IN_BUFFER_SIZE];    /* RX ring buffer */

    volatile unsigned long in_lock; /* single-reader lock */
    uint64_t *in_history;       /* RX timestamp buffer */

    int out_head;           /* TX ring buffer, head pointer */
    int out_tail;           /* TX ring buffer, tail pointer */
    size_t out_npend;       /* pending bytes in TX ring */
    rtdm_event_t out_event;     /* raised to unblock writer */
    char out_buf[OUT_BUFFER_SIZE];  /* TX ring buffer */
    rtdm_mutex_t out_lock;      /* single-writer mutex */

    uint64_t last_timestamp;    /* timestamp of last event */
    int ioc_events;         /* recorded events */
    rtdm_event_t ioc_event;     /* raised to unblock event waiter */
    volatile unsigned long ioc_event_lock;  /* single-waiter lock */

    int ier_status;         /* IER cache */
    int mcr_status;         /* MCR cache */
    int status;         /* cache for LSR + soft-states */
    int saved_errors;       /* error cache for RTIOC_GET_STATUS */

    /*
     * The port structure holds all the information about the UART
     * port like base address, and so on.
     */
    struct rt_mxs_auart_port *port;
};

В моем обработчике прерываний я делаю это:

    if (istat & AUART_INTR_TXIS){
        pr_info("Transmit Interrupt Status enabled\n");
        rt_mxs_auart_tx_chars(ctx);
        istat &= ~AUART_INTR_TXIS;
        ret = RTDM_IRQ_HANDLED;
    }

, что означает, что если флаг состояния прерывания активен, мы отправляем данные снова с тем же function rt_mxs_auart_tx_chars

Моя проблема в том, что я не получаю конца моего сообщения. Например, если я пытаюсь отправить «Это ... это мое второе сообщение» (29 символов), я получаю только «Это ... это мой набор c» (17 символов). Журнал выглядит следующим образом:

Calling open function
Calling write function
Enabling Transmitter
Start transmitting
We've stopped transmitting because FIFO is full, remains: 12 to be sent (bytes pending)
12 bytes pending, setting AUART_INTR_TXIEN
IRQ handler called
Transmit Interrupt Status enabled
Start transmitting
We've stopped transmitting because FIFO is full, remains: 4 to be sent (bytes pending)
4 bytes pending, setting AUART_INTR_TXIEN
Receive Interrupt Status or Receive Timeout Interrupt Status enabled
IRQ handler called
Transmit Interrupt Status enabled
Start transmitting
0 bytes pending, clearing AUART_INTR_TXIEN
Disabling Transmitter

Как вы думаете, я могу это исправить?

...