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