shallada
Posts: 10
Joined: Sun Aug 18, 2013 8:42 pm

RPI2 UART example

Mon Oct 26, 2015 11:32 pm

I am looking for some example code (either ASM or C) for outputting characters on the UART for the RPI2. I have code for the Pi1 that uses the UART. I realize the peripherals base address has moved on the RPI2. I tried changing the base address on my Pi1 code to the new address for the RPI2 and running it, but that does not seem to work. I am pretty sure I have the correct base address as I am able to build a blinking LED programming for the RPI2 using the new base address. I have spent a lot of time trying to find any other difference between the Pi1 and the RPI2, but have not found anything. I am out of ideas, so I am looking for some example code that I can follow along and get working.

User avatar
DougieLawson
Posts: 36130
Joined: Sun Jun 16, 2013 11:19 pm
Location: Basingstoke, UK
Contact: Website Twitter

Re: RPI2 UART example

Tue Oct 27, 2015 7:58 am

Post your code or a link to the code you're trying to update for your RPi2.
Note: Having anything humorous in your signature is completely banned on this forum. Wear a tin-foil hat and you'll get a ban.

Any DMs sent on Twitter will be answered next month.

This is a doctor free zone.

JacobL
Posts: 76
Joined: Sun Apr 15, 2012 2:23 pm

Re: RPI2 UART example

Tue Oct 27, 2015 8:31 pm

Some simple code for outputting a character on the UART, provided it is already initialised. As far as I remember, it gets initialised by the start blob.

This should output an "A" as far as I remember:

Code: Select all

