leiradel
Posts: 32
Joined: Wed Feb 13, 2019 10:38 pm

Mini UART eats some characters

Wed Feb 13, 2019 10:57 pm

Hello,

I'm studying bare metal programming in the RPi, and now I'm trying to upload code via the UART to avoid constantly removing and inserting the memory card in order to copy the program.

I've tested the Mini UART at 115200 transmitting from the RPi to Linux running minicom, and everything worked just fine. My test consisted in streaming the entire ASCII movie found here: http://www.asciimation.co.nz/index.php

I then wrote code to read ihex files from the UART, but it doesn't work and I can't for the life of me find the reason. At first I though it was the memory barriers that I was neglecting to add, but then I added them and the problem persisted. I increased to places where the memory barriers are executed up to around all peripheral reads and writes, but the exact same problem persisted.

Code: Select all

Welcome to minicom 2.7.1

OPTIONS: I18n 
Compiled on Aug 13 2017, 15:25:34.
Port /dev/ttyUSB0, 22:55:03

Press CTRL-A Z for help on special keys

Waiting for file
Read char 0
Read char 2
Read byte 02
Record has 02 bytes
Read char 0
Read char 0
Read byte 00
Read char 0
Read char 0
Read byte 00
Read word 0000
Offset is 0000
Read char 0
Read char 2
Read byte 02
Record type is 02
Reading data bytes
Read char 1
Read char 0
Read byte 10
Read char 2
Read char 0
Read byte 20
Read char E
Read char \x0a
Error, invalid hexa digit \x0a
Waiting for file
I took the UART code from https://github.com/dwelch67/raspberrypi ... loader07.c (thanks David) and still the problem persisted. I tried in both a RPi 1 B and a 3 B+ and the issue is the same.

My code is here in case anyone can take a look: https://github.com/leiradel/barebones-r ... arebones08

The kernel that sets up the environment is in the kernel folder. It doesn't free any secondary cores, for now only the primary core runs. It waits for something in the UART, then tries to decode an ihex file, but right at the beginning, in the first line, it seems to skip characters, which causes the kernel to abandon the download, go to the top of the loop, and wait for another file.

Maybe the ihex decoding has bugs but that's not my concern, I can iron them out once the UART is working.

Any help is appreciated. Maybe it's something obvious, maybe I just need to take a break and code something else for a while :)

leiradel
Posts: 32
Joined: Wed Feb 13, 2019 10:38 pm

Re: Mini UART eats some characters

Thu Feb 14, 2019 1:08 pm

I've rubber ducked the issue with a friend during lunch and I see that I'm missing characters because I'm writing characters to the UART in busy loops to log everything that is happening :oops:

I'll log the messages to a memory buffer and dump its contents to the UART after the IHEX is read, or maybe setup a framebuffer. This will likely allow me to find any issues in my IHEX parser.

Cheers!

LdB
Posts: 1280
Joined: Wed Dec 07, 2016 2:29 pm

Re: Mini UART eats some characters

Thu Feb 14, 2019 4:33 pm

If you turn the optimizer on I expect half your status code will probably optimize away.

Think very carefully about this code when probably inlined and optimized in the loop shown next.

Code: Select all

int uart_canwrite(void) {
  const uint32_t value = mem_read32(BASE_ADDR + AUX_MU_LSR_REG);
  return (value & 0x20) != 0;
}

Code: Select all

while (!uart_canwrite()) {
      // nothing
}
I think you are expecting it to loop reading the status but I am guessing it gets optimized away so I would do an assembler dump and check :-)

Let me offer you an alternative for the uart_canwrite function .. volatile unlike const does protect you from the optimizer.
When it now inlines the code it can see it can't optimize "value" away it is volatile.

Code: Select all

int uart_canwrite(void) {
  volatile uint32_t value = mem_read32(BASE_ADDR + AUX_MU_LSR_REG);
  return (value & 0x20) != 0;
}

leiradel
Posts: 32
Joined: Wed Feb 13, 2019 10:38 pm

Re: Mini UART eats some characters

Thu Feb 14, 2019 9:53 pm

So yeah, while trying to measure the system I've changed its state :oops:

I've added a framebuffer and was able to debug my IHEX parser until it worked. Well, kind of. I'm getting an undefined instruction exception trying to execute the downloaded file, but that's another issue.

leiradel
Posts: 32
Joined: Wed Feb 13, 2019 10:38 pm

Re: Mini UART eats some characters

Thu Feb 14, 2019 10:10 pm

LdB wrote:
Thu Feb 14, 2019 4:33 pm
Let me offer you an alternative for the uart_canwrite function .. volatile unlike const does protect you from the optimizer.
My understanding of volatile is that it makes the compiler read the value from memory every time it's needed, preventing it from being cached in a register, and this seems to be the case: https://godbolt.org/z/oLXIQ2

Quite surprising to me, the compiler even wrote the value to memory allocated on the stack just to make sure it was reading the value from memory instead of using it from the register :lol:

