New tutorials

pull/4/head
bzt 6 years ago
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…
Cancel
Save