From 5102fff8a13c0319d8125a51d3d2354e7aacdcea Mon Sep 17 00:00:00 2001 From: chen <15335560115@163.com> Date: 星期四, 31 七月 2025 16:40:06 +0800 Subject: [PATCH] 修改为2HZ发poll包,修改second task从原来2s一次为1s一次 --- keil/include/drivers/mk_uart.c | 388 ++++++++++++++++++++++++++++++++++++------------------ 1 files changed, 257 insertions(+), 131 deletions(-) diff --git a/keil/include/drivers/mk_uart.c b/keil/include/drivers/mk_uart.c index 5b24f04..f29ccb0 100644 --- a/keil/include/drivers/mk_uart.c +++ b/keil/include/drivers/mk_uart.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019-2023 Beijing Hanwei Innovation Technology Ltd. Co. and + * Copyright (c) 2019-2025 Beijing Hanwei Innovation Technology Ltd. Co. and * its subsidiaries and affiliates (collectly called MKSEMI). * * All rights reserved. @@ -59,13 +59,13 @@ .dma_tx_ch = DMA_CH7, }, }; -//脪脝脰虏 -uint32_t SerialKeyPressed(uint8_t *key)//脜脨露脧脢媒戮脻脢脟路帽脢脮碌陆碌脛 MK8000脨脼赂脛 +//ò??2 +uint32_t SerialKeyPressed(uint8_t *key)//?D??êy?Yê?·?ê?μ?μ? MK8000DT?? { uint32_t status = uart_handle[1].base->STATUS; if (status & UART_STATUS_DR_MSK) { - //Serial0PutString("鲁脡鹿娄陆脫脢脮ing"); + //Serial0PutString("3é1|?óê?ing"); //uart_receive(UART_ID1,test_buf,10,NULL); *key = (uint8_t)uart_handle[1].base->RX_DATA; //uart_rx_fifo_clear(UART_ID1); @@ -93,7 +93,7 @@ } } void Serial0PutChar(uint8_t c) -{ //脜脨露脧脢媒戮脻禄潞麓忙脟酶脦陋驴脮录麓脡脧脪禄赂枚脳脰陆脷脢媒戮脻脪脩戮颅卤禄脣脥碌陆路垄脣脥录脛麓忙脝梅路垄脣脥鲁枚脠楼脕脣 +{ //?D??êy?Y?o′????a???′é?ò???×??úêy?Yò??-±??íμ?·¢?í??′??÷·¢?í3?è¥á? // wait TX FIFO empty while (uart_handle[0].base->TX_FL) { @@ -139,37 +139,37 @@ // update state switch (uart_handle[id].state) { - case UART_STATE_READY: - uart_handle[id].state = state; - break; - case UART_STATE_BUSY_RX: - if (state == UART_STATE_BUSY_TX) - { - uart_handle[id].state = UART_STATE_BUSY_TX_RX; - } - else - { + case UART_STATE_READY: + uart_handle[id].state = state; + break; + case UART_STATE_BUSY_RX: + if (state == UART_STATE_BUSY_TX) + { + uart_handle[id].state = UART_STATE_BUSY_TX_RX; + } + else + { + ret = DRV_BUSY; + } + break; + case UART_STATE_BUSY_TX: + if (state == UART_STATE_BUSY_RX) + { + uart_handle[id].state = UART_STATE_BUSY_TX_RX; + } + else + { + ret = DRV_BUSY; + } + break; + case UART_STATE_BUSY_TX_RX: ret = DRV_BUSY; - } - break; - case UART_STATE_BUSY_TX: - if (state == UART_STATE_BUSY_RX) - { - uart_handle[id].state = UART_STATE_BUSY_TX_RX; - } - else - { - ret = DRV_BUSY; - } - break; - case UART_STATE_BUSY_TX_RX: - ret = DRV_BUSY; - break; - case UART_STATE_RESET: - case UART_STATE_TIMEOUT: - case UART_STATE_ERROR: - ret = DRV_ERROR; - break; + break; + case UART_STATE_RESET: + case UART_STATE_TIMEOUT: + case UART_STATE_ERROR: + ret = DRV_ERROR; + break; } int_unlock(lock); @@ -193,15 +193,24 @@ return uart_handle[id].state; } -bool uart_tx_in_progress(enum UART_DEV_T id) +bool uart_is_busy(enum UART_DEV_T id) { - return ((uart_handle[id].state & UART_STATE_BUSY_TX) && (uart_handle[id].base->STATUS & UART_STATUS_BUSY_MSK)); + // - Transmission in progress on serial interface + // - Transmit data present in TX FIFO + // - Reception in progress on the interface + // - Receive data present in RX FIFO + // - [Patch] UART is not enabled but RX is pulled low + return ((uart_handle[id].state != UART_STATE_RESET) && (uart_handle[id].base->STATUS & UART_STATUS_BUSY_MSK)); } -bool uart_fifo_busy(enum UART_DEV_T id) +bool uart_tx_in_progress(enum UART_DEV_T id) { - // UART is not enabled but RX is pulled low - return ((uart_handle[id].state != UART_STATE_RESET) && (uart_handle[id].base->STATUS & UART_STATUS_BUSY_MSK)); + return ((uart_handle[id].state & UART_STATE_BUSY_TX) || !(uart_handle[id].base->STATUS & UART_STATUS_TEMT_MSK)); +} + +bool uart_tx_fifo_is_empty(enum UART_DEV_T id) +{ + return (uart_handle[id].base->STATUS & UART_STATUS_TEMT_MSK); } void uart_rx_fifo_clear(enum UART_DEV_T id) @@ -210,6 +219,13 @@ while (uart_handle[id].base->STATUS & UART_STATUS_RFNE_MSK) { uart_handle[id].base->RX_DATA; + } + + if (uart_handle[id].dma_en) + { + // reset RX FIFO, clear DMA request for rx fifo + // Note: It is not recommended to use UART DMA software ack, as this may affect the actively working TX unless in half-duplex mode + uart_handle[id].base->CTRL0 = uart_handle[id].ctrl0 | UART_CTRL0_RX_FIFO_RESET_MSK; } } @@ -432,14 +448,6 @@ while (uart_handle[id].tx_count < uart_handle[id].tx_size) { status = uart_handle[id].base->STATUS; - if (status & (UART_STATUS_OE_MSK | UART_STATUS_PE_MSK | UART_STATUS_FE_MSK | UART_STATUS_BI_MSK | UART_STATUS_RFE_MSK)) - { - // TODO: user handle the error case - uart_handle[id].base->INTR_CLR = UART_INTR_CLR_LSR_INT_CLR_MSK; - status |= UART_ERR_LINE; - ret = DRV_ERROR; - break; - } if (uart_handle[id].base->STATUS & UART_STATUS_TFNF_MSK) { @@ -544,8 +552,6 @@ if (status & (UART_STATUS_OE_MSK | UART_STATUS_PE_MSK | UART_STATUS_FE_MSK | UART_STATUS_BI_MSK | UART_STATUS_RFE_MSK)) { // TODO: user handle the error case - // Clear error bits - uart_handle[id].base->INTR_CLR = UART_INTR_CLR_LSR_INT_CLR_MSK; status |= UART_ERR_LINE; ret = DRV_ERROR; break; @@ -569,6 +575,91 @@ } return ret; +} + +int uart_dma_receive_with_llp(enum UART_DEV_T id, uint8_t *rx_buf, uint32_t len, struct DMA_LINK_DESC_T *desc, drv_callback_t callback) +{ + if ((rx_buf == 0) || (len == 0) || !(uart_handle[id].dma_en) || (desc == NULL)) + { + return DRV_ERROR; + } + + // update state + int ret = uart_state_set(id, UART_STATE_BUSY_RX); + if (ret != DRV_OK) + { + return ret; + } + + uart_handle[id].rx_callback = callback; + + // fix TX output low level when host MCU reset + uint32_t err_code = uart_handle[id].base->STATUS; + if (err_code & (UART_STATUS_FE_MSK | UART_STATUS_BI_MSK | UART_STATUS_RFE_MSK)) + { + // reset FIFO + uart_handle[id].base->CTRL0 = UART_CTRL0_RX_FIFO_RESET_MSK | UART_CTRL0_TX_FIFO_RESET_MSK; + // clear STATUS + uart_handle[id].base->INTR_CLR = + UART_INTR_CLR_THRE_INT_CLR_MSK | UART_INTR_CLR_BUSY_INT_CLR_MSK | UART_INTR_CLR_LSR_INT_CLR_MSK | UART_INTR_CLR_MSR_INT_CLR_MSK; + uart_handle[id].base->CTRL0 = uart_handle[id].ctrl0; + } + + struct DMA_CH_CFG_T uart_rx_dma_cfg = { + .fifo_th = DMA_FIFO_TH_1, + .src_burst_size = DMA_SRC_BURST_SIZE_1, + .src_width = DMA_WIDTH_1B, + .dst_width = DMA_WIDTH_1B, + .src_addr_ctrl = DMA_ADDR_FIXED, + .dst_addr_ctrl = DMA_ADDR_INC, + .src_req_sel = (id == UART_ID1 ? DMA_REQ_UART1_RX : DMA_REQ_UART0_RX), + .dst_req_sel = DMA_REQ_MEM, + }; + uart_handle[id].dma_rx_err_state = 0; + + NVIC_ClearPendingIRQ(uart_handle[id].irq); + // Enable Receiver Line Status Interrupt, used to obtain the error interrupt event triggered by the receiver + uart_handle[id].base->INTR_EN = (UART_INTR_EN_ELCOLR_MSK | UART_INTR_EN_ELSI_MSK); + + dma_open(uart_handle[id].dma_rx_ch, &uart_rx_dma_cfg); + DMA->CH[uart_handle[id].dma_rx_ch].CHAIN_PTR = (uint32_t)desc; + while (desc) + { + desc->src_addr = (uint32_t)&uart_handle[id].base->RX_DATA; + desc->ctrl = uart_rx_dma_cfg.fifo_th << 29 | uart_rx_dma_cfg.src_width << 25 | uart_rx_dma_cfg.dst_width << 22 | uart_rx_dma_cfg.src_addr_ctrl << 20 | + uart_rx_dma_cfg.dst_addr_ctrl << 18; + desc = desc->nxt; + } + dma_transfer(uart_handle[id].dma_rx_ch, (uint8_t *)&uart_handle[id].base->RX_DATA, rx_buf, len, uart_dma_callback); + + return ret; +} + +void uart_send_over_fifo(enum UART_DEV_T id, uint8_t *tx_buf, uint32_t len) +{ + for (uint32_t i = 0; i < len; i++) + { + uart_handle[id].base->TX_DATA = tx_buf[i]; + } +} + +uint32_t uart_receive_from_fifo(enum UART_DEV_T id, uint8_t *rx_buf, uint32_t len) +{ + for (uint32_t i = 0; i < len; i++) + { + uint32_t status = uart_handle[id].base->STATUS; + + if (status & UART_STATUS_RFNE_MSK) + { + rx_buf[i] = (uint8_t)uart_handle[id].base->RX_DATA; + } + else + { + return i; + } + } + + return len; } int uart_tx_abort_dma(enum UART_DEV_T id, drv_callback_t abort_tx_callback) @@ -598,6 +689,24 @@ uart_handle[id].base->CTRL0 = uart_handle[id].ctrl0 | UART_CTRL0_RX_FIFO_RESET_MSK; uart_handle[id].rx_abort_callback = abort_rx_callback; ret = dma_abort(uart_handle[id].dma_rx_ch, uart_dma_abort_callback); + } +#endif + return ret; +} + +int uart_rx_force_abort_dma(enum UART_DEV_T id, drv_callback_t abort_rx_callback) +{ + int ret = DRV_ERROR; +#if UART_DMA_MODE_EN + if (uart_handle[id].dma_en) + { + // RX err - disable interrupts + uart_handle[id].base->INTR_EN &= ~(UART_INTR_EN_ELCOLR_MSK | UART_INTR_EN_ELSI_MSK); + // reset rx FIFO, de-assert the DMA RX request + uart_handle[id].base->CTRL0 = uart_handle[id].ctrl0 | UART_CTRL0_RX_FIFO_RESET_MSK; + uart_handle[id].rx_abort_callback = abort_rx_callback; + dma_force_abort(uart_handle[id].dma_rx_ch, uart_dma_abort_callback); + ret = DRV_OK; } #endif return ret; @@ -710,6 +819,16 @@ // RX done usr_callback = uart_handle[id].rx_callback; + if ((DMA->CH[uart_handle[id].dma_rx_ch].CFG & 0x000F0000) != 0) + { + if (usr_callback) + { + usr_callback(&id, err_code); + } + + return; + } + // update state uart_state_clear(id, UART_STATE_BUSY_RX); } @@ -747,26 +866,22 @@ void uart_irq_handler(enum UART_DEV_T id) { drv_callback_t usr_callback = NULL; - uint32_t err_code = 0; - - // read interrupt ID - uint8_t iid = uart_handle[id].base->INTR_STATUS & 0x0f; + uint32_t err_code = uart_handle[id].base->STATUS; // If DMA is enabled, the uart interrupt handler is only used to handle the error events reported by the receiver if (uart_handle[id].dma_en) { #if UART_DMA_MODE_EN - err_code = uart_handle[id].base->STATUS; // iid == 0xC: The precondition that the timeout event will not be triggered is that the length of // the received data is an integer multiple of the RX FIFO level - if ((err_code & UART_STATUS_ERROR_MSK) || (iid == 0x0C) || (iid == 0x01)) + if (err_code & UART_STATUS_ERROR_MSK) { // RX err - disable interrupts uart_handle[id].base->INTR_EN &= ~UART_INTR_EN_ELSI_MSK; uart_handle[id].base->INTR_CLR = UART_INTR_CLR_LSR_INT_CLR_MSK; - uart_handle[id].dma_rx_err_state = UART_ERR_LINE | iid; + uart_handle[id].dma_rx_err_state = UART_ERR_LINE; usr_callback = uart_handle[id].rx_callback; - err_code = UART_ERR_LINE | iid; + err_code |= UART_ERR_LINE; // update state uart_state_clear(id, UART_STATE_BUSY_RX); @@ -781,108 +896,119 @@ else { #if UART_INT_MODE_EN + // read interrupt ID + uint8_t iid = uart_handle[id].base->INTR_STATUS & 0x0f; + switch (iid) { // modem status - case 0x0: - // clear int - uart_handle[id].base->INTR_CLR = UART_INTR_CLR_MSR_INT_CLR_MSK; - err_code = UART_ERR_MODEM | iid; - break; + case 0x0: + // clear int + uart_handle[id].base->INTR_CLR = UART_INTR_CLR_MSR_INT_CLR_MSK; + err_code |= UART_ERR_MODEM; + break; // no interrupt pending - case 0x1: - break; + case 0x1: + break; // TX_DATA empty - case 0x2: - // clear int - uart_handle[id].base->INTR_CLR = UART_INTR_CLR_THRE_INT_CLR_MSK; - if ((uart_handle[id].state == UART_STATE_BUSY_TX) || (uart_handle[id].state == UART_STATE_BUSY_TX_RX)) - { - if (uart_handle[id].tx_count == uart_handle[id].tx_size) + case 0x2: + // clear int + uart_handle[id].base->INTR_CLR = UART_INTR_CLR_THRE_INT_CLR_MSK; + if ((uart_handle[id].state == UART_STATE_BUSY_TX) || (uart_handle[id].state == UART_STATE_BUSY_TX_RX)) { - // TX done - disable interrupt - uart_handle[id].base->INTR_EN &= ~UART_INTR_EN_ETBEI_MSK; - usr_callback = uart_handle[id].tx_callback; + if (uart_handle[id].tx_count == uart_handle[id].tx_size) + { + // TX done - disable interrupt + uart_handle[id].base->INTR_EN &= ~UART_INTR_EN_ETBEI_MSK; + usr_callback = uart_handle[id].tx_callback; - // update state - uart_state_clear(id, UART_STATE_BUSY_TX); + // update state + uart_state_clear(id, UART_STATE_BUSY_TX); - uart_handle[id].tx_buff = NULL; - uart_handle[id].tx_callback = NULL; - uart_handle[id].tx_count = 0; - uart_handle[id].tx_size = 0; + uart_handle[id].tx_buff = NULL; + uart_handle[id].tx_callback = NULL; + uart_handle[id].tx_count = 0; + uart_handle[id].tx_size = 0; + } + else + { + // TX continue - write data to FIFO + while ((uart_handle[id].tx_count < uart_handle[id].tx_size) && (uart_handle[id].base->STATUS & UART_STATUS_TFNF_MSK)) + { + uart_handle[id].base->TX_DATA = uart_handle[id].tx_buff[uart_handle[id].tx_count++]; + } + } } else { - // TX continue - write data to FIFO - while ((uart_handle[id].tx_count < uart_handle[id].tx_size) && (uart_handle[id].base->STATUS & UART_STATUS_TFNF_MSK)) - { - uart_handle[id].base->TX_DATA = uart_handle[id].tx_buff[uart_handle[id].tx_count++]; - } + // should not get this interrupt in any other state + ASSERT(0, "Uart %d state goes wrong %d", id, uart_handle[id].state); } - } - else - { - // should not get this interrupt in any other state - ASSERT(0, "Uart %d state goes wrong %d", id, uart_handle[id].state); - } - break; + break; // timeout - case 0xc: + case 0xc: // No characters in or out of the RCVR FIFO during the last 4 character times and // there is at least 1 character in it during this time // received data available - case 0x4: - if ((uart_handle[id].state == UART_STATE_BUSY_RX) || (uart_handle[id].state == UART_STATE_BUSY_TX_RX)) - { - // uint8_t len = uart_handle[id].base->RX_FL; - while ((uart_handle[id].rx_count < uart_handle[id].rx_size) && (uart_handle[id].base->STATUS & UART_STATUS_RFNE_MSK)) + case 0x4: + if ((uart_handle[id].state == UART_STATE_BUSY_RX) || (uart_handle[id].state == UART_STATE_BUSY_TX_RX)) { - uint8_t data = (uint8_t)uart_handle[id].base->RX_DATA; - uart_handle[id].rx_buff[uart_handle[id].rx_count++] = data; - } + // uint8_t len = uart_handle[id].base->RX_FL; + while ((uart_handle[id].rx_count < uart_handle[id].rx_size) && (uart_handle[id].base->STATUS & UART_STATUS_RFNE_MSK)) + { + uint8_t data = (uint8_t)uart_handle[id].base->RX_DATA; + uart_handle[id].rx_buff[uart_handle[id].rx_count++] = data; + } - if (uart_handle[id].rx_count == uart_handle[id].rx_size) + if (uart_handle[id].rx_count == uart_handle[id].rx_size) + { + // RX done - disable interrupts + uart_handle[id].base->INTR_EN &= ~(UART_INTR_EN_ELSI_MSK | UART_INTR_EN_ERBFI_MSK); + usr_callback = uart_handle[id].rx_callback; + + // update state + uart_state_clear(id, UART_STATE_BUSY_RX); + + uart_handle[id].rx_buff = NULL; + uart_handle[id].rx_callback = NULL; + uart_handle[id].rx_count = 0; + uart_handle[id].rx_size = 0; + } + } + else { - // RX done - disable interrupts - uart_handle[id].base->INTR_EN &= ~(UART_INTR_EN_ELSI_MSK | UART_INTR_EN_ERBFI_MSK); - usr_callback = uart_handle[id].rx_callback; - - // update state - uart_state_clear(id, UART_STATE_BUSY_RX); - - uart_handle[id].rx_buff = NULL; - uart_handle[id].rx_callback = NULL; - uart_handle[id].rx_count = 0; - uart_handle[id].rx_size = 0; + // received unexpected data } - } - else - { - // received unexpected data - } - break; + break; // receiver line status - case 0x6: - // clear int - uart_handle[id].base->INTR_CLR = UART_INTR_CLR_LSR_INT_CLR_MSK; - err_code = UART_ERR_LINE | iid; - break; + case 0x6: + // clear int (Overrun/parity/framing errors, break interrupt, or address received interrupt) + // RX err - disable interrupts + uart_handle[id].base->INTR_EN &= ~UART_INTR_EN_ELSI_MSK; + uart_handle[id].base->INTR_CLR = UART_INTR_CLR_LSR_INT_CLR_MSK; + usr_callback = uart_handle[id].rx_callback; + err_code |= UART_ERR_LINE; + + uart_handle[id].rx_buff = NULL; + uart_handle[id].rx_callback = NULL; + uart_handle[id].rx_count = 0; + uart_handle[id].rx_size = 0; + break; // busy detect - case 0x7: - // clear int - uart_handle[id].base->INTR_CLR = UART_INTR_CLR_BUSY_INT_CLR_MSK; - err_code = UART_ERR_BUSY | iid; - break; + case 0x7: + // clear int + uart_handle[id].base->INTR_CLR = UART_INTR_CLR_BUSY_INT_CLR_MSK; + err_code |= UART_ERR_BUSY; + break; - default: - break; + default: + break; } #endif } -- Gitblit v1.9.3