Also, my mem_read32 function is written in a volatile assembly statement, so I don't think the compiler could optimize it away. Regardless, it was a nice lead and I went to see the generated code just to make sure it was ok, so thanks for that. Now I have to remove the data memory barriers that I've put around all individual peripheral reads and writes, while debugging the UART issue.

Ah, thanks a lot for all the work you've done in baremetal programming for the Raspberry Pi. My first blog post after a long while was about SmartStart, I hope I got everything right! https://leiradel.github.io/2019/01/06/SmartStart.html

LdB
Posts: 1280
Joined: Wed Dec 07, 2016 2:29 pm

Re: Mini UART eats some characters

Fri Feb 15, 2019 7:28 am

The only part you got wrong was missing out the roll of the bootstubs

The initial parts of the GPU boot are correct but you miss that the ARM starts at 0x0 but the GPU positions a bootstub that runs on entry .. the bootstub code is open source and in the user library
https://github.com/raspberrypi/tools/tr ... r/armstubs

armstub.S is for BCM2835
armstub7.S is for BCM 2836 and BCM2837 in 32bit mode
armstub8.S is for BCM2837 in 64 bit mode.

Bin2c is the utility they use to convert the code to C for including into what I assume becomes the VC4 start ELF file.

It is that bootstub that places the CPU in the hypervisor mode and sets the entry address to 0x8000 for 32bit or 0x80000 for 64 bit and it is that code that parks core 1,2,3 on BCM2836, BCM2837 all cores initially start the same.

You state
I couldn’t find the hypervisor mode value in the documentation.

AFAIK, ARM CPUs are set to supervisor mode when powered on. SmartStart seems to believe that both A7 and A53 boot in hypervisor mode, but I couldn’t find any reference.
Look at the bootstub code it provides the documentation and especially on the A53 in 64bit mode the processor actually enters the bootstub in EL3 and it is the bootstub that drops it to EL2 and delivers it to you at 0x80000 in that mode (note it also does some EL3 register sets) :-)

dpotop
Posts: 78
Joined: Mon Nov 24, 2014 2:14 pm

Re: Mini UART eats some characters

Fri Feb 15, 2019 2:14 pm

This week I did (in some spare time) exactly this - writing a loader over UART.
I've had some issues with lost characters, too.

It seems they were timing-related. After removing all spurious code on the
RPi-side receiving code and adding a small consistency test in the writing
loop on the PC side (which adds a small delay), everything is working perfectly.
Since I'm talking timing, I must be precise. The RPi is a RPi3 (didn't test, yet,
on a RPi 1 and I have no plans to test on a RPi2) and the PC is a
Macbook (2.5GHz).

The difficult part was getting to the point where I could actually test this
easily. :)

If you still have problems, I can share my (working :D ) code with you.

Good luck,
Dpotop
dpotop

leiradel
Posts: 32
Joined: Wed Feb 13, 2019 10:38 pm

Re: Mini UART eats some characters

Fri Feb 15, 2019 3:55 pm

LdB wrote:
Fri Feb 15, 2019 7:28 am
The only part you got wrong was missing out the roll of the bootstubs
Isn't it described here?

Code: Select all

7. start.elf writes some ARM bootstrap code to RAM that will be executed before jumping to the kernel
8. start.elf loads kernel.img to address 0x8000 and releases the ARM CPU to execute the bootstrap code
My second baremetal post was about the stubs: https://leiradel.github.io/2019/01/20/R ... Stubs.html

leiradel
Posts: 32
Joined: Wed Feb 13, 2019 10:38 pm

Re: Mini UART eats some characters

Fri Feb 15, 2019 4:01 pm

dpotop wrote:
Fri Feb 15, 2019 2:14 pm
It seems they were timing-related.
Yes, I also had trouble with timing, first because I decided to printf-debug the issues by sending message over to the PC via the UART :oops:, and then because I started to log message to a framebuffer, but scrolling it was making the code lose some characters in the receive FIFO.

After removing must of the log messages I could iron out the bugs and now I'm able to receive the entire IHEX file in my RPi 1. Since I'm testing the checksum, I'm pretty confident this part is ok.
dpotop wrote:
Fri Feb 15, 2019 2:14 pm
If you still have problems, I can share my (working :D ) code with you.
Thank you very much, I'll see if I can make everything work this weekend, if not I'll ping you.

leiradel
Posts: 32
Joined: Wed Feb 13, 2019 10:38 pm

Re: Mini UART eats some characters

Sat Feb 16, 2019 8:31 pm

So I was jumping to the wrong address, now everything works: https://asciinema.org/a/TUy7twjQhlK1hsBnPWe2Xvldf

I was expecting to be more productive this way, but I think I was overestimating the upload speed via serial. I know the Mini UART can go up to megabouds, but minicom seems unable to handle anything above 115200?

Return to “Bare metal, Assembly language”