Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add hardware sync capability to SerialBase #14600

Closed
wants to merge 65 commits into from

Conversation

pennam
Copy link
Contributor

@pennam pennam commented Apr 28, 2021

Summary of changes

Following the discussion here #14420 trying to solve this #14227. Here is a proposal to add hardware sync capability to SerialBase.

For this purpose uart_writable and serial_tx_active were not suitable. uart_writable implementation is different from platform to platform, sometimes it checks if tx buffer/fifo is empty and some other if it is not full. serial_tx_active implementation is related to async API, so the decision to add serial_tx_empty that checks hardware flags to determine if serial transmission is completed.

Impact of changes

serial_tx_empty is not implemented for the following platforms because i didn't found enough information:
TARGET_ARM_FM/TARGET_FVP_MPS2
TARGET_ARM_SSG/TARGET_CM3DS_MPS2
TARGET_ARM_SSG/TARGET_MPS2
all the other platforms should be ok with one note about Maxim LPC and TOSHIBA targets where serial_tx_empty is checking only FIFO status and not uart shift register.

Migration actions required

Documentation

Here there is the implementation status of serial_writable serial_tx_active and serial_tx_empty with some notes:

TARGET_Ambiq_Micro/Target_Apollo3
                         serial_tx_active() -> not implemented
                         serial_writable()  -> transmit FIFO full indicator TXFF
                         serial_tx_empty()  -> transmit FIFO empty indicator TXFE && !TXBUSY
                   
TARGET_Analog_Device/TARGET_ADUCM302X
TARGET_Analog_Device/TARGET_ADUCM4X50
                         serial_tx_active() -> not implemented
                         serial_writable()  -> adi_uart_IsTxBufferAvailable
                         serial_tx_empty()  -> adi_uart_IsTxComplete
                         
TARGET_ARM_FM/TARGET_FVP_MPS2
                         serial_tx_active() -> not implemented
                         serial_writable()  -> !(obj->uart->STATE & 0x1)  not TXBF (tx buffer full flag?)
                         serial_tx_empty()  -> ??TODO??
                         
TARGET_ARM_SSG/TARGET_CM3DS_MPS2  
                         serial_tx_active() -> not implemented
                         serial_writable()  -> arm_uart_tx_ready -> !(p_uart->state & ARM_UART_TX_BF)
                         serial_tx_empty()  -> ??TODO??
                         
TARGET_ARM_SSG/TARGET_MPS2             
                         serial_tx_active() -> not implemented
                         serial_writable()  -> !(obj->uart->STATE & 0x1)  not TXBF (tx buffer full flag?)
                         serial_tx_empty()  -> ??TODO??
                         
TARGET_ARM_SSG/TARGET_MUSCA_B1
                         serial_tx_active() -> not implemented
                         serial_writable()  -> uart_pl011_is_writable -> !UART_PL011_UARTFR_TX_FIFO_FULL
                         serial_tx_empty()  -> uart_pl011_is_tx_empty -> UART_PL011_UARTFR_TX_FIFO_EMPTY && !UART_PL011_UARTFR_BUSYBIT
                         
TARGET_ARM_SSG/TARGET_MUSCA_S1
                         serial_tx_active() -> not implemented
                         serial_writable()  -> uart_pl011_is_writable -> !UART_PL011_UARTFR_TX_FIFO_FULL
                         serial_tx_empty()  -> uart_pl011_is_tx_empty -> UART_PL011_UARTFR_TX_FIFO_EMPTY && !UART_PL011_UARTFR_BUSYBIT                       
                         
TARGET_Cypress/TARGET_PSOC6           
                         serial_tx_active() -> tx active && not complete
                         serial_writable()  -> fifo not full
                         serial_tx_empty()  -> !serial_tx_active()
                         
TARGET_Freescale/TARGET_KL25Z  
                         serial_tx_active() -> not implemented
                         serial_writable()  -> UARTLP_S1_TDRE_MASK
                         serial_tx_empty()  -> UARTLP_S1_TC_MASK
                         
TARGET_Freescale/TARGET_KL46Z  
                         serial_tx_active() -> not implemented
                         serial_writable()  -> UARTLP_S1_TDRE_MASK
                         serial_tx_empty()  -> UARTLP_S1_TC_MASK                         

TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F
                         serial_tx_active() -> tx state not idle
                         serial_writable()  -> (status_flags & kUART_TxDataRegEmptyFlag)
                         serial_tx_empty()  -> ((status_flags & kUART_TxDataRegEmptyFlag) && (status_flags & kUART_TransmissionCompleteFlag));
                         
TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K82F
                         serial_tx_active() -> not implemented
                         serial_writable()  -> (status_flags & kLPUART_TxDataRegEmptyFlag)
                         serial_tx_empty()  -> ((status_flags & kLPUART_TxDataRegEmptyFlag) && (status_flags & kLPUART_TransmissionCompleteFlag));
                         
TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL43Z  
                         serial_tx_active() -> not implemented
                         serial_writable()  -> (status_flags & kLPUART_TxDataRegEmptyFlag)
                         serial_tx_empty()  -> ((status_flags & kLPUART_TxDataRegEmptyFlag) && (status_flags & kLPUART_TransmissionCompleteFlag));
                         
TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KW41Z    
                         serial_tx_active() -> not implemented
                         serial_writable()  -> (status_flags & kUART_TxDataRegEmptyFlag)
                         serial_tx_empty()  -> ((status_flags & kUART_TxDataRegEmptyFlag) && (status_flags & kUART_TransmissionCompleteFlag));
                         
TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_MCU_K22F
                         serial_tx_active() -> not implemented
                         serial_writable()  -> (status_flags & kUART_TxDataRegEmptyFlag)
                         serial_tx_empty()  -> ((status_flags & kUART_TxDataRegEmptyFlag) && (status_flags & kUART_TransmissionCompleteFlag));
                         
TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_MCU_K64F                         
                         serial_tx_active() -> tx state not idle
                         serial_writable()  -> (status_flags & kUART_TxDataRegEmptyFlag)
                         serial_tx_empty()  -> ((status_flags & kUART_TxDataRegEmptyFlag) && (status_flags & kUART_TransmissionCompleteFlag));
                         
TARGET_GigaDevice/TARGET_GD32F4XX
                         serial_tx_active() -> OP_STATE_BUSY_TX
                         serial_writable()  -> USART_FLAG_TBE (transmission buffer empty)
                         serial_tx_empty()  -> USART_FLAG_TBE && USART_FLAG_TC (transmission buffer empty && complete)
                         
TARGET_GigaDevice/TARGET_GD32F30X
                         serial_tx_active() -> OP_STATE_BUSY_TX
                         serial_writable()  -> USART_FLAG_TBE (transmission buffer empty)
                         serial_tx_empty()  -> USART_FLAG_TBE && USART_FLAG_TC (transmission buffer empty && complete)
                         
TARGET_Maxim/TARGET_MAX32620C
                         serial_tx_active() -> not implemented
                         serial_writable()  -> UART_NumWriteAvail
                         serial_tx_empty()  -> MXC_UART_FIFO_DEPTH == UART_NumWriteAvail
                         
TARGET_Maxim/TARGET_MAX32625
                         serial_tx_active() -> not implemented
                         serial_writable()  -> UART_NumWriteAvail
                         serial_tx_empty()  -> MXC_UART_FIFO_DEPTH == UART_NumWriteAvail
                         
TARGET_Maxim/TARGET_MAX32630
                         serial_tx_active() -> not implemented
                         serial_writable()  -> UART_NumWriteAvail
                         serial_tx_empty()  -> MXC_UART_FIFO_DEPTH == UART_NumWriteAvail
                         
TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52
                         serial_tx_active() -> tx_asynch flag
                         serial_writable()  -> !tx_in_progress && NRF_UARTE_EVENT_TXDDY
                         serial_tx_empty()  -> !tx_in_progress && NRF_UARTE_EVENT_TXDDY
                         
TARGET_NUVOTON/TARGET_M251
TARGET_NUVOTON/TARGET_M261
TARGET_NUVOTON/TARGET_M451
TARGET_NUVOTON/TARGET_M480
TARGET_NUVOTON/TARGET_NANO100
TARGET_NUVOTON/TARGET_NUC472
                         serial_tx_active() -> obj->serial.vec == var->vec_async
                         serial_writable()  -> ! UART_IS_TX_FULL
                         serial_tx_empty()  -> UART_GET_TX_EMPTY (set when stop bit of last byte is sent)
                         
TARGET_NXP/TARGET_LPC11XX_11CXX
                         serial_tx_active() -> not implemented
                         serial_writable()  -> LSR & 0x20 Transmitter empty flag
                         serial_tx_empty()  -> LSR & 0x20 Transmitter empty flag (UOTHR UOTSR empty)
                         
TARGET_NXP/TARGET_LPC176X
                         serial_tx_active() -> not implemented
                         serial_writable()  -> CTS + obj->uart->LSR & 0x40 (BUG)
                         serial_tx_empty()  -> LSR & 0x20 Transmitter empty flag (UOTHR UOTSR empty)
                         
TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_IMX      
                         serial_tx_active() -> not implemented
                         serial_writable()  -> (status_flags & kLPUART_TxDataRegEmptyFlag);
                         serial_tx_empty()  -> ((status_flags & kLPUART_TxDataRegEmptyFlag) && (status_flags & kLPUART_TransmissionCompleteFlag));
                         
TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_LPC   
                         serial_tx_active() -> not implemented
                         serial_writable()  -> status_flags & kUSART_TxFifoNotFullFlag
                         serial_tx_empty()  -> status_flags & kUSART_TxFifoEmptyFlag

TARGET_RENESAS/TARGET_RZ_A1XX
TARGET_RENESAS/TARGET_RZ_A2XX
                         serial_tx_active() -> tranferring_obj != NULL
                         serial_writable()  -> TDFE != 0
                         serial_tx_empty()  -> TDFE != 0 && TEND != 0  (FIFO empty and transmission ended)
                         
