Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Raspberry Pi3 Uart #496

Merged
merged 2 commits into from
Sep 2, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions config/examples/raspi3.config
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ SPMATH?=1
IMAGE_HEADER_SIZE?=1024
PKA?=1
WOLFTPM?=0
DEBUG_UART?=0
WOLFBOOT_SECTOR_SIZE=0x400
WOLFBOOT_NO_PARTITIONS=1
WOLFBOOT_LOAD_ADDRESS?=0x3080000
Expand Down
60 changes: 58 additions & 2 deletions docs/Targets.md
Original file line number Diff line number Diff line change
Expand Up @@ -1089,7 +1089,7 @@ git clone https://github.com/raspberrypi/linux linux-rpi -b rpi-4.19.y --depth=1
export wolfboot_dir=`pwd`
cd linux-rpi
patch -p1 < $wolfboot_dir/tools/wolfboot-rpi-devicetree.diff
make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- bcmrpi3_defconfig
make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- bcm2711_defconfig
make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu-
```

Expand Down Expand Up @@ -1126,10 +1126,66 @@ dd if=bcm2710-rpi-3-b.dtb of=wolfboot_linux_raspi.bin bs=1 seek=128K conv=notrun

* Test boot using qemu

Download [root file system image(2020-02-13-raspbian-buster-lite.zip)](https://ftp.jaist.ac.jp/pub/raspberrypi/raspbian_lite/images/raspbian_lite-2020-02-14/2020-02-13-raspbian-buster-lite.zip)
```
qemu-system-aarch64 -M raspi3b -m 1024 -serial stdio -kernel wolfboot_linux_raspi.bin -cpu cortex-a53
qemu-system-aarch64 -M raspi3b -m 1024 -serial stdio -kernel wolfboot_linux_raspi.bin -cpu cortex-a53 -drive file=../wolfboot/2020-02-13-raspbian-buster-lite.img,if=sd,format=raw
```

### Testing on [Raspberry PI 3 B Plus](https://www.raspberrypi.com/products/raspberry-pi-3-model-b-plus/)

* Copy dtb file for Raspberry PI 3 B Plus to the wolfboot directory

```
cp /path/to/raspberry-pi-linux/arch/arm64/boot/dts/broadcom/bcm2710-rpi-3-b-plus.dtb $wolfboot_dir
cd $wolfboot_dir
```

* Compose the image
```
dd if=bcm2710-rpi-3-b-plus.dtb of=wolfboot_linux_raspi.bin bs=1 seek=128K conv=notrunc
```

* Copy the kernel image to boot partition of boot media. e.g. SD card

Raspberry Pi loads `kernel8.img` when it is in `AArch64` mode. Therefore, the kernel image is copied to boot partition as `kernel8.img` file name.
```
cp wolfboot_linux_raspi.bin /media/foo/boot/kernel8.img
```

* Troubleshooting

o Turn on UART for debugging to know what boot-process is going on. Chaning DEBUG_UART property in .config to 1.
```
DEBUG_UART?=1
```
UART properties set as 115200 bps, 8bit data transmission, 1 stop bit and no parity.

You would see the following message when wolfboot starts.
```
My board version is: 0xA020D3
Trying partition 0 at 0x140000
Boot partition: 0x140000 (size 14901760, version 0x1)
....
````
Note: Now, integrity-check takes 2 - 3 minutes to complete before running Linux kernel.

o Kernel panic after wolfboot message
Mount position of root file system could be wrong. Checking your boot media by `lsblk` command.
```
$ lsblk
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
mmcblk0 179:0 0 29.7G 0 disk
├─mmcblk0p1 179:1 0 63M 0 part
├─mmcblk0p2 179:2 0 1K 0 part
├─mmcblk0p5 179:5 0 32M 0 part
├─mmcblk0p6 179:6 0 66M 0 part /boot
└─mmcblk0p7 179:7 0 29.6G 0 part /
```

