@@ -130,152 +130,91 @@ void* hal_get_dts_address(void)
130130#define DEBUG_UART_BASE MSS_UART1_LO_BASE
131131#endif
132132
133- /***************************************************************************/ /**
134- * Configure baud divisors using fractional baud rate if possible.
133+ /* Configure baud divisors with fractional baud rate support.
134+ *
135+ * UART baud rate divisor formula: divisor = PCLK / (baudrate * 16)
136+ *
137+ * To support fractional divisors (6-bit, 0-63), we scale up the calculation:
138+ * divisor_x128 = (PCLK * 8) / baudrate (128x scaled for rounding precision)
139+ * divisor_x64 = divisor_x128 / 2 (64x scaled for 6-bit fractional)
140+ * integer_div = divisor_x64 / 64 (integer portion of divisor)
141+ * frac_div = divisor_x64 % 64 (fractional portion, 0-63)
142+ *
143+ * The fractional part is then adjusted using the x128 value for rounding.
135144 */
136- static void config_baud_divisors (uint32_t baudrate )
145+ static void uart_config_clk (uint32_t baudrate )
137146{
138- uint32_t baud_value ;
139- uint32_t baud_value_by_64 ;
140- uint32_t baud_value_by_128 ;
141- uint32_t fractional_baud_value ;
142- uint64_t pclk_freq ;
143-
144- /* Use the system clock value from hw_platform.h */
145- pclk_freq = MSS_APB_AHB_CLK ;
146-
147- /*
148- * Compute baud value based on requested baud rate and PCLK frequency.
149- * The baud value is computed using the following equation:
150- * baud_value = PCLK_Frequency / (baud_rate * 16)
151- */
152- baud_value_by_128 = (uint32_t )((8UL * pclk_freq ) / baudrate );
153- baud_value_by_64 = baud_value_by_128 / 2u ;
154- baud_value = baud_value_by_64 / 64u ;
155- fractional_baud_value = baud_value_by_64 - (baud_value * 64u );
156- fractional_baud_value += (baud_value_by_128 - (baud_value * 128u ))
157- - (fractional_baud_value * 2u );
158-
159- if (baud_value <= (uint32_t )UINT16_MAX ) {
160- if (baud_value > 1u ) {
161- /*
162- * Use Fractional baud rate divisors
163- */
164- /* set divisor latch */
165- MMUART_LCR (DEBUG_UART_BASE ) |= DLAB_MASK ;
166-
167- /* baud value */
168- MMUART_DMR (DEBUG_UART_BASE ) = (uint8_t )(baud_value >> 8 );
169- MMUART_DLR (DEBUG_UART_BASE ) = (uint8_t )baud_value ;
170-
171- /* reset divisor latch */
172- MMUART_LCR (DEBUG_UART_BASE ) &= ~DLAB_MASK ;
173-
174- /* Enable Fractional baud rate */
175- MMUART_MM0 (DEBUG_UART_BASE ) |= EFBR_MASK ;
176-
177- /* Load the fractional baud rate register */
178- MMUART_DFR (DEBUG_UART_BASE ) = (uint8_t )fractional_baud_value ;
179- }
180- else {
181- /*
182- * Do NOT use Fractional baud rate divisors.
183- */
184- /* set divisor latch */
185- MMUART_LCR (DEBUG_UART_BASE ) |= DLAB_MASK ;
186-
187- /* baud value */
188- MMUART_DMR (DEBUG_UART_BASE ) = (uint8_t )(baud_value >> 8u );
189- MMUART_DLR (DEBUG_UART_BASE ) = (uint8_t )baud_value ;
190-
191- /* reset divisor latch */
192- MMUART_LCR (DEBUG_UART_BASE ) &= ~DLAB_MASK ;
193-
194- /* Disable Fractional baud rate */
195- MMUART_MM0 (DEBUG_UART_BASE ) &= ~EFBR_MASK ;
196- }
147+ const uint64_t pclk = MSS_APB_AHB_CLK ;
148+
149+ /* Scale up for precision: (PCLK * 128) / (baudrate * 16) */
150+ uint32_t div_x128 = (uint32_t )((8UL * pclk ) / baudrate );
151+ uint32_t div_x64 = div_x128 / 2u ;
152+
153+ /* Extract integer and fractional parts */
154+ uint32_t div_int = div_x64 / 64u ;
155+ uint32_t div_frac = div_x64 - (div_int * 64u );
156+
157+ /* Apply rounding correction from x128 calculation */
158+ div_frac += (div_x128 - (div_int * 128u )) - (div_frac * 2u );
159+
160+ if (div_int > (uint32_t )UINT16_MAX )
161+ return ;
162+
163+ /* Write 16-bit divisor: set DLAB, write high/low bytes, clear DLAB */
164+ MMUART_LCR (DEBUG_UART_BASE ) |= DLAB_MASK ;
165+ MMUART_DMR (DEBUG_UART_BASE ) = (uint8_t )(div_int >> 8 );
166+ MMUART_DLR (DEBUG_UART_BASE ) = (uint8_t )div_int ;
167+ MMUART_LCR (DEBUG_UART_BASE ) &= ~DLAB_MASK ;
168+
169+ /* Enable fractional divisor if integer divisor > 1 */
170+ if (div_int > 1u ) {
171+ MMUART_MM0 (DEBUG_UART_BASE ) |= EFBR_MASK ;
172+ MMUART_DFR (DEBUG_UART_BASE ) = (uint8_t )div_frac ;
173+ }
174+ else {
175+ MMUART_MM0 (DEBUG_UART_BASE ) &= ~EFBR_MASK ;
197176 }
198177}
199178
200179void uart_init (void )
201180{
202- uint32_t baud_rate = 115200 ;
203- uint32_t line_config = (
204- MSS_UART_DATA_8_BITS |
205- MSS_UART_NO_PARITY |
206- MSS_UART_ONE_STOP_BIT
207- );
208-
209- /* Disable LIN mode */
181+ /* Disable special modes: LIN, IrDA, SmartCard */
210182 MMUART_MM0 (DEBUG_UART_BASE ) &= ~ELIN_MASK ;
211-
212- /* Disable IrDA mode */
213183 MMUART_MM1 (DEBUG_UART_BASE ) &= ~EIRD_MASK ;
214-
215- /* Disable SmartCard Mode */
216184 MMUART_MM2 (DEBUG_UART_BASE ) &= ~EERR_MASK ;
217185
218- /* disable interrupts */
186+ /* Disable interrupts */
219187 MMUART_IER (DEBUG_UART_BASE ) = 0u ;
220188
221- /* FIFO configuration */
189+ /* Reset and configure FIFOs, enable RXRDYN/TXRDYN pins */
222190 MMUART_FCR (DEBUG_UART_BASE ) = 0u ;
223-
224- /* clear receiver FIFO */
225- MMUART_FCR (DEBUG_UART_BASE ) |= CLEAR_RX_FIFO_MASK ;
226-
227- /* clear transmitter FIFO */
228- MMUART_FCR (DEBUG_UART_BASE ) |= CLEAR_TX_FIFO_MASK ;
229-
230- /* set default READY mode : Mode 0*/
231- /* enable RXRDYN and TXRDYN pins. The earlier FCR write to set the TX FIFO
232- * trigger level inadvertently disabled the FCR_RXRDY_TXRDYN_EN bit. */
191+ MMUART_FCR (DEBUG_UART_BASE ) |= CLEAR_RX_FIFO_MASK | CLEAR_TX_FIFO_MASK ;
233192 MMUART_FCR (DEBUG_UART_BASE ) |= RXRDY_TXRDYN_EN_MASK ;
234193
235- /* disable loopback : local * remote */
236- MMUART_MCR (DEBUG_UART_BASE ) &= ~LOOP_MASK ;
237-
238- MMUART_MCR (DEBUG_UART_BASE ) &= ~RLOOP_MASK ;
239-
240- /* set default TX endian */
241- MMUART_MM1 (DEBUG_UART_BASE ) &= ~E_MSB_TX_MASK ;
194+ /* Disable loopback (local and remote) */
195+ MMUART_MCR (DEBUG_UART_BASE ) &= ~(LOOP_MASK | RLOOP_MASK );
242196
243- /* set default RX endian */
244- MMUART_MM1 (DEBUG_UART_BASE ) &= ~E_MSB_RX_MASK ;
197+ /* Set LSB-first for TX/RX */
198+ MMUART_MM1 (DEBUG_UART_BASE ) &= ~( E_MSB_TX_MASK | E_MSB_RX_MASK ) ;
245199
246- /* default AFM : disabled */
247- MMUART_MM2 (DEBUG_UART_BASE ) &= ~EAFM_MASK ;
200+ /* Disable AFM, single wire mode */
201+ MMUART_MM2 (DEBUG_UART_BASE ) &= ~( EAFM_MASK | ESWM_MASK ) ;
248202
249- /* disable TX time guard */
250- MMUART_MM0 (DEBUG_UART_BASE ) &= ~ETTG_MASK ;
203+ /* Disable TX time guard, RX timeout, fractional baud */
204+ MMUART_MM0 (DEBUG_UART_BASE ) &= ~( ETTG_MASK | ERTO_MASK | EFBR_MASK ) ;
251205
252- /* set default RX timeout */
253- MMUART_MM0 (DEBUG_UART_BASE ) &= ~ERTO_MASK ;
254-
255- /* disable fractional baud-rate */
256- MMUART_MM0 (DEBUG_UART_BASE ) &= ~EFBR_MASK ;
257-
258- /* disable single wire mode */
259- MMUART_MM2 (DEBUG_UART_BASE ) &= ~ESWM_MASK ;
260-
261- /* set filter to minimum value */
206+ /* Clear timing registers */
262207 MMUART_GFR (DEBUG_UART_BASE ) = 0u ;
263-
264- /* set default TX time guard */
265208 MMUART_TTG (DEBUG_UART_BASE ) = 0u ;
266-
267- /* set default RX timeout */
268209 MMUART_RTO (DEBUG_UART_BASE ) = 0u ;
269210
270- /*
271- * Configure baud rate divisors. This uses the fractional baud rate divisor
272- * where possible to provide the most accurate baud rat possible.
273- */
274- config_baud_divisors (baud_rate );
275-
276- /* set the line control register (bit length, stop bits, parity) */
277- MMUART_LCR (DEBUG_UART_BASE ) = line_config ;
211+ /* Configure baud rate (115200) */
212+ uart_config_clk (115200 );
278213
214+ /* Set line config: 8N1 */
215+ MMUART_LCR (DEBUG_UART_BASE ) = MSS_UART_DATA_8_BITS |
216+ MSS_UART_NO_PARITY |
217+ MSS_UART_ONE_STOP_BIT ;
279218}
280219
281220void uart_write (const char * buf , unsigned int sz )
0 commit comments