Skip to content

Commit c0b60f4

Browse files
committed
Improvements to startup and UART driver
1 parent b6be03b commit c0b60f4

File tree

5 files changed

+150
-161
lines changed

5 files changed

+150
-161
lines changed

hal/mpfs250.c

Lines changed: 60 additions & 121 deletions
Original file line numberDiff line numberDiff line change
@@ -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

200179
void 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

281220
void uart_write(const char* buf, unsigned int sz)

hal/mpfs250.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -48,11 +48,11 @@
4848
#define CSR_MIMPID 0xf13
4949
#define CSR_MHARTID 0xf14
5050

51-
/* default entry point */
51+
/* Initial stack pointer address (stack grows downward from here) */
5252
#ifdef WOLFBOOT_RISCV_SMODE
53-
#define SYS_INIT_SP_ADDR 0x80200000
53+
#define WOLFBOOT_STACK_TOP 0x80200000
5454
#else
55-
#define SYS_INIT_SP_ADDR 0x80000000
55+
#define WOLFBOOT_STACK_TOP 0x80000000
5656
#endif
5757

5858
#ifdef WOLFBOOT_RISCV_SMODE

src/boot_riscv64.c

Lines changed: 5 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -42,36 +42,25 @@ extern uint64_t _end_bss;
4242
extern uint64_t _end_stack;
4343
extern uint64_t _start_heap;
4444
extern uint64_t _global_pointer;
45-
extern void (* const IV[])(void);
45+
extern void (* const trap_vector_table[])(void);
4646

47-
extern void main(void);
47+
/* reloc_trap_vector is implemented in boot_riscv64_start.S */
48+
extern void reloc_trap_vector(const uint32_t *address);
4849

4950
unsigned long handle_trap(unsigned long cause, unsigned long epc, unsigned long tval)
5051
{
5152
/* TODO: Implement trap handling */
5253
return epc;
5354
}
5455

55-
void trap_from_machine_mode(uintptr_t * regs, uintptr_t dummy, uintptr_t mepc)
56-
{
57-
/* TODO: Implement trap from machine mode */
58-
}
59-
60-
void RAMFUNCTION reloc_iv(const uint32_t *address)
61-
{
62-
/* Set machine trap vector to address */
63-
asm volatile("csrw mtvec, %0":: "r"(address + 1));
64-
}
65-
66-
6756
#ifdef MMU
6857
void do_boot(const uint32_t *app_offset, const uint32_t* dts_offset)
6958
#else
7059
void do_boot(const uint32_t *app_offset)
7160
#endif
7261
{
73-
/* Relocate interrupt vector to application */
74-
reloc_iv(app_offset);
62+
/* Relocate trap vector table to application */
63+
reloc_trap_vector(app_offset);
7564

7665
/* Jump to application entry point */
7766
asm volatile("jr %0":: "r"((uint8_t *)(app_offset)));

0 commit comments

Comments
 (0)