It need to modify dtb file accordingly. Go to /path/to/raspberry-pi-linux/arch/arm/boot/dts/bcm2710-rpi-3-b-plus.dts. Change `root=/dev/mmcblk0p7` of the following line in the file to your root file system device.
```
bootargs = "coherent_pool=1M 8250.nr_uarts=1 console=ttyAMA0,115200 console=tty1 root=/dev/mmcblk0p7 rootfstype=ext4 elevator=deadline fsck.repair=yes rootwait splash plymouth.ignore-serial-consoles";
```

### Testing with kernel encryption

Expand Down
258 changes: 255 additions & 3 deletions hal/raspi3.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,23 +18,209 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
*/

#include <stddef.h>
#include <stdint.h>
#include <string.h>
#include <target.h>
#include "image.h"
#include "printf.h"
#ifndef ARCH_AARCH64
# error "wolfBoot raspi3 HAL: wrong architecture selected. Please compile with ARCH=AARCH64."
#endif

#define TEST_ENCRYPT

#if defined(DEBUG_UART)
#define PRINTF_ENABLED
#endif


#define CORTEXA53_0_CPU_CLK_FREQ_HZ 1099989014
#define CORTEXA53_0_TIMESTAMP_CLK_FREQ 99998999

#define MMIO_BASE 0x3F000000

#define GPIO_BASE MMIO_BASE + 0x200000

#define GPFSEL1 ((volatile unsigned int*)(GPIO_BASE+0x04))
#define GPPUD ((volatile unsigned int*)(GPIO_BASE+0x94))
#define GPPUDCLK0 ((volatile unsigned int*)(GPIO_BASE+0x98))

/* PL011 UART registers */
#define UART0_BASE GPIO_BASE + 0x1000
#define UART0_DR ((volatile unsigned int*)(UART0_BASE+0x00))
#define UART0_FR ((volatile unsigned int*)(UART0_BASE+0x18))
#define UART0_IBRD ((volatile unsigned int*)(UART0_BASE+0x24))
#define UART0_FBRD ((volatile unsigned int*)(UART0_BASE+0x28))
#define UART0_LCRH ((volatile unsigned int*)(UART0_BASE+0x2C))
#define UART0_CR ((volatile unsigned int*)(UART0_BASE+0x30))
#define UART0_IMSC ((volatile unsigned int*)(UART0_BASE+0x38))
#define UART0_ICR ((volatile unsigned int*)(UART0_BASE+0x44))

/* mail box message buffer */
volatile unsigned int __attribute__((aligned(16))) mbox[36];

#define VIDEOCORE_MBOX (MMIO_BASE+0x0000B880)
#define MBOX_READ ((volatile unsigned int*)(VIDEOCORE_MBOX+0x0))
#define MBOX_POLL ((volatile unsigned int*)(VIDEOCORE_MBOX+0x10))
#define MBOX_SENDER ((volatile unsigned int*)(VIDEOCORE_MBOX+0x14))
#define MBOX_STATUS ((volatile unsigned int*)(VIDEOCORE_MBOX+0x18))
#define MBOX_CONFIG ((volatile unsigned int*)(VIDEOCORE_MBOX+0x1C))
#define MBOX_WRITE ((volatile unsigned int*)(VIDEOCORE_MBOX+0x20))
#define MBOX_RESPONSE 0x80000000
#define MBOX_FULL 0x80000000
#define MBOX_EMPTY 0x40000000

#define MBOX_REQUEST 0

/* channels */
#define MBOX_CH_POWER 0
#define MBOX_CH_FB 1
#define MBOX_CH_VUART 2
#define MBOX_CH_VCHIQ 3
#define MBOX_CH_LEDS 4
#define MBOX_CH_BTNS 5
#define MBOX_CH_TOUCH 6
#define MBOX_CH_COUNT 7
#define MBOX_CH_PROP 8

/* tags */
#define MBOX_TAG_GETBRDVERSION 0x10002
#define MBOX_TAG_GETSERIAL 0x10004
#define MBOX_TAG_GET_CLOCK_RATE 0x30002
#define MBOX_TAG_SETCLKRATE 0x38002
#define MBOX_TAG_LAST 0

