@@ -38,52 +38,75 @@ static uint32_t uartfbrd;
3838static uint32_t uartlcr_h ;
3939static uint32_t uartcr ;
4040
41- /** Pico1 uart uses non-sdk conform defines
42- * @todo Change Pico1 defines if I ever get around to it
43- */
44- #define UART0_UARTIMSC_RXIM_Msk (UART_UARTIMSC_RXIM_BITS)
45-
46- void _irq_enable (uart_t uart ) {
41+ void _irq_enable (uart_t uart )
42+ {
4743 UART0_Type * dev = uart_config [uart ].dev ;
4844 /* We set the UART Receive Interrupt Mask (Bit 4) [See p979 UART 12.1]*/
49- dev -> UARTIMSC = UART0_UARTIMSC_RXIM_Msk ;
45+ dev -> UARTIMSC = UART_UARTIMSC_RXIM_BITS ;
5046 /* Enable the IRQ */
5147 rp_irq_enable (uart_config [uart ].irqn );
5248}
5349
50+ void _set_symbolrate (uart_t uart , uint32_t baud )
51+ {
52+ assert (baud != 0 );
53+ UART0_Type * dev = uart_config [uart ].dev ;
54+ uint32_t baud_rate_div = (8 * CPUFREQ / baud );
55+ uint32_t baud_ibrd = baud_rate_div >> 7 ;
56+ uint32_t baud_fbrd ;
57+
58+ if (baud_ibrd == 0 ) {
59+ baud_ibrd = 1 ;
60+ baud_fbrd = 0 ;
61+ }
62+ else if (baud_ibrd >= 65535 ) {
63+ baud_ibrd = 65535 ;
64+ baud_fbrd = 0 ;
65+ }
66+ else {
67+ baud_fbrd = ((baud_rate_div & 0x7f ) + 1 ) / 2 ;
68+ }
69+
70+ dev -> UARTIBRD = baud_ibrd ;
71+ dev -> UARTFBRD = baud_fbrd ;
72+ }
73+
5474int uart_mode (uart_t uart , uart_data_bits_t data_bits , uart_parity_t parity ,
5575 uart_stop_bits_t stop_bits ) {
5676 assert ((unsigned )uart < UART_NUMOF );
5777 UART0_Type * dev = uart_config [uart ].dev ;
5878
59- (void )data_bits ;
60- (void )stop_bits ;
61-
6279 /* Disable the UART before changing the mode */
6380 atomic_clear (& dev -> UARTCR , UART_UARTCR_UARTEN_BITS | UART_UARTCR_RXE_BITS |
64- UART_UARTCR_TXE_BITS );
65-
66- /* Set the data bits, parity, and stop bits
67- * Set to 8 bits (0b11) based on Table 1035 page 976
68- * @todo allow different data bits
69- */
70- dev -> UARTLCR_H = 0b11 << 5 ;
81+ UART_UARTCR_TXE_BITS | 1 << 7 );
82+
83+ /* Beware of strange hardware bug: If the configuration bitmask is prepared in register and
84+ * transferred with a single 32 bit write (updating both parity and number of data bits at the
85+ * same time), the configuration change of the parity bits will not take place until after the
86+ * next char send out. If the configuration is updated in multiple bus accesses, it will apply
87+ * directly to the next char. So: Double check e.g. with tests/periph/uart_mode after touching
88+ * the initialization code here
89+ * based on Table 1035 page 976 */
90+ dev -> UARTLCR_H = (uint32_t )data_bits << 5 ;
91+
92+ if (stop_bits == UART_STOP_BITS_2 ) {
93+ atomic_set (& dev -> UARTLCR_H , UART0_UARTLCR_H_STP2_Msk );
94+ }
7195
7296 switch (parity ) {
7397 case UART_PARITY_NONE :
7498 break ;
75- /* Currently we don't support parity settings yet
76- * case UART_PARITY_EVEN:
77- * io_reg_atomic_set(&dev->UARTLCR_H, UART0_UARTLCR_H_EPS_Msk | UART0_UARTLCR_H_PEN_Msk);
78- * break;
79- * case UART_PARITY_ODD:
80- * io_reg_atomic_set(&dev->UARTLCR_H, UART0_UARTLCR_H_PEN_Msk);
81- * break; */
99+ case UART_PARITY_EVEN :
100+ atomic_set (& dev -> UARTLCR_H , UART0_UARTLCR_H_EPS_Msk | UART0_UARTLCR_H_PEN_Msk );
101+ break ;
102+ case UART_PARITY_ODD :
103+ atomic_set (& dev -> UARTLCR_H , UART0_UARTLCR_H_PEN_Msk );
104+ break ;
82105 default :
83106 return UART_NOMODE ;
84107 }
85108
86- dev -> UARTCR = UART_UARTCR_TXE_BITS | UART_UARTCR_UARTEN_BITS | UART_UARTCR_RXE_BITS ;
109+ atomic_set ( & dev -> UARTCR , UART_UARTCR_TXE_BITS | UART_UARTCR_UARTEN_BITS | UART_UARTCR_RXE_BITS ) ;
87110
88111 return UART_OK ;
89112}
@@ -105,6 +128,10 @@ static void _reset_uart(uart_t uart) {
105128
106129void uart_init_pins (uart_t uart ) {
107130 assert ((unsigned )uart < UART_NUMOF );
131+
132+ /* We reset UART0 here, so we can be sure it is in a known state */
133+ _reset_uart (uart );
134+
108135 UART0_Type * dev = uart_config [uart ].dev ;
109136
110137 /* Set the UART pins to the correct function */
@@ -123,16 +150,12 @@ void uart_init_pins(uart_t uart) {
123150 calculate_gpio_pad_register_addr (uart_config [uart ].rx_pin ),
124151 PADS_BANK0_GPIO0_IE_BITS );
125152
126- /* We reset UART0 here, so we can be sure it is in a known state */
127- _reset_uart (uart );
128-
129153 dev -> UARTIBRD = IBRD ;
130154 dev -> UARTFBRD = FBRD ;
131155}
132156
133- int uart_init (uart_t uart , uint32_t baud , uart_rx_cb_t rx_cb , void * arg ) {
134- (void )baud ;
135-
157+ int uart_init (uart_t uart , uint32_t baud , uart_rx_cb_t rx_cb , void * arg )
158+ {
136159 if (uart >= UART_NUMOF ) {
137160 return UART_NODEV ;
138161 }
@@ -143,6 +166,8 @@ int uart_init(uart_t uart, uint32_t baud, uart_rx_cb_t rx_cb, void *arg) {
143166
144167 uart_init_pins (uart );
145168
169+ _set_symbolrate (uart , baud );
170+
146171 if (uart_mode (
147172 uart ,
148173 UART_DATA_BITS_8 ,
@@ -164,13 +189,15 @@ int uart_init(uart_t uart, uint32_t baud, uart_rx_cb_t rx_cb, void *arg) {
164189 return UART_OK ;
165190}
166191
167- void uart_write (uart_t uart , const uint8_t * data , size_t len ) {
192+ void uart_write (uart_t uart , const uint8_t * data , size_t len )
193+ {
194+ assert ((unsigned )uart < UART_NUMOF );
168195 UART0_Type * dev = uart_config [uart ].dev ;
196+
169197 for (size_t i = 0 ; i < len ; i ++ ) {
170198 dev -> UARTDR = data [i ];
171199 /* Wait until the TX FIFO is empty before sending the next byte */
172- while (!(dev -> UARTFR & UART_UARTFR_TXFE_BITS )) {
173- }
200+ while (!(dev -> UARTRIS & UART0_UARTRIS_TXRIS_Msk )) { }
174201 }
175202}
176203
@@ -218,11 +245,16 @@ void isr_handler(uint8_t num) {
218245 UART0_Type * dev = uart_config [num ].dev ;
219246
220247 uint32_t status = dev -> UARTMIS ;
221- dev -> UARTICR = status ;
248+ atomic_set ( & dev -> UARTICR , status ) ;
222249
223250 if (status & UART_UARTMIS_RXMIS_BITS ) {
224251 uint32_t data = dev -> UARTDR ;
225- ctx [num ].rx_cb (ctx [num ].arg , (uint8_t )data );
252+ if (data & (UART0_UARTDR_BE_Msk | UART0_UARTDR_PE_Msk | UART0_UARTDR_FE_Msk )) {
253+ puts ("[rpx0xx] uart RX error (parity, break, or framing error" );
254+ }
255+ else {
256+ ctx [num ].rx_cb (ctx [num ].arg , (uint8_t )data );
257+ }
226258 }
227259}
228260
0 commit comments