#define PHYS_IO_BASE		0x3F000000
	UART_PHYS_BASE .req r11
	mov	UART_PHYS_BASE,#PHYS_IO_BASE
	orr	UART_PHYS_BASE,UART_PHYS_BASE,#0x00200000
	orr	UART_PHYS_BASE,UART_PHYS_BASE,#0x00001000

	mov	r12, #0x41
	strb	r12, [UART_PHYS_BASE, #0x00]

shallada
Posts: 10
Joined: Sun Aug 18, 2013 8:42 pm

Re: RPI2 UART example

Tue Oct 27, 2015 11:30 pm

Posting the code is not quite as simple as it seems. I am developing a simple assembler of my own and I am trying to test the assembler by writing output to the UART. So the code is not standard ARM assembler (but it's a close subset). This is actually an assignment for a class I will be teaching in a few weeks. I expect my undergrad students to be able to do this, so I need to make sure I can do it first:).
The code is below. It blinks the LED correctly, but I get no output from the UART. I have included the assembly machine hex encodings as comments to most of the code (I do not show the encodings for the section I am sure works).

;
; Blink the LED and output H's
;

ADDRESS: 0x0100 ;Sets the current target address for the code generation
BLOCK 0x100 ;Allocates a block of 0x100 bytes for the stack
STACK: ;Creates a label for the stack (which grows down)

DELAY: ; Subroutine for creating a delay (known to work)
PUSH R0
LDR R0, R13, 4
delayloop:
SUBS R0, R0, 1
BNE delayloop
POP R0
MOVR R15, R14

TURN_ON: ;Subroutine to turn on the LED (known to work)
PUSH R1
PUSH R2
MOV R1, 0x8000
ADD R2, R0, 0x20
STR R1, R2, 0
POP R2
POP R1
MOVR R15, R14

TURN_OFF: ;Subroutine to turn off the LED (known to work)
PUSH R1
PUSH R2
MOV R1, 0x8000
ADD R2, R0, 0x2C
STR R1, R2, 0
POP R2
POP R1
MOVR R15, R14

ADDRESS: 0x0000 ;Reset the target address back to the beginning



;Initialize the stack
MOVW R13, STACK ;E3 00 D2 00

;Set pin 47 to output mode for the LED
;NOTE: R0 acts as a global value that holds the peripherals base address
MOVW R0, 0 ;E3 00 00 00
MOVT R0, 0x3F20 ;E3 43 0F 20
ADD R1, R0, 0x10 ;E2 80 10 10
LDR R2, R1, 0 ;E5 91 20 00
OR R2, R2, 0x200000 ;E3 82 26 02
STR R2, R1, 0 ;E5 81 20 00

;Set up the UART
ADD R1, R0, 0x1000 ;E2 80 1A 01
MOVW R2, 0 ;E3 00 20 00
STR R2, R1, 0x0030 ;E5 81 20 30
STR R2, R0, 0x0094 ;E5 80 20 94

MOVW R3, 0x00 ;E3 00 30 00
MOVT R3, 0x020 ;E3 40 30 20
PUSH R3 ;E5 2D 30 04
BL DELAY ;EB 00 01 F0
ADD R13, R13, 4 ;E2 8D D0 04

MOVW R2, 0x0C000 ;E3 0C 20 00
STR R2, R0, 0x0098 ;E5 80 20 98

MOVW R3, 0x00 ;E3 00 30 00
MOVT R3, 0x020 ;E3 40 30 20
PUSH R3 ;E5 2D 30 04
BL DELAY ;EB 00 01 E9
ADD R13, R13, 4 ;E2 8D D0 04

MOVW R2, 0 ;E3 00 20 00
STR R2, R0, 0x0098 ;E5 80 20 98
MOVW R2, 0x07FF ;E3 00 27 FF
STR R2, R1, 0x44 ;E5 81 20 44

MOVW R2, 1 ;E3 00 20 01
STR R2, R1, 0x24 ;E5 81 20 24
MOVW R2, 40 ;E3 00 20 28
STR R2, R1, 0x28 ;E5 81 20 28
MOVW R2, 0x70 ;E3 00 20 70
STR R2, R1, 0x2C ;E5 81 20 2C
MOVW R2, 0x7F2 ;E3 00 27 F2
STR R2, R1, 0x038 ;E5 81 20 38
MOVW R2, 0x0301 ;E3 00 23 01
STR R2, R1, 0x030 ;E5 81 20 30
; End UART init



;Loop forever…
loop:

; Turn on the LED
BL TURN_ON ;EB 00 01 DF

; Output an 'H'
MOVW R2, 0x48 ;E3 00 20 48
STR R2, R1, 0 ;E5 81 20 00

; Wait for a while
MOVW R3, 0x00 ;E3 00 30 00
MOVT R3, 0x020 ;E3 40 30 20
PUSH R3 ;E5 2D 30 04
BL DELAY ;EB 00 01 D3
ADD R13, R13, 4 ;E2 8D D0 04

; Turn off the LED
BL TURN_OFF ;EB 00 01 DF

; Output a space
MOVW R2, 0x20 ;E3 00 20 20
STR R2, R1, 0 ;E5 81 20 00

; Wait for a while
MOVW R3, 0x00 ;E3 00 30 00
MOVT R3, 0x010 ;E3 40 30 10
PUSH R3 ;E5 2D 30 04
BL DELAY ;EB 00 01 CB
ADD R13, R13, 4 ;E2 8D D0 04

BAL loop ;EA FF FF EE

shallada
Posts: 10
Joined: Sun Aug 18, 2013 8:42 pm

Re: RPI2 UART example

Wed Oct 28, 2015 12:50 am

I figured this out. I didn't have my terminal emulator configured correctly.
My deepest apologies for wasting anyone's time with this issue.

shallada
Posts: 10
Joined: Sun Aug 18, 2013 8:42 pm

Re: RPI2 UART example

Wed Oct 28, 2015 3:15 pm

Also, in case anybody cares, the previously posted code works. This code blinks the LED and outputs the letter 'H' followed by a space, infinitely. While the assembly is not standard, the encodings should help make it clear what the instructions actually are.
It turns out that the UART does actually work just as it did in the previous versions of the Pi, except that the peripherals base-address has changed as noted in the code.

shallada
Posts: 10
Joined: Sun Aug 18, 2013 8:42 pm

Re: RPI2 UART example

Tue Nov 03, 2015 1:45 am

I took the above code and made the modifications to try to run this code using the kernel_old=1 line in config.txt. This works fine on the older Pi's, but on the RPi2, I am having a strange problem. Instead of getting a single character, I get multiple characters each time I try and write to the UART. After spending many hours on this, I was able to eliminate any differences between my code when it is loaded at 0x8000 and 0x0000, so that the memory image is identical in both cases. So it has to be that something else is different between how the GPU configures the Pi before the GPU turns over to kernel7.img. Then I realized the the multiple characters I was seeing coming from the UART was always 4. It finally occurred to me that each of the 4 cores is probably writing to the UART.
Does anybody know if the kernel_old=1 causes all 4 cores to run, whereas without kernel_old=1 only one core runs?
Second, is there any simple code example that would disable three of the cores? I have looked into trying to use LDREX/STREX, but it looks like I may have to setup the MMU to get that to work and I am hoping to avoid that complexity at this time.

JacobL
Posts: 76
Joined: Sun Apr 15, 2012 2:23 pm

Re: RPI2 UART example

Tue Nov 03, 2015 6:30 am

I had the same issue. See viewtopic.php?f=72&t=122938

Return to “Bare metal, Assembly language”