/* Fixed addresses */
extern void *kernel_addr, *update_addr, *dts_addr;
/* Loop <delay> times */
static inline void delay(int32_t count)
{
register unsigned int c;
c = count;
while (c--) {
asm volatile("nop");
}
}
/**
* write message to mailbox
*/
static void mailbox_write(uint8_t chan)
{
uint32_t ch = (((uint32_t)((unsigned long)&mbox) & ~0xf)
| (chan & 0xf));

/* wait until mail box becomes ready to write */
while ((*MBOX_STATUS & MBOX_FULL) != 0) { }

/* write the address of the message to mail-box channel */
*MBOX_WRITE = ch;
}
/**
* read message from mailbox
*/
static int mailbox_read(uint8_t chan)
{
uint32_t ch = (((uint32_t)((unsigned long)&mbox) & ~0xf)
| (chan & 0xf));
/* now wait for the response */
while(1) {
while ((*MBOX_STATUS & MBOX_EMPTY) != 0) { }
if(ch == *MBOX_READ)
/* is it a valid successful response */
return mbox[1] == MBOX_RESPONSE;
}
return 0;
}

/* UART functions for Raspberry Pi 3 UART */
void uart_tx(char c)
{
/* wait until uart channel is ready to send */
do{
asm volatile("nop");
} while(*UART0_FR & 0x20);
*UART0_DR = c;
}

char uart_read(void)
{
char c;
/* wait until data is comming */
do{
asm volatile("nop");
} while(*UART0_FR & 0x10);
/* read it and return */
c = (char)(*UART0_DR);
/* convert carrige return to newline */
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

spelling: carriage. Is this conversion really required?

if (c == '\r')
c = '\n';

return c;
}

/**
* Send string to UART
*/
void uart_write(const char* buf, uint32_t sz) {
uint32_t len = sz;

while (len > 0 && *buf) {
/* convert newline to carrige return + newline */
Copy link
Member

@danielinux danielinux Aug 26, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

spelling, plus conversion from CR to CR+LF, that should be handled by the caller, or left as is.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks. Agree. Carriage return code should be handled by the caller.

if (*buf == '\n')
uart_tx('\r');

uart_tx(*buf++);
len--;
}
}

void uart_init()
{
register unsigned int c;

/* initialize UART. turn off UART 0*/
*UART0_CR = 0;

/* set up clock for consistent divisor values */
mbox[0] = 9 * 4;
mbox[1] = MBOX_REQUEST;
/* tag for setting clock rate */
mbox[2] = MBOX_TAG_SETCLKRATE;
mbox[3] = 12;
mbox[4] = 8;
/* specify UART clock channel */
mbox[5] = 2;
/* UART clock rate in hz(4Mhz)*/
mbox[6] = 4000000;
/* not use turbo */
mbox[7] = 0;
mbox[8] = MBOX_TAG_LAST;

mailbox_write(MBOX_CH_PROP);
mailbox_read(MBOX_CH_PROP);

/* disable pull up/down for all GPIO pins */
*GPPUD = 0;
delay(150);
/* Disable pull up/down for pin 14 and 15 */
*GPPUDCLK0 = (1<<14)|(1<<15);
delay(150);
/* flush GPIO setting to make it take effect */
*GPPUDCLK0 = 0;

/* clear pending interrupts */
*UART0_ICR = 0x7FF;
/* select 115200 baud rate */
/* divider = 4000000 / (16 * 115200) = 2.17 = ~2 */
*UART0_IBRD = 2;
/* Fractional part register = (.17013 * 64) + 0.5 = 11.38 = ~11 */
*UART0_FBRD = 0xB;
/* Enable fifo, 8bit data transmission ( 1stop bit, no parity) */
*UART0_LCRH = (1 << 4) | (1 << 5) | (1 << 6);
/* enable UART0 transfer & receive*/
*UART0_CR = (1 << 0) | (1 << 8) | (1 << 9);
}

