polarfire-soc / polarfire-soc-bare-metal-examples

Bare metal example software projects for PolarFire SoC
25 stars 14 forks source link

Cannot access seventh bit of LCR (DLAB) #13

Closed rejsys closed 1 year ago

rejsys commented 1 year ago

https://github.com/polarfire-soc/polarfire-soc-bare-metal-examples/blob/92a7fcdcfc7fa7899562590452b3459a572802f9/driver-examples/mss/mss-mmuart/mpfs-mmuart-interrupt/src/platform/drivers/mss/mss_mmuart/mss_uart.c#L1539

I have two Polarfire boards and on both of them the seventh bit of LCR ("DLAB" divisor latch of UART) cannot be accessed or edited. Is this a known issue or do I need to consider something specific if I want to write this bit?

hughbreslin commented 1 year ago

Hey @rejsys what do you mean "cannot be accessed or edited" as in its read only?

When I set a breakpoint on the line of code setting this bit I can see:

before write: image

after write: image

And you can see the bit being set.

rejsys commented 1 year ago

I just found out, that its the writing of the baudrate which does not work for me. If I do not use the divisor latch I write the baudrate wrong and it works fine but as soon as I enable the DLAB, the writing of the baudrate fails. Do I need to enable the fractional baud rate if my baudrate is above 1u ? Can this cause an exception?

hughbreslin commented 1 year ago

Are you using our driver? You should just be able to pass the required baud rate in the init call, for example:

MSS_UART_init( g_uart, MSS_UART_115200_BAUD, MSS_UART_DATA_8_BITS | MSS_UART_NO_PARITY | MSS_UART_ONE_STOP_BIT);

And the supported baud rates are shown here

It doesn't seem like you're using the provided calls to initialize the uart? In the driver it is enabling the fractional baud rate divisors if the baud rate is > 1 and there is an assert if the fractional baud rate is >= 255, shown in this block, otherwise the fractional baud rate divisors are disabled, this block.

Some notes on the use of the DLAB bit from the register map which may be useful:

Notes:

To access DLR register (offset 0x00) - first set DLAB(bit7) of LCR register.

To access DMR register (offset 0x04) - first set DLAB(bit7) of LCR register.

THR register (offset 0x00) is a write only register.

  • write 0 to DLAB(bit7) of LCR register. it is 0 on reset.

  • then do write transaction to offset 0x00

RBR register (offset 0x00) is a read only register

  • write 0 to DLAB(bit7) of LCR register. it is 0 on reset.

  • then do read transaction to offset 0x00

Therefore when DLAB bit in LCR is 0. write transaction to offset 0x00 goes to THR register and read transaction to offset 0x00 reads from RBR.

FCR register (offset 0x08) is write only. Therefore write transaction to 0x08 goes to this register irrespective of the value in DLAB bit in LCR.

IR register (offset 0x08) is read only. Therefore a read transaction to 0x08 fetches data from this register irrespective of the value in DLAB bit in LCR.

What do you mean by "writing of the baud rate fails"?

rejsys commented 1 year ago

thank you for the help! I solved my problem. I used the wrong register offset for the fractional baud rate.