TARGET_Samsung/TARGET_SIDK_S1SBP6A
                         serial_tx_active() -> not implemented
                         serial_writable()  -> FIFO not full / TX empty (if FIFO is not used)
                         serial_tx_empty()  -> TX_EMPTY (UTRSTAT bit 2 transmit shift register empty)
                         
TARGET_Samsung/TARGET_SIDK_S5JS100
                         serial_tx_active() -> not implemented
                         serial_writable()  -> !(p_PL011_UART->FR & (1u << 5))
                         serial_tx_empty()  -> ((p_PL011_UART->FR & (1u << 7)) && (!(p_PL011_UART->FR & (1u << 7))))

TARGET_Silicon_Labs/TARGET_EFM32
                         serial_tx_active() -> (obj->serial.periph.uart->IEN & (USART_IEN_TXBL|USART_IEN_TXC)) ? true : false;
                         serial_writable()  -> return obj->serial.periph.uart->STATUS & USART_STATUS_TXBL; buffer level set to one if empty
                         serial_tx_empty()  -> ((obj->serial.periph.uart->STATUS & USART_STATUS_TXBL) && (obj->serial.periph.uart->STATUS & USART_STATUS_TXIDLE)); buffer level set to one if empty (TXBIL should be 0)

TARGET_STM  
                        serial_tx_active() -> (((HAL_UART_GetState(huart) & HAL_UART_STATE_BUSY_TX) == HAL_UART_STATE_BUSY_TX) ? 1 : 0);
                        serial_writable()  -> __HAL_UART_GET_FLAG(huart, UART_FLAG_TXE) != RESET
                        serial_tx_empty()  -> __HAL_UART_GET_FLAG(huart, UART_FLAG_TXE) != RESET && 
                                              __HAL_UART_GET_FLAG(huart, UART_FLAG_TC) != RESET 
                        
TARGET_TOSHIBA/TARGET_TMPM4G9
                        serial_tx_active() -> not implemented
                        serial_writable()  -> Status not RUN or TX fifo empty
                        serial_tx_empty()  -> Status not RUN or TX fifo empty
                        
TARGET_TOSHIBA/TARGET_TMPM46B            
                        serial_tx_active() -> not implemented
                        serial_writable()  -> Status DONE or TX fifo empty
                        serial_tx_empty()  -> Status DONE or TX fifo empty

Pull request type

[] Patch update (Bug fix / Target update / Docs update / Test update / Refactor)
[X] Feature update (New feature / Functionality change / New API)
[] Major update (Breaking change E.g. Return code change / API behaviour change)

Test results

Need some help with testing :D

[] No Tests required for this change (E.g docs only update)
[] Covered by existing mbed-os tests (Greentea or Unittest)
[] Tests / results supplied as part of this PR

Reviewers

@facchinm @0xc0170 @kjbracey-arm


@ciarmcom
Copy link
Member

@pennam, thank you for your changes.
@kjbracey-arm @0xc0170 @ARMmbed/team-nordic @ARMmbed/team-cypress @ARMmbed/team-nxp @ARMmbed/team-st-mcd @ARMmbed/mbed-os-core @ARMmbed/team-arm-oss-platform @ARMmbed/team-analogdevices @ARMmbed/team-samsung @ARMmbed/team-silabs @ARMmbed/team-gigadevice @ARMmbed/team-renesas-rz @ARMmbed/team-maximintegrated @ARMmbed/mbed-os-hal @ARMmbed/team-toshiba @ARMmbed/team-nuvoton @ARMmbed/team-sparkfun @ARMmbed/mbed-os-maintainers please review.

@ciarmcom ciarmcom added stale Stale Pull Request and removed stale Stale Pull Request labels Sep 10, 2021
@ciarmcom ciarmcom removed the stale Stale Pull Request label Sep 18, 2021
@hallard
Copy link
Contributor

hallard commented Sep 18, 2021

Hi There,
Just to let you know that I'm facing the issue on STM32WL board, I'm using BufferedSerial and calling sync() never returns. was working fine (modbus board) before (let's says 8 days ago) not anymore, I dirty fixed removing sync() and replaced by delay_ms() but not the best deal of course.
What is strange is that I got old compiled firmware binaries that works, and if I get the same commit of mbed-os used for compiling, it just does lock also.
So my guess it may not be related to mbed-os, only change on my computer is updated mbed-studio and tools, my dev team did the same, same issue. So I asked my customer not updating mbed-studio and guess what? with mbed-os 6.15.0.rcx it does not lock and works fine. So may be an entry point.

@ciarmcom ciarmcom added stale Stale Pull Request and removed stale Stale Pull Request labels Sep 19, 2021
@ciarmcom ciarmcom added the stale Stale Pull Request label Sep 26, 2021
@0xc0170
Copy link
Contributor

0xc0170 commented Oct 12, 2022

I'll close this pull request. Feel free to reopen with an update,

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.