void* hal_get_primary_address(void)
{
Expand Down Expand Up @@ -91,22 +277,88 @@ void qspi_init(uint32_t cpu_clock, uint32_t flash_freq)
{
}


void zynq_init(uint32_t cpu_clock)
{
}

#if defined(DISPLAY_CLOCKS)
static uint32_t getclocks(uint8_t cid)
{
/* Retrive clock rate */
/* length of the message */
mbox[0] = 8 * 4;
mbox[1] = MBOX_REQUEST;
/* tag for get board version */
mbox[2] = MBOX_TAG_GET_CLOCK_RATE;
/* buffer size */
mbox[3] = 8;
mbox[4] = 8;
/* clock id CORE*/
mbox[5] = cid;
/* clock frequency */
mbox[6] = 0;
mbox[7] = MBOX_TAG_LAST;
mailbox_write(MBOX_CH_PROP);

if (mailbox_read(MBOX_CH_PROP)) {
return mbox[6];
}
else {
return 0;
}
}
#endif /* DISPLAY clocks */

/* public HAL functions */
void hal_init(void)
{
#if defined(TEST_ENCRYPT) && defined (EXT_ENCRYPTED)
char enc_key[] = "0123456789abcdef0123456789abcdef"
"0123456789abcdef";
"0123456789abcdef";
wolfBoot_set_encrypt_key((uint8_t *)enc_key,(uint8_t *)(enc_key + 32));
#endif

uart_init();

/* length of the message */
mbox[0] = 7 * 4;
mbox[1] = MBOX_REQUEST;
/* tag for get board version */
mbox[2] = MBOX_TAG_GETBRDVERSION;
/* buffer size */
mbox[3] = 4;
mbox[4] = 0;
mbox[5] = 0;
mbox[6] = MBOX_TAG_LAST;

/* send the message to the GPU */
mailbox_write(MBOX_CH_PROP);

if (mailbox_read(MBOX_CH_PROP)) {
wolfBoot_printf("My board version is: 0x%08x", mbox[5]);
wolfBoot_printf("\n");
} else {
wolfBoot_printf("Unable to query board version!\n");
}

#if defined(DISPLAY_CLOCKS) && defined(PRINTF_ENABLED)
/* Get clocks */
wolfBoot_printf("\n EMMC clock : %d Hz", getclocks(1));
wolfBoot_printf("\n UART clock : %d Hz", getclocks(2));
wolfBoot_printf("\n ARM clock : %d Hz", getclocks(3));
wolfBoot_printf("\n CORE clock : %d Hz", getclocks(4));
wolfBoot_printf("\n V3D clock : %d Hz", getclocks(5));
wolfBoot_printf("\n H264 clock : %d Hz", getclocks(6));
wolfBoot_printf("\n ISP clock : %d Hz", getclocks(7));
wolfBoot_printf("\n SDRAM clock : %d Hz", getclocks(8));
wolfBoot_printf("\n PIXEL clock : %d Hz", getclocks(9));
wolfBoot_printf("\n PWM clock : %d Hz", getclocks(10));
wolfBoot_printf("\n HEVC clock : %d Hz", getclocks(11));
wolfBoot_printf("\n EMMC2 clock : %d Hz", getclocks(12));
wolfBoot_printf("\n M2MC clock : %d Hz", getclocks(13));
wolfBoot_printf("\n PIXEL_BVB clock : %d Hz\n", getclocks(14));
#endif

}

void hal_prepare_boot(void)
Expand Down
2 changes: 1 addition & 1 deletion hal/raspi3.ld
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
MEMORY
{
DDR_MEM(rwx): ORIGIN = 0x00080000, LENGTH = 0x80000000
DDR_MEM(rwx): ORIGIN = 0x00080000, LENGTH = 0x3c000000
}
ENTRY(_vector_table);

Expand Down
Loading
Loading