New tutorials
parent
a97bfecdd0
commit
823040a6bf
@ -0,0 +1,43 @@
|
|||||||
|
#
|
||||||
|
# Copyright (C) 2018 bzt (bztsrc@github)
|
||||||
|
#
|
||||||
|
# Permission is hereby granted, free of charge, to any person
|
||||||
|
# obtaining a copy of this software and associated documentation
|
||||||
|
# files (the "Software"), to deal in the Software without
|
||||||
|
# restriction, including without limitation the rights to use, copy,
|
||||||
|
# modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||||
|
# of the Software, and to permit persons to whom the Software is
|
||||||
|
# furnished to do so, subject to the following conditions:
|
||||||
|
#
|
||||||
|
# The above copyright notice and this permission notice shall be
|
||||||
|
# included in all copies or substantial portions of the Software.
|
||||||
|
#
|
||||||
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||||
|
# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||||
|
# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
|
# DEALINGS IN THE SOFTWARE.
|
||||||
|
#
|
||||||
|
#
|
||||||
|
|
||||||
|
SRCS = $(wildcard *.c)
|
||||||
|
OBJS = $(SRCS:.c=.o)
|
||||||
|
CFLAGS = -Wall -O2 -ffreestanding -nostdinc -nostdlib -nostartfiles
|
||||||
|
|
||||||
|
all: clean kernel8.img
|
||||||
|
|
||||||
|
start.o: start.S
|
||||||
|
aarch64-elf-gcc $(CFLAGS) -c start.S -o start.o
|
||||||
|
|
||||||
|
%.o: %.c
|
||||||
|
aarch64-elf-gcc $(CFLAGS) -c $< -o $@
|
||||||
|
|
||||||
|
kernel8.img: start.o $(OBJS)
|
||||||
|
aarch64-elf-ld -nostdlib -nostartfiles start.o $(OBJS) -T link.ld -o kernel8.elf
|
||||||
|
aarch64-elf-objcopy -O binary kernel8.elf kernel8.img
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm kernel8.elf *.o >/dev/null 2>/dev/null || true
|
@ -0,0 +1,43 @@
|
|||||||
|
Oktatóanyag 12 - Printf
|
||||||
|
=======================
|
||||||
|
|
||||||
|
Mielőtt kibővítenénk a kivételkezelőnket, szükségünk lesz néhány jól ismert C függvényre. Mivel alacsony szinten
|
||||||
|
programozunk, nem támaszkodhatunk a libc-re, ezért nekünk kell egy saját printf() implementációt megvalósítanunk.
|
||||||
|
|
||||||
|
```sh
|
||||||
|
$ qemu-system-aarch64 -M raspi3 -kernel kernel8.img -serial stdio
|
||||||
|
Hello World!
|
||||||
|
This is character 'A', a hex number: 7FFF and in decimal: 32767
|
||||||
|
Padding test: '00007FFF', ' -123'
|
||||||
|
```
|
||||||
|
|
||||||
|
Sprintf.h, sprintf.c
|
||||||
|
--------------------
|
||||||
|
|
||||||
|
Az érdekes rész. Nagyban ráhagyatkozunk a fordítónk beépített funkcióira, hogy a változó elemszámú paramétereket
|
||||||
|
lekezeljük. Amint ebben az oktatóanyag sorozatban megszokhattunk, nem a tökéletes kompatibilitásra, hanem a
|
||||||
|
szükséges minimum implementációra törekszünk. Ezért csak a '%s', '%c', '%d' és '%x' opciókat támogatjuk. Az
|
||||||
|
igazítás is limitált, csak jobbra lehet igazítani, hexa számokat nullákkal, decimálisakat szóközzel.
|
||||||
|
|
||||||
|
`sprintf(dst, fmt, ...)` ugyanaz, mint a printf, csak az eredményt egy sztringbe rakja
|
||||||
|
|
||||||
|
`vsprintf(dst, fmt, va)` olyan változat, ami paraméterlistát vár változó számú paraméter helyett.
|
||||||
|
|
||||||
|
|
||||||
|
Uart.h, uart.c
|
||||||
|
-------------
|
||||||
|
|
||||||
|
`printf(fmt, ...)` a jó öreg C függvény. A fenti sprintf-et hívja, majd az eredményt ugyanúgy írja ki, mint
|
||||||
|
ahogy azt az uart_puts() tette. Mivel most már van '%x', az uart_hex() feleslegessé vált, ezért kivettem.
|
||||||
|
|
||||||
|
Start
|
||||||
|
-----
|
||||||
|
|
||||||
|
Bár mi nem fogunk floatokat és doubleöket használni, a beépített gcc funkciók lehet, hogy használnak. Ezért
|
||||||
|
engedélyeznünk kell az FPU koprocesszort, hogy ne keletkezzenek "ismeretlen utasítás" kivételek. Továbbá mivel
|
||||||
|
ebben a példában nincs rendes kivételkezőnk, ezért az `exc_handler` csak egy függvénycsonk ebben a fájlban.
|
||||||
|
|
||||||
|
Main
|
||||||
|
----
|
||||||
|
|
||||||
|
Leteszteljük a printf megvalósításunkat.
|
@ -0,0 +1,42 @@
|
|||||||
|
Tutorial 12 - Printf
|
||||||
|
====================
|
||||||
|
|
||||||
|
Before we can improve our exception handler, we are going to need some functions very well known from the C library.
|
||||||
|
Since we are programming bare metal, we don't have libc, therefore we have to implement printf() on our own.
|
||||||
|
|
||||||
|
```sh
|
||||||
|
$ qemu-system-aarch64 -M raspi3 -kernel kernel8.img -serial stdio
|
||||||
|
Hello World!
|
||||||
|
This is character 'A', a hex number: 7FFF and in decimal: 32767
|
||||||
|
Padding test: '00007FFF', ' -123'
|
||||||
|
```
|
||||||
|
|
||||||
|
Sprintf.h, sprintf.c
|
||||||
|
--------------------
|
||||||
|
|
||||||
|
The interesting part. We heavily rely on our compiler's features to handle variable length argument list. As usual
|
||||||
|
in these tutorials, it's not a fully featured, but rather a bare minimum implementation. Supports '%s', '%c',
|
||||||
|
'%d' and '%x'. Padding is limited, only right alignment with leading zeros for hex and spaces for decimal.
|
||||||
|
|
||||||
|
`sprintf(dst, fmt, ...)` same as printf, but stores result in a string
|
||||||
|
|
||||||
|
`vsprintf(dst, fmt, va)` a variant that receives an argument list parameter instead of a variable length list of arguments.
|
||||||
|
|
||||||
|
|
||||||
|
Uart.h, uart.c
|
||||||
|
-------------
|
||||||
|
|
||||||
|
`printf(fmt, ...)` the good old C library function. Uses the sprintf function above and then outputs the string
|
||||||
|
in the same way as uart_puts() did. Since we have '%x', uart_hex() became unnecessary, therefore removed.
|
||||||
|
|
||||||
|
Start
|
||||||
|
-----
|
||||||
|
|
||||||
|
Although we are not going to use floats and doubles, gcc built-ins might. So we have to enable the FPU
|
||||||
|
coprocessor to avoid "undefined instruction" exceptions. Also, in a lack of a proper exception handler,
|
||||||
|
we have a dummy `exc_handler` stub this time.
|
||||||
|
|
||||||
|
Main
|
||||||
|
----
|
||||||
|
|
||||||
|
We test our printf implementation.
|
@ -0,0 +1,45 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2018 bzt (bztsrc@github)
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person
|
||||||
|
* obtaining a copy of this software and associated documentation
|
||||||
|
* files (the "Software"), to deal in the Software without
|
||||||
|
* restriction, including without limitation the rights to use, copy,
|
||||||
|
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||||
|
* of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be
|
||||||
|
* included in all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||||
|
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||||
|
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
|
* DEALINGS IN THE SOFTWARE.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define MMIO_BASE 0x3F000000
|
||||||
|
|
||||||
|
#define GPFSEL0 ((volatile unsigned int*)(MMIO_BASE+0x00200000))
|
||||||
|
#define GPFSEL1 ((volatile unsigned int*)(MMIO_BASE+0x00200004))
|
||||||
|
#define GPFSEL2 ((volatile unsigned int*)(MMIO_BASE+0x00200008))
|
||||||
|
#define GPFSEL3 ((volatile unsigned int*)(MMIO_BASE+0x0020000C))
|
||||||
|
#define GPFSEL4 ((volatile unsigned int*)(MMIO_BASE+0x00200010))
|
||||||
|
#define GPFSEL5 ((volatile unsigned int*)(MMIO_BASE+0x00200014))
|
||||||
|
#define GPSET0 ((volatile unsigned int*)(MMIO_BASE+0x0020001C))
|
||||||
|
#define GPSET1 ((volatile unsigned int*)(MMIO_BASE+0x00200020))
|
||||||
|
#define GPCLR0 ((volatile unsigned int*)(MMIO_BASE+0x00200028))
|
||||||
|
#define GPLEV0 ((volatile unsigned int*)(MMIO_BASE+0x00200034))
|
||||||
|
#define GPLEV1 ((volatile unsigned int*)(MMIO_BASE+0x00200038))
|
||||||
|
#define GPEDS0 ((volatile unsigned int*)(MMIO_BASE+0x00200040))
|
||||||
|
#define GPEDS1 ((volatile unsigned int*)(MMIO_BASE+0x00200044))
|
||||||
|
#define GPHEN0 ((volatile unsigned int*)(MMIO_BASE+0x00200064))
|
||||||
|
#define GPHEN1 ((volatile unsigned int*)(MMIO_BASE+0x00200068))
|
||||||
|
#define GPPUD ((volatile unsigned int*)(MMIO_BASE+0x00200094))
|
||||||
|
#define GPPUDCLK0 ((volatile unsigned int*)(MMIO_BASE+0x00200098))
|
||||||
|
#define GPPUDCLK1 ((volatile unsigned int*)(MMIO_BASE+0x0020009C))
|
Binary file not shown.
@ -0,0 +1,44 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2018 bzt (bztsrc@github)
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person
|
||||||
|
* obtaining a copy of this software and associated documentation
|
||||||
|
* files (the "Software"), to deal in the Software without
|
||||||
|
* restriction, including without limitation the rights to use, copy,
|
||||||
|
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||||
|
* of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be
|
||||||
|
* included in all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||||
|
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||||
|
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
|
* DEALINGS IN THE SOFTWARE.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
SECTIONS
|
||||||
|
{
|
||||||
|
. = 0x80000;
|
||||||
|
.text : { KEEP(*(.text.boot)) *(.text .text.* .gnu.linkonce.t*) }
|
||||||
|
.rodata : { *(.rodata .rodata.* .gnu.linkonce.r*) }
|
||||||
|
PROVIDE(_data = .);
|
||||||
|
.data : { *(.data .data.* .gnu.linkonce.d*) }
|
||||||
|
.bss (NOLOAD) : {
|
||||||
|
. = ALIGN(16);
|
||||||
|
__bss_start = .;
|
||||||
|
*(.bss .bss.*)
|
||||||
|
*(COMMON)
|
||||||
|
__bss_end = .;
|
||||||
|
}
|
||||||
|
_end = .;
|
||||||
|
|
||||||
|
/DISCARD/ : { *(.comment) *(.gnu*) *(.note*) *(.eh_frame*) }
|
||||||
|
}
|
||||||
|
__bss_size = (__bss_end - __bss_start)>>3;
|
@ -0,0 +1,43 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2018 bzt (bztsrc@github)
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person
|
||||||
|
* obtaining a copy of this software and associated documentation
|
||||||
|
* files (the "Software"), to deal in the Software without
|
||||||
|
* restriction, including without limitation the rights to use, copy,
|
||||||
|
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||||
|
* of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be
|
||||||
|
* included in all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||||
|
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||||
|
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
|
* DEALINGS IN THE SOFTWARE.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "uart.h"
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
// set up serial console
|
||||||
|
uart_init();
|
||||||
|
|
||||||
|
// test our printf implementation
|
||||||
|
printf( "Hello %s!\n"
|
||||||
|
"This is character '%c', a hex number: %x and in decimal: %d\n"
|
||||||
|
"Padding test: '%8x', '%8d'\n",
|
||||||
|
"World", 'A', 32767, 32767, 0x7FFF, -123);
|
||||||
|
|
||||||
|
// echo everything back
|
||||||
|
while(1) {
|
||||||
|
uart_send(uart_getc());
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,63 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2018 bzt (bztsrc@github)
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person
|
||||||
|
* obtaining a copy of this software and associated documentation
|
||||||
|
* files (the "Software"), to deal in the Software without
|
||||||
|
* restriction, including without limitation the rights to use, copy,
|
||||||
|
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||||
|
* of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be
|
||||||
|
* included in all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||||
|
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||||
|
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
|
* DEALINGS IN THE SOFTWARE.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "gpio.h"
|
||||||
|
|
||||||
|
/* mailbox 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
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Make a mailbox call. Returns 0 on failure, non-zero on success
|
||||||
|
*/
|
||||||
|
int mbox_call(unsigned char ch)
|
||||||
|
{
|
||||||
|
unsigned int r;
|
||||||
|
/* wait until we can write to the mailbox */
|
||||||
|
do{asm volatile("nop");}while(*MBOX_STATUS & MBOX_FULL);
|
||||||
|
/* write the address of our message to the mailbox with channel identifier */
|
||||||
|
*MBOX_WRITE = (((unsigned int)((unsigned long)&mbox)&~0xF) | (ch&0xF));
|
||||||
|
/* now wait for the response */
|
||||||
|
while(1) {
|
||||||
|
/* is there a response? */
|
||||||
|
do{asm volatile("nop");}while(*MBOX_STATUS & MBOX_EMPTY);
|
||||||
|
r=*MBOX_READ;
|
||||||
|
/* is it a response to our message? */
|
||||||
|
if((unsigned char)(r&0xF)==ch && (r&~0xF)==(unsigned int)((unsigned long)&mbox))
|
||||||
|
/* is it a valid successful response? */
|
||||||
|
return mbox[1]==MBOX_RESPONSE;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
@ -0,0 +1,47 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2018 bzt (bztsrc@github)
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person
|
||||||
|
* obtaining a copy of this software and associated documentation
|
||||||
|
* files (the "Software"), to deal in the Software without
|
||||||
|
* restriction, including without limitation the rights to use, copy,
|
||||||
|
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||||
|
* of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be
|
||||||
|
* included in all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||||
|
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||||
|
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
|
* DEALINGS IN THE SOFTWARE.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* a properly aligned buffer */
|
||||||
|
extern volatile unsigned int mbox[36];
|
||||||
|
|
||||||
|
#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_GETSERIAL 0x10004
|
||||||
|
#define MBOX_TAG_SETCLKRATE 0x38002
|
||||||
|
#define MBOX_TAG_LAST 0
|
||||||
|
|
||||||
|
int mbox_call(unsigned char ch);
|
@ -0,0 +1,148 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2018 bzt (bztsrc@github)
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person
|
||||||
|
* obtaining a copy of this software and associated documentation
|
||||||
|
* files (the "Software"), to deal in the Software without
|
||||||
|
* restriction, including without limitation the rights to use, copy,
|
||||||
|
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||||
|
* of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be
|
||||||
|
* included in all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||||
|
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||||
|
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
|
* DEALINGS IN THE SOFTWARE.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* minimal sprintf implementation
|
||||||
|
*/
|
||||||
|
unsigned int vsprintf(char *dst, char* fmt, __builtin_va_list args)
|
||||||
|
{
|
||||||
|
long int arg;
|
||||||
|
int len, sign, i;
|
||||||
|
char *p, *orig=dst, tmpstr[19];
|
||||||
|
|
||||||
|
// failsafes
|
||||||
|
if(dst==(void*)0 || fmt==(void*)0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// main loop
|
||||||
|
arg = 0;
|
||||||
|
while(*fmt) {
|
||||||
|
// argument access
|
||||||
|
if(*fmt=='%') {
|
||||||
|
fmt++;
|
||||||
|
// literal %
|
||||||
|
if(*fmt=='%') {
|
||||||
|
goto put;
|
||||||
|
}
|
||||||
|
len=0;
|
||||||
|
// size modifier
|
||||||
|
while(*fmt>='0' && *fmt<='9') {
|
||||||
|
len *= 10;
|
||||||
|
len += *fmt-'0';
|
||||||
|
fmt++;
|
||||||
|
}
|
||||||
|
// skip long modifier
|
||||||
|
if(*fmt=='l') {
|
||||||
|
fmt++;
|
||||||
|
}
|
||||||
|
// character
|
||||||
|
if(*fmt=='c') {
|
||||||
|
arg = __builtin_va_arg(args, int);
|
||||||
|
*dst++ = (char)arg;
|
||||||
|
fmt++;
|
||||||
|
continue;
|
||||||
|
} else
|
||||||
|
// decimal number
|
||||||
|
if(*fmt=='d') {
|
||||||
|
arg = __builtin_va_arg(args, int);
|
||||||
|
// check input
|
||||||
|
sign=0;
|
||||||
|
if((int)arg<0) {
|
||||||
|
arg*=-1;
|
||||||
|
sign++;
|
||||||
|
}
|
||||||
|
if(arg>99999999999999999L) {
|
||||||
|
arg=99999999999999999L;
|
||||||
|
}
|
||||||
|
// convert to string
|
||||||
|
i=18;
|
||||||
|
tmpstr[i]=0;
|
||||||
|
do {
|
||||||
|
tmpstr[--i]='0'+(arg%10);
|
||||||
|
arg/=10;
|
||||||
|
} while(arg!=0 && i>0);
|
||||||
|
if(sign) {
|
||||||
|
tmpstr[--i]='-';
|
||||||
|
}
|
||||||
|
// padding, only space
|
||||||
|
if(len>0 && len<18) {
|
||||||
|
while(i>18-len) {
|
||||||
|
tmpstr[--i]=' ';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
p=&tmpstr[i];
|
||||||
|
goto copystring;
|
||||||
|
} else
|
||||||
|
// hex number
|
||||||
|
if(*fmt=='x') {
|
||||||
|
arg = __builtin_va_arg(args, long int);
|
||||||
|
// convert to string
|
||||||
|
i=16;
|
||||||
|
tmpstr[i]=0;
|
||||||
|
do {
|
||||||
|
char n=arg & 0xf;
|
||||||
|
// 0-9 => '0'-'9', 10-15 => 'A'-'F'
|
||||||
|
tmpstr[--i]=n+(n>9?0x37:0x30);
|
||||||
|
arg>>=4;
|
||||||
|
} while(arg!=0 && i>0);
|
||||||
|
// padding, only leading zeros
|
||||||
|
if(len>0 && len<=16) {
|
||||||
|
while(i>16-len) {
|
||||||
|
tmpstr[--i]='0';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
p=&tmpstr[i];
|
||||||
|
goto copystring;
|
||||||
|
} else
|
||||||
|
// string
|
||||||
|
if(*fmt=='s') {
|
||||||
|
p = __builtin_va_arg(args, char*);
|
||||||
|
copystring: if(p==(void*)0) {
|
||||||
|
p="(null)";
|
||||||
|
}
|
||||||
|
while(*p) {
|
||||||
|
*dst++ = *p++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
put: *dst++ = *fmt;
|
||||||
|
}
|
||||||
|
fmt++;
|
||||||
|
}
|
||||||
|
*dst=0;
|
||||||
|
// number of bytes written
|
||||||
|
return dst-orig;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Variable length arguments
|
||||||
|
*/
|
||||||
|
unsigned int sprintf(char *dst, char* fmt, ...)
|
||||||
|
{
|
||||||
|
__builtin_va_list args;
|
||||||
|
__builtin_va_start(args, fmt);
|
||||||
|
return vsprintf(dst,fmt,args);
|
||||||
|
}
|
@ -0,0 +1,27 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2018 bzt (bztsrc@github)
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person
|
||||||
|
* obtaining a copy of this software and associated documentation
|
||||||
|
* files (the "Software"), to deal in the Software without
|
||||||
|
* restriction, including without limitation the rights to use, copy,
|
||||||
|
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||||
|
* of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be
|
||||||
|
* included in all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||||
|
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||||
|
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
|
* DEALINGS IN THE SOFTWARE.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
unsigned int sprintf(char *dst, char* fmt, ...);
|
||||||
|
unsigned int vsprintf(char *dst,char* fmt, __builtin_va_list args);
|
@ -0,0 +1,149 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2018 bzt (bztsrc@github)
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person
|
||||||
|
* obtaining a copy of this software and associated documentation
|
||||||
|
* files (the "Software"), to deal in the Software without
|
||||||
|
* restriction, including without limitation the rights to use, copy,
|
||||||
|
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||||
|
* of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be
|
||||||
|
* included in all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||||
|
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||||
|
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
|
* DEALINGS IN THE SOFTWARE.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
.section ".text.boot"
|
||||||
|
|
||||||
|
.global _start
|
||||||
|
|
||||||
|
_start:
|
||||||
|
// read cpu id, stop slave cores
|
||||||
|
mrs x1, mpidr_el1
|
||||||
|
and x1, x1, #3
|
||||||
|
cbz x1, 2f
|
||||||
|
// cpu id > 0, stop
|
||||||
|
1: wfe
|
||||||
|
b 1b
|
||||||
|
2: // cpu id == 0
|
||||||
|
|
||||||
|
// set stack before our code
|
||||||
|
ldr x1, =_start
|
||||||
|
|
||||||
|
// set up EL1
|
||||||
|
mrs x0, CurrentEL
|
||||||
|
and x0, x0, #12 // clear reserved bits
|
||||||
|
|
||||||
|
// running at EL3?
|
||||||
|
cmp x0, #12
|
||||||
|
bne 5f
|
||||||
|
// should never be executed, just for completeness
|
||||||
|
mov x2, #0x5b1
|
||||||
|
msr scr_el3, x2
|
||||||
|
mov x2, #0x3c9
|
||||||
|
msr spsr_el3, x2
|
||||||
|
adr x2, 5f
|
||||||
|
msr elr_el3, x2
|
||||||
|
eret
|
||||||
|
|
||||||
|
// running at EL2?
|
||||||
|
5: cmp x0, #4
|
||||||
|
beq 5f
|
||||||
|
msr sp_el1, x1
|
||||||
|
// enable CNTP for EL1
|
||||||
|
mrs x0, cnthctl_el2
|
||||||
|
orr x0, x0, #3
|
||||||
|
msr cnthctl_el2, x0
|
||||||
|
msr cntvoff_el2, xzr
|
||||||
|
// disable coprocessor traps
|
||||||
|
mov x0, #0x33FF
|
||||||
|
msr cptr_el2, x0
|
||||||
|
msr hstr_el2, xzr
|
||||||
|
mov x0, #(3 << 20)
|
||||||
|
msr cpacr_el1, x0
|
||||||
|
// enable AArch64 in EL1
|
||||||
|
mov x0, #(1 << 31) // AArch64
|
||||||
|
orr x0, x0, #(1 << 1) // SWIO hardwired on Pi3
|
||||||
|
msr hcr_el2, x0
|
||||||
|
mrs x0, hcr_el2
|
||||||
|
// Setup SCTLR access
|
||||||
|
mov x2, #0x0800
|
||||||
|
movk x2, #0x30d0, lsl #16
|
||||||
|
msr sctlr_el1, x2
|
||||||
|
// set up exception handlers
|
||||||
|
ldr x2, =_vectors
|
||||||
|
msr vbar_el1, x2
|
||||||
|
// change execution level to EL1
|
||||||
|
mov x2, #0x3c4
|
||||||
|
msr spsr_el2, x2
|
||||||
|
adr x2, 5f
|
||||||
|
msr elr_el2, x2
|
||||||
|
eret
|
||||||
|
|
||||||
|
5: mov sp, x1
|
||||||
|
|
||||||
|
// clear bss
|
||||||
|
ldr x1, =__bss_start
|
||||||
|
ldr w2, =__bss_size
|
||||||
|
3: cbz w2, 4f
|
||||||
|
str xzr, [x1], #8
|
||||||
|
sub w2, w2, #1
|
||||||
|
cbnz w2, 3b
|
||||||
|
|
||||||
|
// jump to C code, should not return
|
||||||
|
4: bl main
|
||||||
|
// for failsafe, halt this core too
|
||||||
|
b 1b
|
||||||
|
|
||||||
|
// a dummy exception handler in this tutorial
|
||||||
|
exc_handler:
|
||||||
|
eret
|
||||||
|
|
||||||
|
// important, code has to be properly aligned
|
||||||
|
.align 11
|
||||||
|
_vectors:
|
||||||
|
// synchronous
|
||||||
|
.align 7
|
||||||
|
mov x0, #0
|
||||||
|
mrs x1, esr_el1
|
||||||
|
mrs x2, elr_el1
|
||||||
|
mrs x3, spsr_el1
|
||||||
|
mrs x4, far_el1
|
||||||
|
b exc_handler
|
||||||
|
|
||||||
|
// IRQ
|
||||||
|
.align 7
|
||||||
|
mov x0, #1
|
||||||
|
mrs x1, esr_el1
|
||||||
|
mrs x2, elr_el1
|
||||||
|
mrs x3, spsr_el1
|
||||||
|
mrs x4, far_el1
|
||||||
|
b exc_handler
|
||||||
|
|
||||||
|
// FIQ
|
||||||
|
.align 7
|
||||||
|
mov x0, #2
|
||||||
|
mrs x1, esr_el1
|
||||||
|
mrs x2, elr_el1
|
||||||
|
mrs x3, spsr_el1
|
||||||
|
mrs x4, far_el1
|
||||||
|
b exc_handler
|
||||||
|
|
||||||
|
// SError
|
||||||
|
.align 7
|
||||||
|
mov x0, #3
|
||||||
|
mrs x1, esr_el1
|
||||||
|
mrs x2, elr_el1
|
||||||
|
mrs x3, spsr_el1
|
||||||
|
mrs x4, far_el1
|
||||||
|
b exc_handler
|
@ -0,0 +1,123 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2018 bzt (bztsrc@github)
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person
|
||||||
|
* obtaining a copy of this software and associated documentation
|
||||||
|
* files (the "Software"), to deal in the Software without
|
||||||
|
* restriction, including without limitation the rights to use, copy,
|
||||||
|
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||||
|
* of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be
|
||||||
|
* included in all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||||
|
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||||
|
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
|
* DEALINGS IN THE SOFTWARE.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "gpio.h"
|
||||||
|
#include "mbox.h"
|
||||||
|
#include "sprintf.h"
|
||||||
|
|
||||||
|
/* PL011 UART registers */
|
||||||
|
#define UART0_DR ((volatile unsigned int*)(MMIO_BASE+0x00201000))
|
||||||
|
#define UART0_FR ((volatile unsigned int*)(MMIO_BASE+0x00201018))
|
||||||
|
#define UART0_IBRD ((volatile unsigned int*)(MMIO_BASE+0x00201024))
|
||||||
|
#define UART0_FBRD ((volatile unsigned int*)(MMIO_BASE+0x00201028))
|
||||||
|
#define UART0_LCRH ((volatile unsigned int*)(MMIO_BASE+0x0020102C))
|
||||||
|
#define UART0_CR ((volatile unsigned int*)(MMIO_BASE+0x00201030))
|
||||||
|
#define UART0_IMSC ((volatile unsigned int*)(MMIO_BASE+0x00201038))
|
||||||
|
#define UART0_ICR ((volatile unsigned int*)(MMIO_BASE+0x00201044))
|
||||||
|
|
||||||
|
// get address from linker
|
||||||
|
extern volatile unsigned char _end;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set baud rate and characteristics (115200 8N1) and map to GPIO
|
||||||
|
*/
|
||||||
|
void uart_init()
|
||||||
|
{
|
||||||
|
register unsigned int r;
|
||||||
|
|
||||||
|
/* initialize UART */
|
||||||
|
*UART0_CR = 0; // turn off UART0
|
||||||
|
|
||||||
|
/* set up clock for consistent divisor values */
|
||||||
|
mbox[0] = 8*4;
|
||||||
|
mbox[1] = MBOX_REQUEST;
|
||||||
|
mbox[2] = MBOX_TAG_SETCLKRATE; // set clock rate
|
||||||
|
mbox[3] = 12;
|
||||||
|
mbox[4] = 8;
|
||||||
|
mbox[5] = 2; // UART clock
|
||||||
|
mbox[6] = 4000000; // 4Mhz
|
||||||
|
mbox[7] = MBOX_TAG_LAST;
|
||||||
|
mbox_call(MBOX_CH_PROP);
|
||||||
|
|
||||||
|
/* map UART0 to GPIO pins */
|
||||||
|
r=*GPFSEL1;
|
||||||
|
r&=~((7<<12)|(7<<15)); // gpio14, gpio15
|
||||||
|
r|=(4<<12)|(4<<15); // alt0
|
||||||
|
*GPFSEL1 = r;
|
||||||
|
*GPPUD = 0; // enable pins 14 and 15
|
||||||
|
r=150; while(r--) { asm volatile("nop"); }
|
||||||
|
*GPPUDCLK0 = (1<<14)|(1<<15);
|
||||||
|
r=150; while(r--) { asm volatile("nop"); }
|
||||||
|
*GPPUDCLK0 = 0; // flush GPIO setup
|
||||||
|
|
||||||
|
*UART0_ICR = 0x7FF; // clear interrupts
|
||||||
|
*UART0_IBRD = 2; // 115200 baud
|
||||||
|
*UART0_FBRD = 0xB;
|
||||||
|
*UART0_LCRH = 0b11<<5; // 8n1
|
||||||
|
*UART0_CR = 0x301; // enable Tx, Rx, FIFO
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send a character
|
||||||
|
*/
|
||||||
|
void uart_send(unsigned int c) {
|
||||||
|
/* wait until we can send */
|
||||||
|
do{asm volatile("nop");}while(*UART0_FR&0x20);
|
||||||
|
/* write the character to the buffer */
|
||||||
|
*UART0_DR=c;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Receive a character
|
||||||
|
*/
|
||||||
|
char uart_getc() {
|
||||||
|
char r;
|
||||||
|
/* wait until something is in the buffer */
|
||||||
|
do{asm volatile("nop");}while(*UART0_FR&0x10);
|
||||||
|
/* read it and return */
|
||||||
|
r=(char)(*UART0_DR);
|
||||||
|
/* convert carrige return to newline */
|
||||||
|
return r=='\r'?'\n':r;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Display a string
|
||||||
|
*/
|
||||||
|
void printf(char *fmt, ...) {
|
||||||
|
__builtin_va_list args;
|
||||||
|
__builtin_va_start(args, fmt);
|
||||||
|
// we don't have memory allocation yet, so we
|
||||||
|
// simply place our string after our code
|
||||||
|
char *s = (char*)&_end;
|
||||||
|
// use sprintf to format our string
|
||||||
|
vsprintf(s,fmt,args);
|
||||||
|
// print out as usual
|
||||||
|
while(*s) {
|
||||||
|
/* convert newline to carrige return + newline */
|
||||||
|
if(*s=='\n')
|
||||||
|
uart_send('\r');
|
||||||
|
uart_send(*s++);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,29 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2018 bzt (bztsrc@github)
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person
|
||||||
|
* obtaining a copy of this software and associated documentation
|
||||||
|
* files (the "Software"), to deal in the Software without
|
||||||
|
* restriction, including without limitation the rights to use, copy,
|
||||||
|
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||||
|
* of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be
|
||||||
|
* included in all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||||
|
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||||
|
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
|
* DEALINGS IN THE SOFTWARE.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
void uart_init();
|
||||||
|
void uart_send(unsigned int c);
|
||||||
|
char uart_getc();
|
||||||
|
void printf(char *fmt, ...);
|
@ -0,0 +1,43 @@
|
|||||||
|
#
|
||||||
|
# Copyright (C) 2018 bzt (bztsrc@github)
|
||||||
|
#
|
||||||
|
# Permission is hereby granted, free of charge, to any person
|
||||||
|
# obtaining a copy of this software and associated documentation
|
||||||
|
# files (the "Software"), to deal in the Software without
|
||||||
|
# restriction, including without limitation the rights to use, copy,
|
||||||
|
# modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||||
|
# of the Software, and to permit persons to whom the Software is
|
||||||
|
# furnished to do so, subject to the following conditions:
|
||||||
|
#
|
||||||
|
# The above copyright notice and this permission notice shall be
|
||||||
|
# included in all copies or substantial portions of the Software.
|
||||||
|
#
|
||||||
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||||
|
# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||||
|
# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
|
# DEALINGS IN THE SOFTWARE.
|
||||||
|
#
|
||||||
|
#
|
||||||
|
|
||||||
|
SRCS = $(wildcard *.c)
|
||||||
|
OBJS = $(SRCS:.c=.o)
|
||||||
|
CFLAGS = -Wall -O2 -ffreestanding -nostdinc -nostdlib -nostartfiles
|
||||||
|
|
||||||
|
all: clean kernel8.img
|
||||||
|
|
||||||
|
start.o: start.S
|
||||||
|
aarch64-elf-gcc $(CFLAGS) -c start.S -o start.o
|
||||||
|
|
||||||
|
%.o: %.c
|
||||||
|
aarch64-elf-gcc $(CFLAGS) -c $< -o $@
|
||||||
|
|
||||||
|
kernel8.img: start.o $(OBJS)
|
||||||
|
aarch64-elf-ld -nostdlib -nostartfiles start.o $(OBJS) -T link.ld -o kernel8.elf
|
||||||
|
aarch64-elf-objcopy -O binary kernel8.elf kernel8.img
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm kernel8.elf *.o >/dev/null 2>/dev/null || true
|
@ -0,0 +1,54 @@
|
|||||||
|
Oktatóanyag 13 - Debugger
|
||||||
|
=========================
|
||||||
|
|
||||||
|
Zuzassunk egy nagyot, rakjunk mindjárt egy interaktív debuggert a kivételkezelőbe! :-) Most hogy már van printf(),
|
||||||
|
nem lesz olyan vészes.
|
||||||
|
|
||||||
|
```sh
|
||||||
|
$ qemu-system-aarch64 -M raspi3 -kernel kernel8.img -serial stdio
|
||||||
|
Synchronous: Breakpoint instruction
|
||||||
|
> x
|
||||||
|
0007FFF0: 13 60 09 00 00 00 00 00 24 10 20 3F 00 00 00 00 .`......$. ?....
|
||||||
|
> i x30 x30+64
|
||||||
|
00080804: D2800000 movz x0, #0x0
|
||||||
|
00080808: 94003D1C bl 0x8FC78
|
||||||
|
0008080C: 94003ECF bl 0x90348
|
||||||
|
00080810: D69F03E0 eret
|
||||||
|
00080814: D503201F 27 x nop
|
||||||
|
>
|
||||||
|
```
|
||||||
|
|
||||||
|
Dbg.h, dbg.c
|
||||||
|
------------
|
||||||
|
|
||||||
|
Egy nagyon minimális és egyszerű debugger (~300 C sor).
|
||||||
|
|
||||||
|
`breakpoint` újonnan definiált C kulcsszó. Ahová beillesztjük a kódba, ott meghívódik a debugger
|
||||||
|
|
||||||
|
`dbg_decodeexc()` hasonló a 11-es oktatóanyagbeli exc_handler-hez, dekódolja a kivételt kiváltó okot és kiírja
|
||||||
|
|
||||||
|
`dbg_getline()` na ja, mégegy hiányzó függvény. Szükségünk van egy módra, amivel a felhasználó szerkesztheti
|
||||||
|
a parancssort és ami sztringként visszaadja amit begépelt, mikor <kbd>Enter</kbd>-t üt. Szokásunkhoz híven minimál
|
||||||
|
|
||||||
|
`dbg_getoffs()` ez a funkció a parancs paramétereit értelmezi. Elfogad hexa és decimális számot "regiszter+/-offszet"
|
||||||
|
formátumban
|
||||||
|
|
||||||
|
`dbg_main()` a debugger fő ciklusa.
|
||||||
|
|
||||||
|
Disasm.h
|
||||||
|
--------
|
||||||
|
|
||||||
|
Mivel kicsi (~72k), kivételesen könnyű integrálni, mégis minden ARMv8.2-es utasítást ismer, ezért a választásom
|
||||||
|
az [Universal Disassembler](https://github.com/bztsrc/udisasm)-re esett ehhez az oktatóanyaghoz. Ha nem szeretnél
|
||||||
|
disassemblert belefordítani a debuggeredbe, akkor a dbg.c fájl elején állítsd a DISASSEMBLER define-t 0-ra.
|
||||||
|
|
||||||
|
Start
|
||||||
|
-----
|
||||||
|
|
||||||
|
A `_vector` táblánk kicsit máshogy fest. Először is el kell mentenünk a regiszterek értékét a `dbg_saveregs` hívással,
|
||||||
|
majd kiírjuk a kivétel okát és meghívjuk a mini-debuggerünk fő ciklusát.
|
||||||
|
|
||||||
|
Main
|
||||||
|
----
|
||||||
|
|
||||||
|
Leteszteljük az új `breakpoint` kulcsszavunkat C-ben.
|
@ -0,0 +1,54 @@
|
|||||||
|
Tutorial 13 - Debugger
|
||||||
|
======================
|
||||||
|
|
||||||
|
Let's rock by implementing an interactive debugger in our exception handler! :-) Now that we have printf(), it
|
||||||
|
shouldn't be hard.
|
||||||
|
|
||||||
|
```sh
|
||||||
|
$ qemu-system-aarch64 -M raspi3 -kernel kernel8.img -serial stdio
|
||||||
|
Synchronous: Breakpoint instruction
|
||||||
|
> x
|
||||||
|
0007FFF0: 13 60 09 00 00 00 00 00 24 10 20 3F 00 00 00 00 .`......$. ?....
|
||||||
|
> i x30 x30+64
|
||||||
|
00080804: D2800000 movz x0, #0x0
|
||||||
|
00080808: 94003D1C bl 0x8FC78
|
||||||
|
0008080C: 94003ECF bl 0x90348
|
||||||
|
00080810: D69F03E0 eret
|
||||||
|
00080814: D503201F 27 x nop
|
||||||
|
>
|
||||||
|
```
|
||||||
|
|
||||||
|
Dbg.h, dbg.c
|
||||||
|
------------
|
||||||
|
|
||||||
|
A very minimal and simple debugger (~300 lines in C).
|
||||||
|
|
||||||
|
`breakpoint` a newly defined keyword. We can use this anywhere in our code where we want to invoke the debugger
|
||||||
|
|
||||||
|
`dbg_decodeexc()` similar to exc_handler in tutorial 11, decodes the cause of the exception and prints it
|
||||||
|
|
||||||
|
`dbg_getline()` yep, another low level library we're missing. We need a way to allow the user to edit command line
|
||||||
|
and return it as a string when he/she presses <kbd>Enter</kbd>. A minimal implementation, as usual
|
||||||
|
|
||||||
|
`dbg_getoffs()` this function parses the command line for arguments. Accepts hex, decimal number in
|
||||||
|
"register+/-offset" format
|
||||||
|
|
||||||
|
`dbg_main()` the main loop of the debugger.
|
||||||
|
|
||||||
|
Disasm.h
|
||||||
|
--------
|
||||||
|
|
||||||
|
Because it's small (~72k), extremely easy to integrate, yet it supports all ARMv8.2 instructions, I decided to
|
||||||
|
use the [Universal Disassembler](https://github.com/bztsrc/udisasm) for this tutorial. If you don't want to
|
||||||
|
compile a disassembler into your debugger, simply set the DISASSEMBLER define 0 in top of dbg.c.
|
||||||
|
|
||||||
|
Start
|
||||||
|
-----
|
||||||
|
|
||||||
|
Our `_vector` table looks different. We have to save registers in memory with `dbg_saveregs`, print out
|
||||||
|
the cause of the exception, and call our mini-debugger's main loop.
|
||||||
|
|
||||||
|
Main
|
||||||
|
----
|
||||||
|
|
||||||
|
We'll test our shiny new `breakpoint` keyword in C.
|
@ -0,0 +1,332 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2018 bzt (bztsrc@github)
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person
|
||||||
|
* obtaining a copy of this software and associated documentation
|
||||||
|
* files (the "Software"), to deal in the Software without
|
||||||
|
* restriction, including without limitation the rights to use, copy,
|
||||||
|
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||||
|
* of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be
|
||||||
|
* included in all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||||
|
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||||
|
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
|
* DEALINGS IN THE SOFTWARE.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "uart.h"
|
||||||
|
|
||||||
|
#define DISASSEMBLER 1
|
||||||
|
|
||||||
|
// array to store register values (see dbg_saveregs in start.S)
|
||||||
|
unsigned long dbg_regs[37];
|
||||||
|
// command line
|
||||||
|
char cmd[256], dbg_running=0;
|
||||||
|
|
||||||
|
#if DISASSEMBLER
|
||||||
|
/**
|
||||||
|
* things needed by the disassembler
|
||||||
|
*/
|
||||||
|
#include "sprintf.h"
|
||||||
|
#define NULL ((void*)0)
|
||||||
|
typedef unsigned long uint64_t;
|
||||||
|
typedef unsigned int uint32_t;
|
||||||
|
typedef unsigned short uint16_t;
|
||||||
|
typedef unsigned char uint8_t;
|
||||||
|
// include the Universal Disassembler Library
|
||||||
|
#include "disasm.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decode exception cause
|
||||||
|
*/
|
||||||
|
void dbg_decodeexc(unsigned long type)
|
||||||
|
{
|
||||||
|
unsigned char cause=dbg_regs[33]>>26;
|
||||||
|
|
||||||
|
// print out interruption type
|
||||||
|
switch(type) {
|
||||||
|
case 0: printf("Synchronous"); break;
|
||||||
|
case 1: printf("IRQ"); break;
|
||||||
|
case 2: printf("FIQ"); break;
|
||||||
|
case 3: printf("SError"); break;
|
||||||
|
}
|
||||||
|
printf(": ");
|
||||||
|
// decode exception type (some, not all. See ARM DDI0487B_b chapter D10.2.28)
|
||||||
|
switch(cause) {
|
||||||
|
case 0b000000: printf("Unknown"); break;
|
||||||
|
case 0b000001: printf("Trapped WFI/WFE"); break;
|
||||||
|
case 0b001110: printf("Illegal execution"); break;
|
||||||
|
case 0b010101: printf("System call"); break;
|
||||||
|
case 0b100000: printf("Instruction abort, lower EL"); break;
|
||||||
|
case 0b100001: printf("Instruction abort, same EL"); break;
|
||||||
|
case 0b100010: printf("Instruction alignment fault"); break;
|
||||||
|
case 0b100100: printf("Data abort, lower EL"); break;
|
||||||
|
case 0b100101: printf("Data abort, same EL"); break;
|
||||||
|
case 0b100110: printf("Stack alignment fault"); break;
|
||||||
|
case 0b101100: printf("Floating point"); break;
|
||||||
|
case 0b110000: printf("Breakpoint, lower EL"); break;
|
||||||
|
case 0b110001: printf("Breakpoint, same EL"); break;
|
||||||
|
case 0b111100: printf("Breakpoint instruction"); break;
|
||||||
|
default: printf("Unknown %x", cause); break;
|
||||||
|
}
|
||||||
|
// decode data abort cause
|
||||||
|
if(cause==0b100100 || cause==0b100101) {
|
||||||
|
printf(", ");
|
||||||
|
switch((dbg_regs[33]>>2)&0x3) {
|
||||||
|
case 0: printf("Address size fault"); break;
|
||||||
|
case 1: printf("Translation fault"); break;
|
||||||
|
case 2: printf("Access flag fault"); break;
|
||||||
|
case 3: printf("Permission fault"); break;
|
||||||
|
}
|
||||||
|
switch(dbg_regs[33]&0x3) {
|
||||||
|
case 0: printf(" at level 0"); break;
|
||||||
|
case 1: printf(" at level 1"); break;
|
||||||
|
case 2: printf(" at level 2"); break;
|
||||||
|
case 3: printf(" at level 3"); break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
// if the exception happened in the debugger, we stop to avoid infinite loop
|
||||||
|
if(dbg_running) {
|
||||||
|
printf("Exception in debugger!\n"
|
||||||
|
" elr_el1: %x spsr_el1: %x\n esr_el1: %x far_el1: %x\nsctlr_el1: %x tcr_el1: %x\n",
|
||||||
|
dbg_regs[31],dbg_regs[32],dbg_regs[33],dbg_regs[34],dbg_regs[35],dbg_regs[36]);
|
||||||
|
while(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* helper to read a line from user. We redefine some control caracters to handle CSI
|
||||||
|
* \e[3~ = 1, delete
|
||||||
|
* \e[D = 2, cursor left
|
||||||
|
* \e[C = 3, cursor right
|
||||||
|
*/
|
||||||
|
void dbg_getline()
|
||||||
|
{
|
||||||
|
int i,cmdidx=0,cmdlast=0;
|
||||||
|
char c;
|
||||||
|
cmd[0]=0;
|
||||||
|
// prompt
|
||||||
|
printf("\r> ");
|
||||||
|
// read until Enter pressed
|
||||||
|
while((c=uart_getc())!='\n') {
|
||||||
|
// decode CSI key sequences (some, not all)
|
||||||
|
if(c==27) {
|
||||||
|
c=uart_getc();
|
||||||
|
if(c=='[') {
|
||||||
|
c=uart_getc();
|
||||||
|
if(c=='C') c=3; else // left
|
||||||
|
if(c=='D') c=2; else // right
|
||||||
|
if(c=='3') {
|
||||||
|
c=uart_getc();
|
||||||
|
if(c=='~') c=1; // delete
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Backspace
|
||||||
|
if(c==8 || c==127) {
|
||||||
|
if(cmdidx>0) {
|
||||||
|
cmdidx--;
|
||||||
|
for(i=cmdidx;i<cmdlast;i++) cmd[i]=cmd[i+1];
|
||||||
|
cmdlast--;
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
// Delete
|
||||||
|
if(c==1) {
|
||||||
|
if(cmdidx<cmdlast) {
|
||||||
|
for(i=cmdidx;i<cmdlast;i++) cmd[i]=cmd[i+1];
|
||||||
|
cmdlast--;
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
// cursor left
|
||||||
|
if(c==2) {
|
||||||
|
if(cmdidx>0) cmdidx--;
|
||||||
|
} else
|
||||||
|
// cursor right
|
||||||
|
if(c==3) {
|
||||||
|
if(cmdidx<cmdlast) cmdidx++;
|
||||||
|
} else {
|
||||||
|
// is there a valid character and space to store it?
|
||||||
|
if(c<' ' || cmdlast>=sizeof(cmd)-1) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// if we're not appending, move bytes after cursor
|
||||||
|
if(cmdidx<cmdlast) {
|
||||||
|
for(i=cmdlast;i>cmdidx;i--)
|
||||||
|
cmd[i]=cmd[i-1];
|
||||||
|
}
|
||||||
|
cmdlast++;
|
||||||
|
cmd[cmdidx++]=c;
|
||||||
|
}
|
||||||
|
cmd[cmdlast]=0;
|
||||||
|
// display prompt and command line, place cursor with CSI code
|
||||||
|
printf("\r> %s \r\e[%dC",cmd,cmdidx+2);
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* helper function to parse the command line for arguments
|
||||||
|
*/
|
||||||
|
unsigned long dbg_getoffs(int i)
|
||||||
|
{
|
||||||
|
unsigned long base=0,ret=0;
|
||||||
|
int j=0,sign=0;
|
||||||
|
// if starts with a register
|
||||||
|
if(cmd[i]=='x' || cmd[i]=='r') {
|
||||||
|
i++; if(cmd[i]>='0' && cmd[i]<='9') { j=cmd[i]-'0'; }
|
||||||
|
i++; if(cmd[i]>='0' && cmd[i]<='9') { j*=10; j+=cmd[i]-'0'; }
|
||||||
|
if(j>=0 && j<37) base=dbg_regs[j];
|
||||||
|
i++;
|
||||||
|
if(cmd[i]=='-') { i++; sign++; }
|
||||||
|
if(cmd[i]=='+') i++;
|
||||||
|
}
|
||||||
|
// offset part
|
||||||
|
if(cmd[i]=='0' && cmd[i+1]=='x') {
|
||||||
|
i+=2;
|
||||||
|
// hex value
|
||||||
|
while((cmd[i]>='0'&&cmd[i]<='9')||(cmd[i]>='a'&&cmd[i]<='f')||(cmd[i]>='A'&&cmd[i]<='F')) {
|
||||||
|
ret <<= 4;
|
||||||
|
if(cmd[i]>='0' && cmd[i]<='9') ret += cmd[i]-'0';
|
||||||
|
else if(cmd[i] >= 'a' && cmd[i] <= 'f') ret += cmd[i]-'a'+10;
|
||||||
|
else if(cmd[i] >= 'A' && cmd[i] <= 'F') ret += cmd[i]-'A'+10;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// decimal value
|
||||||
|
while(cmd[i]>='0'&&cmd[i]<='9'){
|
||||||
|
ret *= 10;
|
||||||
|
ret += cmd[i++]-'0';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// return base + offset
|
||||||
|
return sign? base-ret : base+ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* main loop, get and parse commands
|
||||||
|
*/
|
||||||
|
void dbg_main()
|
||||||
|
{
|
||||||
|
unsigned long os=0, oe=0, a;
|
||||||
|
char c;
|
||||||
|
#if DISASSEMBLER
|
||||||
|
char str[64];
|
||||||
|
#endif
|
||||||
|
int i;
|
||||||
|
|
||||||
|
dbg_running++;
|
||||||
|
|
||||||
|
// main debugger loop
|
||||||
|
while(1) {
|
||||||
|
// get command from user
|
||||||
|
dbg_getline();
|
||||||
|
// parse commands
|
||||||
|
if(cmd[0]==0 || cmd[0]=='?' || cmd[0]=='h') {
|
||||||
|
// print help
|
||||||
|
printf("Mini debugger commands:\n"
|
||||||
|
" ?/h\t\tthis help\n"
|
||||||
|
" r\t\tdump registers\n"
|
||||||
|
" x [os [oe]]\texamine memory from offset start (os) to offset end (oe)\n"
|
||||||
|
" i [os [oe]]\tdisassemble instruction from offset start to offset end\n"
|
||||||
|
" c\t\tcontinue execution\n");
|
||||||
|
continue;
|
||||||
|
} else
|
||||||
|
// continue execution
|
||||||
|
if(cmd[0]=='c') {
|
||||||
|
// move instruction pointer, skip over 'brk'
|
||||||
|
asm volatile ("msr elr_el1, %0" : : "r" (dbg_regs[31]+4));
|
||||||
|
break;
|
||||||
|
} else
|
||||||
|
// dump registers
|
||||||
|
if(cmd[0]=='r') {
|
||||||
|
// general purpose registers x0-x30
|
||||||
|
for(i=0;i<31;i++) {
|
||||||
|
if(i && i%3==0) printf("\n");
|
||||||
|
if(i<10) printf(" ");
|
||||||
|
printf("x%d: %16x ",i,dbg_regs[i]);
|
||||||
|
}
|
||||||
|
// some system registers
|
||||||
|
printf("elr_el1: %x spsr_el1: %x\n esr_el1: %x far_el1: %x\nsctlr_el1: %x tcr_el1: %x\n",
|
||||||
|
dbg_regs[31],dbg_regs[32],dbg_regs[33],dbg_regs[34],dbg_regs[35],dbg_regs[36]);
|
||||||
|
continue;
|
||||||
|
} else
|
||||||
|
// examine or disassemble, commands with arguments
|
||||||
|
if(cmd[0]=='x' || cmd[0]=='i') {
|
||||||
|
i=1;
|
||||||
|
// get first argument
|
||||||
|
while(cmd[i]!=0 && cmd[i]!=' ') i++; // skip command
|
||||||
|
while(cmd[i]!=0 && cmd[i]==' ') i++; // skip separators
|
||||||
|
if(cmd[i]!=0) {
|
||||||
|
os=oe=dbg_getoffs(i);
|
||||||
|
// get second argument
|
||||||
|
while(cmd[i]!=0 && cmd[i]!=' ') i++; // skip 1st arg
|
||||||
|
while(cmd[i]!=0 && cmd[i]==' ') i++; // skip separators
|
||||||
|
if(cmd[i]!=0) {
|
||||||
|
oe=dbg_getoffs(i);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// no arguments, use defaults
|
||||||
|
if(cmd[0]=='i') {
|
||||||
|
// elr or lr (x30)
|
||||||
|
os=oe=dbg_regs[31]?dbg_regs[31]:dbg_regs[30];
|
||||||
|
} else {
|
||||||
|
// sp (x29)
|
||||||
|
os=oe=dbg_regs[29];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// do the thing
|
||||||
|
if(cmd[0]=='i') {
|
||||||
|
// must be multiple of 4
|
||||||
|
os=os&~3L;
|
||||||
|
oe=(oe+3)&~3L;
|
||||||
|
if(oe<=os) oe=os+4;
|
||||||
|
// disassemble AArch64 bytecode
|
||||||
|
while(os<oe) {
|
||||||
|
// print out address and instruction bytecode
|
||||||
|
printf("%8x: %8x",os,*((unsigned int*)os));
|
||||||
|
#if DISASSEMBLER
|
||||||
|
// disassemble and print out instruction mnemonic
|
||||||
|
os=disasm(os,str);
|
||||||
|
printf("\t%s\n",str);
|
||||||
|
#else
|
||||||
|
os+=4;
|
||||||
|
printf("\n");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// dump memory
|
||||||
|
if(oe<=os) oe=os+16;
|
||||||
|
// for each 16 bytes, do
|
||||||
|
for(a=os;a<oe;a+=16) {
|
||||||
|
// print out address
|
||||||
|
printf("%8x: ", a);
|
||||||
|
// hex representation
|
||||||
|
for(i=0;i<16;i++) {
|
||||||
|
printf("%2x%s ",*((unsigned char*)(a+i)),i%4==3?" ":"");
|
||||||
|
}
|
||||||
|
// character representation
|
||||||
|
for(i=0;i<16;i++) {
|
||||||
|
c=*((unsigned char*)(a+i));
|
||||||
|
printf("%c",c<32||c>=127?'.':c);
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
} else {
|
||||||
|
printf("ERROR: unknown command.\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
dbg_running--;
|
||||||
|
}
|
@ -0,0 +1,26 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2018 bzt (bztsrc@github)
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person
|
||||||
|
* obtaining a copy of this software and associated documentation
|
||||||
|
* files (the "Software"), to deal in the Software without
|
||||||
|
* restriction, including without limitation the rights to use, copy,
|
||||||
|
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||||
|
* of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be
|
||||||
|
* included in all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||||
|
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||||
|
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
|
* DEALINGS IN THE SOFTWARE.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define breakpoint asm volatile("brk #0")
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,45 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2018 bzt (bztsrc@github)
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person
|
||||||
|
* obtaining a copy of this software and associated documentation
|
||||||
|
* files (the "Software"), to deal in the Software without
|
||||||
|
* restriction, including without limitation the rights to use, copy,
|
||||||
|
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||||
|
* of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be
|
||||||
|
* included in all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||||
|
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||||
|
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
|
* DEALINGS IN THE SOFTWARE.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define MMIO_BASE 0x3F000000
|
||||||
|
|
||||||
|
#define GPFSEL0 ((volatile unsigned int*)(MMIO_BASE+0x00200000))
|
||||||
|
#define GPFSEL1 ((volatile unsigned int*)(MMIO_BASE+0x00200004))
|
||||||
|
#define GPFSEL2 ((volatile unsigned int*)(MMIO_BASE+0x00200008))
|
||||||
|
#define GPFSEL3 ((volatile unsigned int*)(MMIO_BASE+0x0020000C))
|
||||||
|
#define GPFSEL4 ((volatile unsigned int*)(MMIO_BASE+0x00200010))
|
||||||
|
#define GPFSEL5 ((volatile unsigned int*)(MMIO_BASE+0x00200014))
|
||||||
|
#define GPSET0 ((volatile unsigned int*)(MMIO_BASE+0x0020001C))
|
||||||
|
#define GPSET1 ((volatile unsigned int*)(MMIO_BASE+0x00200020))
|
||||||
|
#define GPCLR0 ((volatile unsigned int*)(MMIO_BASE+0x00200028))
|
||||||
|
#define GPLEV0 ((volatile unsigned int*)(MMIO_BASE+0x00200034))
|
||||||
|
#define GPLEV1 ((volatile unsigned int*)(MMIO_BASE+0x00200038))
|
||||||
|
#define GPEDS0 ((volatile unsigned int*)(MMIO_BASE+0x00200040))
|
||||||
|
#define GPEDS1 ((volatile unsigned int*)(MMIO_BASE+0x00200044))
|
||||||
|
#define GPHEN0 ((volatile unsigned int*)(MMIO_BASE+0x00200064))
|
||||||
|
#define GPHEN1 ((volatile unsigned int*)(MMIO_BASE+0x00200068))
|
||||||
|
#define GPPUD ((volatile unsigned int*)(MMIO_BASE+0x00200094))
|
||||||
|
#define GPPUDCLK0 ((volatile unsigned int*)(MMIO_BASE+0x00200098))
|
||||||
|
#define GPPUDCLK1 ((volatile unsigned int*)(MMIO_BASE+0x0020009C))
|
Binary file not shown.
@ -0,0 +1,44 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2018 bzt (bztsrc@github)
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person
|
||||||
|
* obtaining a copy of this software and associated documentation
|
||||||
|
* files (the "Software"), to deal in the Software without
|
||||||
|
* restriction, including without limitation the rights to use, copy,
|
||||||
|
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||||
|
* of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be
|
||||||
|
* included in all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||||
|
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||||
|
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
|
* DEALINGS IN THE SOFTWARE.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
SECTIONS
|
||||||
|
{
|
||||||
|
. = 0x80000;
|
||||||
|
.text : { KEEP(*(.text.boot)) *(.text .text.* .gnu.linkonce.t*) }
|
||||||
|
.rodata : { *(.rodata .rodata.* .gnu.linkonce.r*) }
|
||||||
|
PROVIDE(_data = .);
|
||||||
|
.data : { *(.data .data.* .gnu.linkonce.d*) }
|
||||||
|
.bss (NOLOAD) : {
|
||||||
|
. = ALIGN(16);
|
||||||
|
__bss_start = .;
|
||||||
|
*(.bss .bss.*)
|
||||||
|
*(COMMON)
|
||||||
|
__bss_end = .;
|
||||||
|
}
|
||||||
|
_end = .;
|
||||||
|
|
||||||
|
/DISCARD/ : { *(.comment) *(.gnu*) *(.note*) *(.eh_frame*) }
|
||||||
|
}
|
||||||
|
__bss_size = (__bss_end - __bss_start)>>3;
|
@ -0,0 +1,41 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2018 bzt (bztsrc@github)
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person
|
||||||
|
* obtaining a copy of this software and associated documentation
|
||||||
|
* files (the "Software"), to deal in the Software without
|
||||||
|
* restriction, including without limitation the rights to use, copy,
|
||||||
|
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||||
|
* of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be
|
||||||
|
* included in all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||||
|
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||||
|
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
|
* DEALINGS IN THE SOFTWARE.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "uart.h"
|
||||||
|
#include "dbg.h"
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
// set up serial console
|
||||||
|
uart_init();
|
||||||
|
|
||||||
|
// test our debugger
|
||||||
|
breakpoint;
|
||||||
|
|
||||||
|
// echo everything back
|
||||||
|
while(1) {
|
||||||
|
uart_send(uart_getc());
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,63 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2018 bzt (bztsrc@github)
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person
|
||||||
|
* obtaining a copy of this software and associated documentation
|
||||||
|
* files (the "Software"), to deal in the Software without
|
||||||
|
* restriction, including without limitation the rights to use, copy,
|
||||||
|
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||||
|
* of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be
|
||||||
|
* included in all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||||
|
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||||
|
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
|
* DEALINGS IN THE SOFTWARE.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "gpio.h"
|
||||||
|
|
||||||
|
/* mailbox 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
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Make a mailbox call. Returns 0 on failure, non-zero on success
|
||||||
|
*/
|
||||||
|
int mbox_call(unsigned char ch)
|
||||||
|
{
|
||||||
|
unsigned int r;
|
||||||
|
/* wait until we can write to the mailbox */
|
||||||
|
do{asm volatile("nop");}while(*MBOX_STATUS & MBOX_FULL);
|
||||||
|
/* write the address of our message to the mailbox with channel identifier */
|
||||||
|
*MBOX_WRITE = (((unsigned int)((unsigned long)&mbox)&~0xF) | (ch&0xF));
|
||||||
|
/* now wait for the response */
|
||||||
|
while(1) {
|
||||||
|
/* is there a response? */
|
||||||
|
do{asm volatile("nop");}while(*MBOX_STATUS & MBOX_EMPTY);
|
||||||
|
r=*MBOX_READ;
|
||||||
|
/* is it a response to our message? */
|
||||||
|
if((unsigned char)(r&0xF)==ch && (r&~0xF)==(unsigned int)((unsigned long)&mbox))
|
||||||
|
/* is it a valid successful response? */
|
||||||
|
return mbox[1]==MBOX_RESPONSE;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
@ -0,0 +1,47 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2018 bzt (bztsrc@github)
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person
|
||||||
|
* obtaining a copy of this software and associated documentation
|
||||||
|
* files (the "Software"), to deal in the Software without
|
||||||
|
* restriction, including without limitation the rights to use, copy,
|
||||||
|
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||||
|
* of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be
|
||||||
|
* included in all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||||
|
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||||
|
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
|
* DEALINGS IN THE SOFTWARE.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* a properly aligned buffer */
|
||||||
|
extern volatile unsigned int mbox[36];
|
||||||
|
|
||||||
|
#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_GETSERIAL 0x10004
|
||||||
|
#define MBOX_TAG_SETCLKRATE 0x38002
|
||||||
|
#define MBOX_TAG_LAST 0
|
||||||
|
|
||||||
|
int mbox_call(unsigned char ch);
|
@ -0,0 +1,148 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2018 bzt (bztsrc@github)
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person
|
||||||
|
* obtaining a copy of this software and associated documentation
|
||||||
|
* files (the "Software"), to deal in the Software without
|
||||||
|
* restriction, including without limitation the rights to use, copy,
|
||||||
|
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||||
|
* of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be
|
||||||
|
* included in all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||||
|
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||||
|
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
|
* DEALINGS IN THE SOFTWARE.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* minimal sprintf implementation
|
||||||
|
*/
|
||||||
|
unsigned int vsprintf(char *dst, char* fmt, __builtin_va_list args)
|
||||||
|
{
|
||||||
|
long int arg;
|
||||||
|
int len, sign, i;
|
||||||
|
char *p, *orig=dst, tmpstr[19];
|
||||||
|
|
||||||
|
// failsafes
|
||||||
|
if(dst==(void*)0 || fmt==(void*)0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// main loop
|
||||||
|
arg = 0;
|
||||||
|
while(*fmt) {
|
||||||
|
// argument access
|
||||||
|
if(*fmt=='%') {
|
||||||
|
fmt++;
|
||||||
|
// literal %
|
||||||
|
if(*fmt=='%') {
|
||||||
|
goto put;
|
||||||
|
}
|
||||||
|
len=0;
|
||||||
|
// size modifier
|
||||||
|
while(*fmt>='0' && *fmt<='9') {
|
||||||
|
len *= 10;
|
||||||
|
len += *fmt-'0';
|
||||||
|
fmt++;
|
||||||
|
}
|
||||||
|
// skip long modifier
|
||||||
|
if(*fmt=='l') {
|
||||||
|
fmt++;
|
||||||
|
}
|
||||||
|
// character
|
||||||
|
if(*fmt=='c') {
|
||||||
|
arg = __builtin_va_arg(args, int);
|
||||||
|
*dst++ = (char)arg;
|
||||||
|
fmt++;
|
||||||
|
continue;
|
||||||
|
} else
|
||||||
|
// decimal number
|
||||||
|
if(*fmt=='d') {
|
||||||
|
arg = __builtin_va_arg(args, int);
|
||||||
|
// check input
|
||||||
|
sign=0;
|
||||||
|
if((int)arg<0) {
|
||||||
|
arg*=-1;
|
||||||
|
sign++;
|
||||||
|
}
|
||||||
|
if(arg>99999999999999999L) {
|
||||||
|
arg=99999999999999999L;
|
||||||
|
}
|
||||||
|
// convert to string
|
||||||
|
i=18;
|
||||||
|
tmpstr[i]=0;
|
||||||
|
do {
|
||||||
|
tmpstr[--i]='0'+(arg%10);
|
||||||
|
arg/=10;
|
||||||
|
} while(arg!=0 && i>0);
|
||||||
|
if(sign) {
|
||||||
|
tmpstr[--i]='-';
|
||||||
|
}
|
||||||
|
// padding, only space
|
||||||
|
if(len>0 && len<18) {
|
||||||
|
while(i>18-len) {
|
||||||
|
tmpstr[--i]=' ';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
p=&tmpstr[i];
|
||||||
|
goto copystring;
|
||||||
|
} else
|
||||||
|
// hex number
|
||||||
|
if(*fmt=='x') {
|
||||||
|
arg = __builtin_va_arg(args, long int);
|
||||||
|
// convert to string
|
||||||
|
i=16;
|
||||||
|
tmpstr[i]=0;
|
||||||
|
do {
|
||||||
|
char n=arg & 0xf;
|
||||||
|
// 0-9 => '0'-'9', 10-15 => 'A'-'F'
|
||||||
|
tmpstr[--i]=n+(n>9?0x37:0x30);
|
||||||
|
arg>>=4;
|
||||||
|
} while(arg!=0 && i>0);
|
||||||
|
// padding, only leading zeros
|
||||||
|
if(len>0 && len<=16) {
|
||||||
|
while(i>16-len) {
|
||||||
|
tmpstr[--i]='0';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
p=&tmpstr[i];
|
||||||
|
goto copystring;
|
||||||
|
} else
|
||||||
|
// string
|
||||||
|
if(*fmt=='s') {
|
||||||
|
p = __builtin_va_arg(args, char*);
|
||||||
|
copystring: if(p==(void*)0) {
|
||||||
|
p="(null)";
|
||||||
|
}
|
||||||
|
while(*p) {
|
||||||
|
*dst++ = *p++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
put: *dst++ = *fmt;
|
||||||
|
}
|
||||||
|
fmt++;
|
||||||
|
}
|
||||||
|
*dst=0;
|
||||||
|
// number of bytes written
|
||||||
|
return dst-orig;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Variable length arguments
|
||||||
|
*/
|
||||||
|
unsigned int sprintf(char *dst, char* fmt, ...)
|
||||||
|
{
|
||||||
|
__builtin_va_list args;
|
||||||
|
__builtin_va_start(args, fmt);
|
||||||
|
return vsprintf(dst,fmt,args);
|
||||||
|
}
|
@ -0,0 +1,27 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2018 bzt (bztsrc@github)
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person
|
||||||
|
* obtaining a copy of this software and associated documentation
|
||||||
|
* files (the "Software"), to deal in the Software without
|
||||||
|
* restriction, including without limitation the rights to use, copy,
|
||||||
|
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||||
|
* of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be
|
||||||
|
* included in all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||||
|
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||||
|
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
|
* DEALINGS IN THE SOFTWARE.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
unsigned int sprintf(char *dst, char* fmt, ...);
|
||||||
|
unsigned int vsprintf(char *dst,char* fmt, __builtin_va_list args);
|
@ -0,0 +1,201 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2018 bzt (bztsrc@github)
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person
|
||||||
|
* obtaining a copy of this software and associated documentation
|
||||||
|
* files (the "Software"), to deal in the Software without
|
||||||
|
* restriction, including without limitation the rights to use, copy,
|
||||||
|
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||||
|
* of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be
|
||||||
|
* included in all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||||
|
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||||
|
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
|
* DEALINGS IN THE SOFTWARE.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
.section ".text.boot"
|
||||||
|
|
||||||
|
.global _start
|
||||||
|
|
||||||
|
_start:
|
||||||
|
// read cpu id, stop slave cores
|
||||||
|
mrs x1, mpidr_el1
|
||||||
|
and x1, x1, #3
|
||||||
|
cbz x1, 2f
|
||||||
|
// cpu id > 0, stop
|
||||||
|
1: wfe
|
||||||
|
b 1b
|
||||||
|
2: // cpu id == 0
|
||||||
|
|
||||||
|
// set stack before our code
|
||||||
|
ldr x1, =_start
|
||||||
|
|
||||||
|
// set up EL1
|
||||||
|
mrs x0, CurrentEL
|
||||||
|
and x0, x0, #12 // clear reserved bits
|
||||||
|
|
||||||
|
// running at EL3?
|
||||||
|
cmp x0, #12
|
||||||
|
bne 5f
|
||||||
|
// should never be executed, just for completeness
|
||||||
|
mov x2, #0x5b1
|
||||||
|
msr scr_el3, x2
|
||||||
|
mov x2, #0x3c9
|
||||||
|
msr spsr_el3, x2
|
||||||
|
adr x2, 5f
|
||||||
|
msr elr_el3, x2
|
||||||
|
eret
|
||||||
|
|
||||||
|
// running at EL2?
|
||||||
|
5: cmp x0, #4
|
||||||
|
beq 5f
|
||||||
|
msr sp_el1, x1
|
||||||
|
// enable CNTP for EL1
|
||||||
|
mrs x0, cnthctl_el2
|
||||||
|
orr x0, x0, #3
|
||||||
|
msr cnthctl_el2, x0
|
||||||
|
msr cntvoff_el2, xzr
|
||||||
|
// disable coprocessor traps
|
||||||
|
mov x0, #0x33FF
|
||||||
|
msr cptr_el2, x0
|
||||||
|
msr hstr_el2, xzr
|
||||||
|
mov x0, #(3 << 20)
|
||||||
|
msr cpacr_el1, x0
|
||||||
|
// enable AArch64 in EL1
|
||||||
|
mov x0, #(1 << 31) // AArch64
|
||||||
|
orr x0, x0, #(1 << 1) // SWIO hardwired on Pi3
|
||||||
|
msr hcr_el2, x0
|
||||||
|
mrs x0, hcr_el2
|
||||||
|
// Setup SCTLR access
|
||||||
|
mov x2, #0x0800
|
||||||
|
movk x2, #0x30d0, lsl #16
|
||||||
|
msr sctlr_el1, x2
|
||||||
|
// set up exception handlers
|
||||||
|
ldr x2, =_vectors
|
||||||
|
msr vbar_el1, x2
|
||||||
|
// change execution level to EL1
|
||||||
|
mov x2, #0x3c4
|
||||||
|
msr spsr_el2, x2
|
||||||
|
adr x2, 5f
|
||||||
|
msr elr_el2, x2
|
||||||
|
// clear EL1 system registers
|
||||||
|
msr elr_el1, xzr
|
||||||
|
msr far_el1, xzr
|
||||||
|
eret
|
||||||
|
|
||||||
|
5: mov sp, x1
|
||||||
|
|
||||||
|
// clear bss
|
||||||
|
ldr x1, =__bss_start
|
||||||
|
ldr w2, =__bss_size
|
||||||
|
3: cbz w2, 4f
|
||||||
|
str xzr, [x1], #8
|
||||||
|
sub w2, w2, #1
|
||||||
|
cbnz w2, 3b
|
||||||
|
|
||||||
|
// jump to C code, should not return
|
||||||
|
4: bl main
|
||||||
|
// for failsafe, halt this core too
|
||||||
|
b 1b
|
||||||
|
|
||||||
|
// save registers before we call any C code
|
||||||
|
dbg_saveregs:
|
||||||
|
str x0, [sp, #-16]! // push x0
|
||||||
|
ldr x0, =dbg_regs+8
|
||||||
|
str x1, [x0], #8 // dbg_regs[1]=x1
|
||||||
|
ldr x1, [sp, #16] // pop x1
|
||||||
|
str x1, [x0, #-16]! // dbg_regs[0]=x1 (x0)
|
||||||
|
add x0, x0, #16
|
||||||
|
str x2, [x0], #8 // dbg_regs[2]=x2
|
||||||
|
str x3, [x0], #8 // ...etc.
|
||||||
|
str x4, [x0], #8
|
||||||
|
str x5, [x0], #8
|
||||||
|
str x6, [x0], #8
|
||||||
|
str x7, [x0], #8
|
||||||
|
str x8, [x0], #8
|
||||||
|
str x9, [x0], #8
|
||||||
|
str x10, [x0], #8
|
||||||
|
str x11, [x0], #8
|
||||||
|
str x12, [x0], #8
|
||||||
|
str x13, [x0], #8
|
||||||
|
str x14, [x0], #8
|
||||||
|
str x15, [x0], #8
|
||||||
|
str x16, [x0], #8
|
||||||
|
str x17, [x0], #8
|
||||||
|
str x18, [x0], #8
|
||||||
|
str x19, [x0], #8
|
||||||
|
str x20, [x0], #8
|
||||||
|
str x21, [x0], #8
|
||||||
|
str x22, [x0], #8
|
||||||
|
str x23, [x0], #8
|
||||||
|
str x24, [x0], #8
|
||||||
|
str x25, [x0], #8
|
||||||
|
str x26, [x0], #8
|
||||||
|
str x27, [x0], #8
|
||||||
|
str x28, [x0], #8
|
||||||
|
str x29, [x0], #8
|
||||||
|
ldr x1, [sp, #16] // pop x30
|
||||||
|
str x1, [x0], #8
|
||||||
|
// also read and store some system registers
|
||||||
|
mrs x1, elr_el1
|
||||||
|
str x1, [x0], #8
|
||||||
|
mrs x1, spsr_el1
|
||||||
|
str x1, [x0], #8
|
||||||
|
mrs x1, esr_el1
|
||||||
|
str x1, [x0], #8
|
||||||
|
mrs x1, far_el1
|
||||||
|
str x1, [x0], #8
|
||||||
|
mrs x1, sctlr_el1
|
||||||
|
str x1, [x0], #8
|
||||||
|
mrs x1, tcr_el1
|
||||||
|
str x1, [x0], #8
|
||||||
|
ret
|
||||||
|
|
||||||
|
// important, code has to be properly aligned
|
||||||
|
.align 11
|
||||||
|
_vectors:
|
||||||
|
// synchronous
|
||||||
|
.align 7
|
||||||
|
str x30, [sp, #-16]! // push x30
|
||||||
|
bl dbg_saveregs
|
||||||
|
mov x0, #0
|
||||||
|
bl dbg_decodeexc
|
||||||
|
bl dbg_main
|
||||||
|
eret
|
||||||
|
|
||||||
|
// IRQ
|
||||||
|
.align 7
|
||||||
|
str x30, [sp, #-16]! // push x30
|
||||||
|
bl dbg_saveregs
|
||||||
|
mov x0, #1
|
||||||
|
bl dbg_decodeexc
|
||||||
|
bl dbg_main
|
||||||
|
eret
|
||||||
|
|
||||||
|
// FIQ
|
||||||
|
.align 7
|
||||||
|
str x30, [sp, #-16]! // push x30
|
||||||
|
bl dbg_saveregs
|
||||||
|
mov x0, #2
|
||||||
|
bl dbg_decodeexc
|
||||||
|
bl dbg_main
|
||||||
|
eret
|
||||||
|
|
||||||
|
// SError
|
||||||
|
.align 7
|
||||||
|
str x30, [sp, #-16]! // push x30
|
||||||
|
bl dbg_saveregs
|
||||||
|
mov x0, #3
|
||||||
|
bl dbg_decodeexc
|
||||||
|
bl dbg_main
|
||||||
|
eret
|
@ -0,0 +1,123 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2018 bzt (bztsrc@github)
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person
|
||||||
|
* obtaining a copy of this software and associated documentation
|
||||||
|
* files (the "Software"), to deal in the Software without
|
||||||
|
* restriction, including without limitation the rights to use, copy,
|
||||||
|
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||||
|
* of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be
|
||||||
|
* included in all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||||
|
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||||
|
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
|
* DEALINGS IN THE SOFTWARE.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "gpio.h"
|
||||||
|
#include "mbox.h"
|
||||||
|
#include "sprintf.h"
|
||||||
|
|
||||||
|
/* PL011 UART registers */
|
||||||
|
#define UART0_DR ((volatile unsigned int*)(MMIO_BASE+0x00201000))
|
||||||
|
#define UART0_FR ((volatile unsigned int*)(MMIO_BASE+0x00201018))
|
||||||
|
#define UART0_IBRD ((volatile unsigned int*)(MMIO_BASE+0x00201024))
|
||||||
|
#define UART0_FBRD ((volatile unsigned int*)(MMIO_BASE+0x00201028))
|
||||||
|
#define UART0_LCRH ((volatile unsigned int*)(MMIO_BASE+0x0020102C))
|
||||||
|
#define UART0_CR ((volatile unsigned int*)(MMIO_BASE+0x00201030))
|
||||||
|
#define UART0_IMSC ((volatile unsigned int*)(MMIO_BASE+0x00201038))
|
||||||
|
#define UART0_ICR ((volatile unsigned int*)(MMIO_BASE+0x00201044))
|
||||||
|
|
||||||
|
// get address from linker
|
||||||
|
extern volatile unsigned char _end;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set baud rate and characteristics (115200 8N1) and map to GPIO
|
||||||
|
*/
|
||||||
|
void uart_init()
|
||||||
|
{
|
||||||
|
register unsigned int r;
|
||||||
|
|
||||||
|
/* initialize UART */
|
||||||
|
*UART0_CR = 0; // turn off UART0
|
||||||
|
|
||||||
|
/* set up clock for consistent divisor values */
|
||||||
|
mbox[0] = 8*4;
|
||||||
|
mbox[1] = MBOX_REQUEST;
|
||||||
|
mbox[2] = MBOX_TAG_SETCLKRATE; // set clock rate
|
||||||
|
mbox[3] = 12;
|
||||||
|
mbox[4] = 8;
|
||||||
|
mbox[5] = 2; // UART clock
|
||||||
|
mbox[6] = 4000000; // 4Mhz
|
||||||
|
mbox[7] = MBOX_TAG_LAST;
|
||||||
|
mbox_call(MBOX_CH_PROP);
|
||||||
|
|
||||||
|
/* map UART0 to GPIO pins */
|
||||||
|
r=*GPFSEL1;
|
||||||
|
r&=~((7<<12)|(7<<15)); // gpio14, gpio15
|
||||||
|
r|=(4<<12)|(4<<15); // alt0
|
||||||
|
*GPFSEL1 = r;
|
||||||
|
*GPPUD = 0; // enable pins 14 and 15
|
||||||
|
r=150; while(r--) { asm volatile("nop"); }
|
||||||
|
*GPPUDCLK0 = (1<<14)|(1<<15);
|
||||||
|
r=150; while(r--) { asm volatile("nop"); }
|
||||||
|
*GPPUDCLK0 = 0; // flush GPIO setup
|
||||||
|
|
||||||
|
*UART0_ICR = 0x7FF; // clear interrupts
|
||||||
|
*UART0_IBRD = 2; // 115200 baud
|
||||||
|
*UART0_FBRD = 0xB;
|
||||||
|
*UART0_LCRH = 0b11<<5; // 8n1
|
||||||
|
*UART0_CR = 0x301; // enable Tx, Rx, FIFO
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send a character
|
||||||
|
*/
|
||||||
|
void uart_send(unsigned int c) {
|
||||||
|
/* wait until we can send */
|
||||||
|
do{asm volatile("nop");}while(*UART0_FR&0x20);
|
||||||
|
/* write the character to the buffer */
|
||||||
|
*UART0_DR=c;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Receive a character
|
||||||
|
*/
|
||||||
|
char uart_getc() {
|
||||||
|
char r;
|
||||||
|
/* wait until something is in the buffer */
|
||||||
|
do{asm volatile("nop");}while(*UART0_FR&0x10);
|
||||||
|
/* read it and return */
|
||||||
|
r=(char)(*UART0_DR);
|
||||||
|
/* convert carrige return to newline */
|
||||||
|
return r=='\r'?'\n':r;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Display a string
|
||||||
|
*/
|
||||||
|
void printf(char *fmt, ...) {
|
||||||
|
__builtin_va_list args;
|
||||||
|
__builtin_va_start(args, fmt);
|
||||||
|
// we don't have memory allocation yet, so we
|
||||||
|
// simply place our string after our code
|
||||||
|
char *s = (char*)&_end;
|
||||||
|
// use sprintf to format our string
|
||||||
|
vsprintf(s,fmt,args);
|
||||||
|
// print out as usual
|
||||||
|
while(*s) {
|
||||||
|
/* convert newline to carrige return + newline */
|
||||||
|
if(*s=='\n')
|
||||||
|
uart_send('\r');
|
||||||
|
uart_send(*s++);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,29 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2018 bzt (bztsrc@github)
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person
|
||||||
|
* obtaining a copy of this software and associated documentation
|
||||||
|
* files (the "Software"), to deal in the Software without
|
||||||
|
* restriction, including without limitation the rights to use, copy,
|
||||||
|
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||||
|
* of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be
|
||||||
|
* included in all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||||
|
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||||
|
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
|
* DEALINGS IN THE SOFTWARE.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
void uart_init();
|
||||||
|
void uart_send(unsigned int c);
|
||||||
|
char uart_getc();
|
||||||
|
void printf(char *fmt, ...);
|
Loading…
Reference in New Issue