Page 1 of 1

Raspberry pi 4 UART not working

Posted: Sun May 09, 2021 5:39 am
by 432
Hello,
I'm trying to set up UART on my Raspberry Pi 4 and it isn't working. I'm sure that usb-uart converter isn't a problem as it supports 3.3V. According to documentation GPIO base address is 0x7E20 5000 but that is not true, it's 0x7E20 0000.
I used ```echo < /dev/ttyUSB0``` to read data.

Code:

Code: Select all

.global uart_prepare
.global uart_write

.section .text

	// UART0   0x7E201000
	// UART1   0x7E201200  mini UART
	// UART2   0x7E201400
	// UART3   0x7E201600
	// UART4   0x7E201800
	// UART5   0x&E201A00

	// DR      0x00     0x7E201000
	// RSRECR  0x04
	// FR      0x18
	// ILPR    0x20     NOT IN USE
	// IBRD    0x24
	// FBRD    0x28
	// LCRH    0x2C
	// CR      0x30
	// IFLS    0x34
	// IMSC    0x38
	// RIS     0x3C
	// MIS     0x40
	// ICR     0x44
	// DMACR   0x48
	// ITCR    0x80
	// ITIP    0x84
	// ITOP    0x88
	// TDR     0x8C



uart_prepare:
	// LCRH Register
	// RRRRRRRR RRRRRRRR RRRRRRRR RRRRRRRR
	// RRRRRRRR RRRRRRRR RRRRRRRR SWWFSEPB
	// 31:8 Reserved
	// 7 SPS stick parity select
	// 6:5 WLEN Word length
	// 4 FEN Fifos enable
	// 3 STP2 Two stop bits select
	// 2 EPS Even parity select
	// 1 PEN Parity enable
	// 0 BRK Break

	mov x0, 0x7E20          // we are using UART2
	lsl x0, x0, #16
	mov x1, 0x1400
	add x0, x0, x1

	mov w1, 0b01110000      // set options; see above
	str w1, [x0, 0x2C]      // write options to LCRH

	// IFLS Register
	// 31:12 Reserved
	// 11:6 Unsupported
	// 5:3 RXIFLSEL
	// 2:0 TXIFLSEL

	mov w1, 0b100000 // interrupt when retrieve fifo is 7/8 full
			   // and when transmit fifo is 1/8 full
	str w1, [x0, 0x34] // write to IFLS

	

	// IBRD Register
	// 31:16 Reserved
	// 15:0 IBRD

	mov w1, #4         // 9600 baud
	str w1, [x0, 0x24]

	// FBRD Register
	// 31:6 Reserved
	// 5:0 FBRD

	mov w1, #0
	//lsl w1, w1, #12
	str w1, [x0, 0x28]

	// IMSC Register
	// 10 OEIM
	// 9 BEIM
	// 8 PEIM
	// 7 FEIM
	// 6 RTIM
	// 5 TXIM     must set
	// 4 RXIM     must set
	// 3 DSRMIM   unsupported
	// 2 DCDMIM   unsupported
	// 1 CTSMIM
	// 0 RIMIM    unsupported

	mov w1, 0b11111110010    // enable all possible interrupts
	str w1, [x0, 0x38]

	// Base address of GPIO register is 0x7E21 5000; no it's 0x7E20 0000

	mov	x1, 0x7E20          //7e21 we set x1 to GPIO base address
	lsl	x1, x1, #16
	//mov x2, 0x5000
	//add x1, x1, x2
	mov	w2, 0b011011     // This makes GPIO 0:1 uart pins
	str	w2, [x1, 0x0]

	// Choose pull down resistors for GPIO 0:1
	ldr	w2, [x1, 0xE4]       // read register
	and	w2, w2, 0xfffffff0   // clear GPIO 0:1
	add	w2, w2, 0b1010       // set GPIO 0:1
	str	w2, [x1, 0xE4]

	// CR Register
	// 32:16 Reserved
	// 15 CTSEN
	// 14 RTSEN
	// 13 OUT2
	// 12 OUT1
	// 11 RTS          unsupported
	// 10 DTR          unsupported
	// 9 RXE
	// 8 TXE
	// 7 LBE
	// 6:3 Reserved
	// 2 SIRLP         unsupported
	// 1 SIREN         unsupported
	// 0 UARTEN

	mov w1, 0b110000001  // enable uart; both receive and transmit
	str w1, [x0, 0x30]  // write options to CR, uart is enabled

	ret

uart_write:
	// x0 points to string we want to write

	//ldrb w1, [x0], #1     // read char and move pointer by one byte
	//cmp w1, 0x0
	//bne uart_write
	//ret

	mov x0, 0x7E20
	lsl x0, x0, #16
	mov x1, 0x14
	lsl x1, x1, #8
	add x0, x0, x1
	mov w1, #57    // this is '9'
	strb w1, [x0, 0x0]

Re: Raspberry pi 4 UART not working

Posted: Mon May 10, 2021 6:10 am
by bzt
432 wrote:According to documentation GPIO base address is 0x7E20 5000 but that is not true, it's 0x7E20 0000.
Neither. Addresses starting with 0x7E... are VC addresses, not ARM addresses (the same memory is visible for both the GPU and the CPU, but at different address). The MMIO base address for the RPi4 CPU is 0xFE000000, so UART0 registers start at 0xFE201000, and UART1 registers start at 0xFE215000. The Linux kernel maps the MMIO at 0x7E000000, that's why you can see this address in the docs, but don't let that fool you.

Furthermore, as far as I know there's only UART0 (an PL011 chip) and a UART1 (an AUX mini uart chip) on board, no more. Other uarts need expansion shields if I'm correct, so changes are high UART2 won't work for you anyway.

Another thing, you can't set the baud divisor without knowing the actual frequency. You should set the UART clock first with a mailbox call (to 4Mhz for example), then you can set the divisor reliably (4Mhz/divisor=115200 for example).
432 wrote:I used ```echo < /dev/ttyUSB0``` to read data.
That's not enough. You need to use certain termios libc calls to get serial port working (try setserial command apriori). But I'd recommend to use minicom instead, which also supports two-way communication (or you could use PuTTY as well).

Cheers,
bzt

Re: Raspberry pi 4 UART not working

Posted: Mon May 10, 2021 12:46 pm
by 432
I updated my code and I'm going to give minicom a try. How do I communicate with VC to set clock frequency? I don't understand this part in RPi barebone. Does it impact one UART or all of them? Any resources? Thank you.

Re: Raspberry pi 4 UART not working

Posted: Mon May 10, 2021 6:16 pm
by bzt
432 wrote:I updated my code and I'm going to give minicom a try. How do I communicate with VC to set clock frequency? I don't understand this part in RPi barebone.
You create an aligned array of integers, put some magic numbers in it, tell the VC where the array is and wait for the response.

For an example, see here.
line 49: read the MBOX_STATUS register (MMIO_BASE + 0xB898) until bit 31 is clear (in other words, wait until it's ready to receive)
line 51: write the array's address to MBOX_WRITE (MMIO_BASE + 0xB8A0), with the lower tetrad being 8 (that selects the property channel)
line 55: in a loop, wait for a response by reading MBOX_STATUS until bit 30 is set (in other words, wait until a response is entirely written into memory).
line 57: if you can now read your array's address from the MBOX_READ register, then the response was made for your request (multiple core might use the mailbox interface simultaneously, so you must check). If not, then repeat the loop.
line 59: if the response was for you, and your array's second element's bit 31 is set, then the request was successfully fulfilled, and your array contains the response (if this bit is clear, that means there was an error).

As you can see, it is pretty simple at its core, the only complication is using spinloops before writing or reading the register, and checking if it's indeed your response, because the interface might be used by multiple cores at once.
432 wrote:Does it impact one UART or all of them?
You can set only one device's freq with one tag, but you can place multiple tags in the array.
432 wrote:Any resources? Thank you.
The spec for the array is here.
An example on how to set the UART freq can be found here.
An example mailbox call in Assembly (fasm dialect) can be found here (it sets the framebuffer, but setting the UART goes the same, you just put different values in the array).

Cheers,
bzt

Re: Raspberry pi 4 UART not working

Posted: Thu May 13, 2021 9:24 am
by 432
Yes, it's quite simple. I started to understand it. I just need to know how do I align messages. Register is 32 bit wide and channel is 4 bit wide. This leaves 28 bits to encode address. Should I fill missing bytes with zeroes?