Fixed typos and more tutorials
parent
158e9ea522
commit
ed7cb505f9
@ -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.
|
||||
#
|
||||
#
|
||||
|
||||
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 $@
|
||||
|
||||
tar.o:
|
||||
tar -cf initrd.tar *.md *.c *.h
|
||||
aarch64-elf-ld -r -b binary -o tar.o initrd.tar
|
||||
|
||||
kernel8.img: start.o tar.o $(OBJS)
|
||||
aarch64-elf-ld -nostdlib -nostartfiles start.o tar.o $(OBJS) -T link.ld -o kernel8.elf
|
||||
aarch64-elf-objcopy -O binary kernel8.elf kernel8.img
|
||||
|
||||
clean:
|
||||
rm kernel8.elf *.o *.tar >/dev/null 2>/dev/null || true
|
@ -0,0 +1,49 @@
|
||||
Tutorial 0E - Kezdeti memória lemez
|
||||
===================================
|
||||
|
||||
Sok OS használ kezdeti memória lemezt (initrd) hogy fájlokat töltsön be induláskor. Szükségét éreztem egy
|
||||
ilyen oktatóanyagnak, mivel a legtöbb hobby OS fejlesztőnek fingja sincs, hogy kell ezt rendesen csinálni.
|
||||
|
||||
Először is, nem fogjuk újra feltalálni a spanyol viaszt és kiagyalni egy új formátumot, amihez aztán egy
|
||||
szörnyű kreátor programot heggesztünk. Helyette a POSIX szabvány `tar` archíválót fogjuk használni. A formátuma
|
||||
pofonegyszerű, először jön egy 512 bájtos fejléc a fájl adataival, majd ezt követi a fájl tartalma nullákkal
|
||||
kiegészítve, hogy a hossza 512-vel osztható legyen. Ez ismétlődik minden egyes fájlra az archívban.
|
||||
Ha szeretnél tömörített initrd-t, akkor javaslom például a [tinf](https://bitbucket.org/jibsen/tinf) könyvtárat
|
||||
a kicsomagoláshoz. A kitömörített adatot az itt ismertetett módszerrel olvashatod.
|
||||
|
||||
Másodszor, a betöltéshez több lehetőségünk is van:
|
||||
|
||||
### Betöltjük a fájlt saját magunk
|
||||
Ehhez használhatod a `fat_readfile()` funkciót az előző oktatóanyagból. Ebben az esetben az initrd címét visszaadja
|
||||
a függvény.
|
||||
|
||||
### Megkéred a GPU-t hogy töltse be neked
|
||||
Aztán használhatod a `config.txt`-t hogy utasítsd a start.elf-et az initrd betöltésére. Ez azért jó, mert ehhez
|
||||
nem kell SD kártya olvasó és FAT értelmező, így a kerneled jóval kissebb lesz. Ami a
|
||||
[config.txt](https://www.raspberry.org/documentation/configuration/config-txt/boot.md) parancsait illeti,
|
||||
két lehetőséged is van:
|
||||
|
||||
`initramfs (fájlnév) followkernel` - ez betölti a (fájlnév) nevű fájlt mindjárt a kerneled után. Az initrd-d kezdőcíme
|
||||
ekkor a *&_end* cimke lesz, amit a linker szkriptben definiáltunk.
|
||||
|
||||
`initramfs (fájlnév) (cím)` - a megadott címre tölti be a (fájlnév) nevű fájlt. A kezdőcíme ekkor *(cím)* lesz.
|
||||
|
||||
### Statikus linkelés
|
||||
Nem túl praktikus, mivel mindig újra kell fordítani a kernelt, ha változtatni akarsz az initrd tartalmán. Azonban
|
||||
ez a legegyszerűbb módszer, és hogy átlátható legyen az oktatóanyag, ezért ezt választottam. Az initrd-d kezdőcímét
|
||||
ez esetben a *_binary_initrd_tar_start* cimke szolgáltatja.
|
||||
|
||||
Makefile
|
||||
--------
|
||||
Hozzáadtam egy tar.o létrehozó szabályt a Makefile-hoz. Ez dinamikusan legenerálja a tar-t, majd object fájllá
|
||||
konvertálja.
|
||||
|
||||
Initrd.h, initrd.c
|
||||
------------------
|
||||
|
||||
`initrd_list(buf)` kilistázza a bufferben lévő tar archív tartalmát.
|
||||
|
||||
Main
|
||||
----
|
||||
|
||||
Inicializáljuk a konzolt, majd átadjuk az initrd kezdőcímét a listázónak.
|
@ -0,0 +1,49 @@
|
||||
Tutorial 0E - Initial RamDisk
|
||||
=============================
|
||||
|
||||
Many OS uses initial ramdisk to load files into memory during boot. I felt the need for such
|
||||
a tutorial as most hobby OS developer's never learned how to do this porperly.
|
||||
|
||||
First of all, we're not going to reinvent the wheel a come up with a new format and an awful
|
||||
image creator tool. We're going to use the POSIX standard `tar` utility to create our initrd. It's format
|
||||
is really simple, first comes an 512 bytes long header with file meta information, followed by the
|
||||
file contents padded with zeros to round up to multiple of 512 bytes. This repeats for every file in the archive.
|
||||
If you want a compressed initrd, you can use for example the [tinf](https://bitbucket.org/jibsen/tinf) library to
|
||||
deflate. The uncompressed buffer can be parsed by the method described here.
|
||||
|
||||
Second, about loading it into memory, we have several options:
|
||||
|
||||
### Load a file on our own
|
||||
You can use the `fat_readfile()` from the previous tutorial. In that case your initrd's address
|
||||
will be returned by the function.
|
||||
|
||||
### Ask the GPU to do so
|
||||
You can use `config.txt` to tell start.elf to load the initrd for you. With this you won't need
|
||||
any SD card reader or FAT parser at all, resulting in a much smaller kernel. As for the
|
||||
[config.txt](https://www.raspberry.org/documentation/configuration/config-txt/boot.md),
|
||||
you have two options:
|
||||
|
||||
`initramfs (filename) followkernel` - this will load (filename) after your kernel. You can access it at the label
|
||||
*&_end* defined by our linker script.
|
||||
|
||||
`initramfs (filename) (address)` - load (filename) into a specified location. You can access it at *(address)*.
|
||||
|
||||
### Statically link
|
||||
This is not very practical because you have to build your kernel every time you want to change the initrd. But
|
||||
it is the simplest method, and to keep this tutorial simple we'll use this. You can access the initrd by the label
|
||||
*_binary_initrd_tar_start*.
|
||||
|
||||
Makefile
|
||||
--------
|
||||
I've added a tar.o to the usual Makefile. This rule will dinamically create a tar file and convert it into an
|
||||
object file.
|
||||
|
||||
Initrd.h, initrd.c
|
||||
------------------
|
||||
|
||||
`initrd_list(buf)` list the contents of a tar archive in the buffer.
|
||||
|
||||
Main
|
||||
----
|
||||
|
||||
We initialize console and the pass the initrd buffer to lister.
|
@ -0,0 +1,81 @@
|
||||
/*
|
||||
* 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"
|
||||
|
||||
#define SYSTMR_LO ((volatile unsigned int*)(MMIO_BASE+0x00003004))
|
||||
#define SYSTMR_HI ((volatile unsigned int*)(MMIO_BASE+0x00003008))
|
||||
|
||||
/**
|
||||
* Wait N CPU cycles (ARM CPU only)
|
||||
*/
|
||||
void wait_cycles(unsigned int n)
|
||||
{
|
||||
if(n) while(n--) { asm volatile("nop"); }
|
||||
}
|
||||
|
||||
/**
|
||||
* Wait N microsec (ARM CPU only)
|
||||
*/
|
||||
void wait_msec(unsigned int n)
|
||||
{
|
||||
register unsigned long f, t, r;
|
||||
// get the current counter frequency
|
||||
asm volatile ("mrs %0, cntfrq_el0" : "=r"(f));
|
||||
// read the current counter
|
||||
asm volatile ("mrs %0, cntpct_el0" : "=r"(t));
|
||||
// calculate expire value for counter
|
||||
t+=((f/1000)*n)/1000;
|
||||
do{asm volatile ("mrs %0, cntpct_el0" : "=r"(r));}while(r<t);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get System Timer's counter
|
||||
*/
|
||||
unsigned long get_system_timer()
|
||||
{
|
||||
unsigned int h=-1, l;
|
||||
// we must read MMIO area as two separate 32 bit reads
|
||||
h=*SYSTMR_HI;
|
||||
l=*SYSTMR_LO;
|
||||
// we have to repeat it if high word changed during read
|
||||
if(h!=*SYSTMR_HI) {
|
||||
h=*SYSTMR_HI;
|
||||
l=*SYSTMR_LO;
|
||||
}
|
||||
// compose long int value
|
||||
return ((unsigned long) h << 32) | l;
|
||||
}
|
||||
|
||||
/**
|
||||
* Wait N microsec (with BCM System Timer)
|
||||
*/
|
||||
void wait_msec_st(unsigned int n)
|
||||
{
|
||||
unsigned long t=get_system_timer();
|
||||
// we must check if it's non-zero, because qemu does not emulate
|
||||
// system timer, and returning constant zero would mean infinite loop
|
||||
if(t) while(get_system_timer() < t+n);
|
||||
}
|
@ -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 wait_cycles(unsigned int n);
|
||||
void wait_msec(unsigned int n);
|
||||
unsigned long get_system_timer();
|
||||
void wait_msec_st(unsigned int n);
|
@ -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))
|
@ -0,0 +1,68 @@
|
||||
/*
|
||||
* 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"
|
||||
|
||||
/**
|
||||
* Helper function to convert ASCII octal number into binary
|
||||
* s string
|
||||
* n number of digits
|
||||
*/
|
||||
int oct2bin(char *s, int n)
|
||||
{
|
||||
int r=0;
|
||||
while(n-->0) {
|
||||
r<<=3;
|
||||
r+=*s++-'0';
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
/**
|
||||
* List the contents of a tar archive
|
||||
*/
|
||||
void initrd_list(char *buf)
|
||||
{
|
||||
uart_puts("Offset Size Access rights\t\tFilename\n");
|
||||
// iterate on archive's contents
|
||||
while(!__builtin_memcmp(buf+257,"ustar",5)){
|
||||
int fs=oct2bin(buf+0x7c,11);
|
||||
// print out meta information
|
||||
uart_hex((unsigned int)((unsigned long)buf)+512);
|
||||
uart_send(' ');
|
||||
uart_hex(fs); // file size in hex
|
||||
uart_send(' ');
|
||||
uart_puts(buf+0x64); // access bits in octal
|
||||
uart_send(' ');
|
||||
uart_puts(buf+0x109); // owner
|
||||
uart_send('.');
|
||||
uart_puts(buf+0x129); // group
|
||||
uart_send('\t');
|
||||
uart_puts(buf); // filename
|
||||
uart_puts("\n");
|
||||
// jump to the next file
|
||||
buf+=(((fs+511)/512)+1)*512;
|
||||
}
|
||||
}
|
@ -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.
|
||||
*
|
||||
*/
|
||||
|
||||
void initrd_list(char *buf);
|
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,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.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "uart.h"
|
||||
#include "initrd.h"
|
||||
|
||||
// import our bitchunk from tar.o
|
||||
extern volatile unsigned char _binary_initrd_tar_start;
|
||||
|
||||
void main()
|
||||
{
|
||||
// set up serial console
|
||||
uart_init();
|
||||
|
||||
// list contents of an archive
|
||||
initrd_list((char*)&_binary_initrd_tar_start);
|
||||
|
||||
// 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_SETPOWER 0x28001
|
||||
#define MBOX_TAG_SETCLKRATE 0x38002
|
||||
#define MBOX_TAG_LAST 0
|
||||
|
||||
int mbox_call(unsigned char ch);
|
@ -0,0 +1,55 @@
|
||||
/*
|
||||
* 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
|
||||
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
|
@ -0,0 +1,153 @@
|
||||
/*
|
||||
* 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 "delays.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))
|
||||
|
||||
/**
|
||||
* 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|=(2<<12)|(2<<15); // alt5
|
||||
*GPFSEL1 = r;
|
||||
*GPPUD = 0; // enable pins 14 and 15
|
||||
wait_cycles(150);
|
||||
*GPPUDCLK0 = (1<<14)|(1<<15);
|
||||
wait_cycles(150);
|
||||
*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 uart_puts(char *s) {
|
||||
while(*s) {
|
||||
/* convert newline to carrige return + newline */
|
||||
if(*s=='\n')
|
||||
uart_send('\r');
|
||||
uart_send(*s++);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Display a binary value in hexadecimal
|
||||
*/
|
||||
void uart_hex(unsigned int d) {
|
||||
unsigned int n;
|
||||
int c;
|
||||
for(c=28;c>=0;c-=4) {
|
||||
// get highest tetrad
|
||||
n=(d>>c)&0xF;
|
||||
// 0-9 => '0'-'9', 10-15 => 'A'-'F'
|
||||
n+=n>9?0x37:0x30;
|
||||
uart_send(n);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Dump memory
|
||||
*/
|
||||
void uart_dump(void *ptr)
|
||||
{
|
||||
unsigned long a,b,d;
|
||||
unsigned char c;
|
||||
for(a=(unsigned long)ptr;a<(unsigned long)ptr+512;a+=16) {
|
||||
uart_hex(a); uart_puts(": ");
|
||||
for(b=0;b<16;b++) {
|
||||
c=*((unsigned char*)(a+b));
|
||||
d=(unsigned int)c;d>>=4;d&=0xF;d+=d>9?0x37:0x30;uart_send(d);
|
||||
d=(unsigned int)c;d&=0xF;d+=d>9?0x37:0x30;uart_send(d);
|
||||
uart_send(' ');
|
||||
if(b%4==3)
|
||||
uart_send(' ');
|
||||
}
|
||||
for(b=0;b<16;b++) {
|
||||
c=*((unsigned char*)(a+b));
|
||||
uart_send(c<32||c>=127?'.':c);
|
||||
}
|
||||
uart_send('\r');
|
||||
uart_send('\n');
|
||||
}
|
||||
}
|
@ -0,0 +1,31 @@
|
||||
/*
|
||||
* 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 uart_puts(char *s);
|
||||
void uart_hex(unsigned int d);
|
||||
void uart_dump(void *ptr);
|
@ -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,26 @@
|
||||
Tutorial 0F - Futási szintek
|
||||
============================
|
||||
|
||||
Mielőtt rátérhetnénk a virtuális memóriára, beszélnünk kell a futási szintekről. Minden szintnek saját
|
||||
lapfordító tára van, emiatt életbevágó, hogy tudjuk, melyik szinten futunk éppen. Ezért ebben az oktatóanyagban
|
||||
megbizonyosodunk róla, hogy rendszerfelügyeleti szinten (supervisor) azaz EL1-en vagyunk-e. Qemu alatt a gép
|
||||
indulhat egyből EL1-en, az igazi Raspberry Pi vason azonban mindig virtualizációs szinten (hypervisor) azaz EL2-n
|
||||
ébredünk. Qemu alatt a szintváltást a "-d int" kapcsolóval debuggolhatjuk.
|
||||
|
||||
```sh
|
||||
$ qemu-system-aarch64 -M raspi3 -kernel kernel8.img -serial stdio -d int
|
||||
Exception return from AArch64 EL2 to AArch64 EL1 PC 0x8004c
|
||||
Current EL is: 00000001
|
||||
```
|
||||
|
||||
Start
|
||||
-----
|
||||
|
||||
Hozzáadtam egy pár Assembly sort, ami átállítja a futási szintet, ha nem rendszerfelügyeleti szinten lennénk.
|
||||
De mielőtt ezt megtehetnénk, hozzáférést kell biztosítani a számláló regiszterekhez (counter, amit a wait_msec()
|
||||
használ). Végezetül egy kivételkezelőből való visszatérést hazudunk, hogy ténylegesen szintet váltsunk.
|
||||
|
||||
Main
|
||||
----
|
||||
|
||||
Lekérjük az aktuális futási szintet, és kiírjuk a soros konzolra.
|
@ -0,0 +1,25 @@
|
||||
Tutorial 0F - Execution levels
|
||||
==============================
|
||||
|
||||
Before we can go on to virtual memory, we have to talk about execution levels. Each level has it's own
|
||||
memory translation tables, therefore it's cruital to know which one we are using. So in this tutorial we're
|
||||
make sure of it, we are at supervisor level, EL1. Qemu may start machine at EL1, but real Raspberry Pi hardware
|
||||
always boots at hypervisor level, EL2. Under qemu use "-d int" to debug the level change.
|
||||
|
||||
```sh
|
||||
$ qemu-system-aarch64 -M raspi3 -kernel kernel8.img -serial stdio -d int
|
||||
Exception return from AArch64 EL2 to AArch64 EL1 PC 0x8004c
|
||||
Current EL is: 00000001
|
||||
```
|
||||
|
||||
Start
|
||||
-----
|
||||
|
||||
I've added a little bit more Assembly code for changing the execution level if we're not at supervisor level.
|
||||
But before we can do that, we have to grant access for the counter registers (used by wait_msec()).
|
||||
Finally, we fake an exception return to change the level for real.
|
||||
|
||||
Main
|
||||
----
|
||||
|
||||
We query the current execution level and then we display it on the serial console.
|
@ -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,46 @@
|
||||
/*
|
||||
* 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()
|
||||
{
|
||||
unsigned int el;
|
||||
|
||||
// set up serial console
|
||||
uart_init();
|
||||
|
||||
// read the current level from system register
|
||||
asm volatile ("mrs %0, CurrentEL" : "=r" (el));
|
||||
|
||||
uart_puts("Current EL is: ");
|
||||
uart_hex(el>>2);
|
||||
uart_puts("\n");
|
||||
|
||||
// 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,73 @@
|
||||
/*
|
||||
* 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
|
||||
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
|
||||
// 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
|
@ -0,0 +1,126 @@
|
||||
/*
|
||||
* 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"
|
||||
|
||||
/* 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))
|
||||
|
||||
/**
|
||||
* 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|=(2<<12)|(2<<15); // alt5
|
||||
*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 uart_puts(char *s) {
|
||||
while(*s) {
|
||||
/* convert newline to carrige return + newline */
|
||||
if(*s=='\n')
|
||||
uart_send('\r');
|
||||
uart_send(*s++);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Display a binary value in hexadecimal
|
||||
*/
|
||||
void uart_hex(unsigned int d) {
|
||||
unsigned int n;
|
||||
int c;
|
||||
for(c=28;c>=0;c-=4) {
|
||||
// get highest tetrad
|
||||
n=(d>>c)&0xF;
|
||||
// 0-9 => '0'-'9', 10-15 => 'A'-'F'
|
||||
n+=n>9?0x37:0x30;
|
||||
uart_send(n);
|
||||
}
|
||||
}
|
@ -0,0 +1,30 @@
|
||||
/*
|
||||
* 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 uart_puts(char *s);
|
||||
void uart_hex(unsigned int d);
|
@ -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,49 @@
|
||||
Tutorial 10 - Virtuális Memória
|
||||
===============================
|
||||
|
||||
Elérkeztünk a legegyszerűbb és egyben legbonyolultabb oktatóanyagunkhoz. Egyszerű, mert nem csinálunk mást, mint
|
||||
feltöltünk egy tömböt, aztán beállítunk pár regisztert. A nehézség abban rejlik, hogy mi kerüljön a tömbbe.
|
||||
|
||||
Feltételezem kellő ismerettel rendelkezel az AMD64-es lapozásáról. Ha nem, akkor erősen javaslom, hogy szánj rá
|
||||
időt mielőtt folytatnád. Az ARMv8 MMU-ja sokkal de sokkal bonyolultabb és összetettebb, mint az AMD64-é. Határozottan
|
||||
nem jó ötlet ezzel kezdeni.
|
||||
|
||||
Az AMD64 címfordítása roppant egyszerű, egy táblacím regisztere van, a memóriát 4k-s lapokra osztja, 4 szinten,
|
||||
és csak egyféle luk van definilálva a címtérben. ARMv8 ennél sokkal combosabb. Beállíthatot a lapkeret méretét,
|
||||
a lapozási szintek számát, összefűzheted a lapfordító táblázatokat egy adott szinten, de még a luk méretét is
|
||||
beállíthatod. Képtelenség mindezt egy oktatóanyaggal lefedni. Ezért úgy döntöttem, inkább úgy állítom be az ARMv8
|
||||
MMU-ját, hogy minnél jobban hasonlítson az AMD64-éhez. Ez a következőket jelenti: 4k-s lapméretet fogunk használni,
|
||||
2M-es blokkmérettel és 512G-s címterülettel (3 szint), ahol a 4. szintet két regiszter helyettesíti. Fogd fel
|
||||
úgy, hogy amíg AMD64-n a 4. szintű laptábla címe a CR3-ban van megadva, addig ARMv8-on van egyszer a TTBR0 regiszter,
|
||||
ami ennek a táblának az első elemét tartalmazza, valamint van a TTBR1 regiszter, ami meg az utolsó, 512. elemét,
|
||||
ezért nincs szükség 4. szintű laptáblára. Minden köztes cím (amit a 2.-511. elemek fordítanának) a lukra esik, más
|
||||
szavakkal azok nem kanonikus memória címek.
|
||||
|
||||
|
||||
A lapfordító táblázat egyébként ugyanúgy néz ki: 64 bites elemeket tartalmaz, amikben van egy fizikai cím és néhány
|
||||
attribútum bit, minden egyes szinten. De ARMv8-on sokkal több lehetőséged van. Külön beállíthatod a gyorsítótárat
|
||||
(cachability), megosztást (shareability) és a hozzáférést is. Ezen kívül van még egy memória típus tömböt tartalmazó
|
||||
regiszter, aminek az elemeire indexelnek a lapcím fordító tábla bejegyzéseinek bitjei.
|
||||
|
||||
A következőképp fogjuk leképezni a virtuális memóriát: az alacsony címeket egy-az-egyben megfeleltetéssel 2M
|
||||
blokkonként, kivéve az első blokkot, amit 4k-nként. A magas címekre pedig, -2M-nél leképezzük az UART0 MMIO-ját.
|
||||
|
||||
Mmu.h, mmu.c
|
||||
------------
|
||||
|
||||
`mmu_init()` inicializálja a memória címfordító egységet (Memory Management Unit)
|
||||
|
||||
Start
|
||||
-----
|
||||
|
||||
Ezúttal hozzáférést kell biztosítanunk a rendszer kontroll regiszterhez is (system control register).
|
||||
|
||||
Link.ld
|
||||
-------
|
||||
|
||||
Most szükség van arra, hogy az adatterületet és a programunk vége cimkét laphatárra igazítsuk.
|
||||
|
||||
Main
|
||||
----
|
||||
|
||||
Beállítjuk a címfordítást, majd kiírunk a konzolra mind egy-az-egyben lapozást, mind magas című lapozást használva.
|
@ -0,0 +1,48 @@
|
||||
Tutorial 10 - Virtual Memory
|
||||
============================
|
||||
|
||||
We came to the simplest and most difficult tutorial at the same time. It's simple as all we are going to do
|
||||
is fill up an array, and set some registers. The difficulty lies in knowing what values should we put in that array.
|
||||
|
||||
I assume you have a fair knowledge about page translation mechanism on AMD64. If not, I strongly suggest to
|
||||
do some tutorial on it before you continue. ARMv8's MMU is much much more complex and featureful than it's AMD64
|
||||
counterpart. It is definitely not good to start with.
|
||||
|
||||
As AMD64's address translation is very simple, it has one paging table register, it splits memory into 4k
|
||||
pages only with 4 levels, and it has one well defined hole in the address space. ARMv8 is much more powerful. You
|
||||
can set the size of the pageframe, the number of translation levels, you can concatenate translation tables for a
|
||||
given level, and you can even configure the hole's size. It is impossible to cover all of these in one tutorial.
|
||||
Therefore what I'm going to do is configuring ARMv8 MMU to be similar to AMD64's as much as possible. That is:
|
||||
we're going to use 4k pageframes with 2M blocks and 512G address space (3 levels) with the 4th level in two registers.
|
||||
Think of it this way: on AMD64 you would have a 4th level table, pointed by CR3. On ARMv8, we have TTBR0 register which
|
||||
holds the first entry of that 4th level table, and TTBR1 which holds the last, 512th entry of the table, therefore we
|
||||
don't need the 4th level table at all. Everything between (memory mapped by the 2nd-511th entries) is in the hole, with
|
||||
other words they are non-canonical addresses.
|
||||
|
||||
The page translation table looks the same: we have 64 bit entries with a physical address and attribute bits in it
|
||||
at each level. But in ARMv8 you have far more options. You can set cacheability, shareability and accessibility as
|
||||
well. You also have a special register holding a page attribute array, and you index that with bits in the page
|
||||
translation attributes.
|
||||
|
||||
We are going to translate virtual address space as follows: lower half will be identity mapped in 2M blocks, except
|
||||
the first block which will be mapped by 4k frames. In the higher half, at -2M we will map the MMIO of UART0.
|
||||
|
||||
Mmu.h, mmu.c
|
||||
------------
|
||||
|
||||
`mmu_init()` function to initialize Memory Management Unit.
|
||||
|
||||
Start
|
||||
-----
|
||||
|
||||
This time we also have to grant access to the system control register.
|
||||
|
||||
Link.ld
|
||||
-------
|
||||
|
||||
This time we need page alignment for the data and the end label.
|
||||
|
||||
Main
|
||||
----
|
||||
|
||||
We set up page translations, and then we print to the console with both identity mapped and higher half mapped MMIO.
|
@ -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,46 @@
|
||||
/*
|
||||
* 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*) }
|
||||
. = ALIGN(4096);
|
||||
PROVIDE(_data = .);
|
||||
.data : { *(.data .data.* .gnu.linkonce.d*) }
|
||||
.bss (NOLOAD) : {
|
||||
. = ALIGN(16);
|
||||
__bss_start = .;
|
||||
*(.bss .bss.*)
|
||||
*(COMMON)
|
||||
__bss_end = .;
|
||||
}
|
||||
. = ALIGN(4096);
|
||||
_end = .;
|
||||
|
||||
/DISCARD/ : { *(.comment) *(.gnu*) *(.note*) *(.eh_frame*) }
|
||||
}
|
||||
__bss_size = (__bss_end - __bss_start)>>3;
|
@ -0,0 +1,57 @@
|
||||
/*
|
||||
* 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 "mmu.h"
|
||||
|
||||
#define KERNEL_UART0_DR ((volatile unsigned int*)0xFFFFFFFFFFE00000)
|
||||
#define KERNEL_UART0_FR ((volatile unsigned int*)0xFFFFFFFFFFE00018)
|
||||
|
||||
void main()
|
||||
{
|
||||
char *s="Writing through MMIO mapped in higher half!\r\n";
|
||||
|
||||
// set up serial console
|
||||
uart_init();
|
||||
|
||||
// set up paging
|
||||
mmu_init();
|
||||
|
||||
// test mapping
|
||||
uart_puts("Writing through identity mapped MMIO.\n");
|
||||
|
||||
// test mapping
|
||||
while(*s) {
|
||||
/* wait until we can send */
|
||||
do{asm volatile("nop");}while(*KERNEL_UART0_FR&0x20);
|
||||
/* write the character to the buffer */
|
||||
*KERNEL_UART0_DR=*s++;
|
||||
}
|
||||
|
||||
// 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,177 @@
|
||||
/*
|
||||
* 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" // get MMIO_BASE
|
||||
#include "uart.h"
|
||||
|
||||
#define PAGESIZE 4096
|
||||
|
||||
// granularity
|
||||
#define PT_PAGE 0b11 // 4k granule
|
||||
#define PT_BLOCK 0b01 // 2M granule
|
||||
// accessibility
|
||||
#define PT_KERNEL (0<<6) // privileged, supervisor EL1 access only
|
||||
#define PT_USER (1<<6) // unprivileged, EL0 access allowed
|
||||
#define PT_RW (0<<7) // read-write
|
||||
#define PT_RO (1<<7) // read-only
|
||||
#define PT_AF (1<<10) // accessed flag
|
||||
#define PT_NX (1UL<<54) // no execute
|
||||
// shareability
|
||||
#define PT_OSH (2<<8) // outter shareable
|
||||
#define PT_ISH (3<<8) // inner shareable
|
||||
// defined in MAIR register
|
||||
#define PT_MEM (0<<2) // normal memory
|
||||
#define PT_DEV (1<<2) // device MMIO
|
||||
#define PT_NC (2<<2) // non-cachable
|
||||
|
||||
#define TTBR_ENABLE 1
|
||||
|
||||
// get addresses from linker
|
||||
extern volatile unsigned char _data;
|
||||
extern volatile unsigned char _end;
|
||||
|
||||
/**
|
||||
* Set up page translation tables and enable virtual memory
|
||||
*/
|
||||
void mmu_init()
|
||||
{
|
||||
unsigned long r, b, *paging=(unsigned long*)&_end;
|
||||
|
||||
/* create MMU translation tables at _end */
|
||||
|
||||
// TTBR0, identity L1
|
||||
paging[0]=(unsigned long)((unsigned char*)&_end+2*PAGESIZE) | // physical address
|
||||
PT_PAGE | // it has the "Present" flag, which must be set, and we have area in it mapped by pages
|
||||
PT_AF | // accessed flag. Without this we're going to have a Data Abort exception
|
||||
PT_USER | // non-privileged
|
||||
PT_ISH | // inner shareable
|
||||
PT_MEM; // normal memory
|
||||
|
||||
// identity L2, first 2M block
|
||||
paging[2*512]=(unsigned long)((unsigned char*)&_end+3*PAGESIZE) | // physical address
|
||||
PT_PAGE | // we have area in it mapped by pages
|
||||
PT_AF | // accessed flag
|
||||
PT_USER | // non-privileged
|
||||
PT_ISH | // inner shareable
|
||||
PT_MEM; // normal memory
|
||||
|
||||
// identity L2 2M blocks
|
||||
b=MMIO_BASE>>21;
|
||||
// skip 0th, as we're about to map it by L3
|
||||
for(r=1;r<512;r++)
|
||||
paging[2*512+r]=(unsigned long)((r<<21)) | // physical address
|
||||
PT_BLOCK | // map 2M block
|
||||
PT_AF | // accessed flag
|
||||
PT_NX | // no execute
|
||||
PT_USER | // non-privileged
|
||||
(r>=b? PT_OSH|PT_DEV : PT_ISH|PT_MEM); // different attributes for device memory
|
||||
|
||||
// identity L3
|
||||
for(r=0;r<512;r++)
|
||||
paging[3*512+r]=(unsigned long)(r*PAGESIZE) | // physical address
|
||||
PT_PAGE | // map 4k
|
||||
PT_AF | // accessed flag
|
||||
PT_USER | // non-privileged
|
||||
PT_ISH | // inner shareable
|
||||
((r<0x80||r>(unsigned long)&_data/PAGESIZE)? PT_RW|PT_NX : PT_RO); // different for code and data
|
||||
|
||||
// TTBR1, kernel L1
|
||||
paging[512+511]=(unsigned long)((unsigned char*)&_end+4*PAGESIZE) | // physical address
|
||||
PT_PAGE | // we have area in it mapped by pages
|
||||
PT_AF | // accessed flag
|
||||
PT_KERNEL | // privileged
|
||||
PT_ISH | // inner shareable
|
||||
PT_MEM; // normal memory
|
||||
|
||||
// kernel L2
|
||||
paging[4*512+511]=(unsigned long)((unsigned char*)&_end+5*PAGESIZE) | // physical address
|
||||
PT_PAGE | // we have area in it mapped by pages
|
||||
PT_AF | // accessed flag
|
||||
PT_KERNEL | // privileged
|
||||
PT_ISH | // inner shareable
|
||||
PT_MEM; // normal memory
|
||||
|
||||
// kernel L3
|
||||
paging[5*512]=(unsigned long)(MMIO_BASE+0x00201000) | // physical address
|
||||
PT_PAGE | // map 4k
|
||||
PT_AF | // accessed flag
|
||||
PT_NX | // no execute
|
||||
PT_KERNEL | // privileged
|
||||
PT_OSH | // outter shareable
|
||||
PT_DEV; // device memory
|
||||
|
||||
/* okay, now we have to set system registers to enable MMU */
|
||||
|
||||
// check for 4k granule and at least 36 bits physical address bus */
|
||||
asm volatile ("mrs %0, id_aa64mmfr0_el1" : "=r" (r));
|
||||
b=r&0xF;
|
||||
if(r&(0xF<<28)/*4k*/ || b<1/*36 bits*/) {
|
||||
uart_puts("ERROR: 4k granule or 36 bit address space not supported\n");
|
||||
return;
|
||||
}
|
||||
|
||||
// first, set Memory Attributes array, indexed by PT_MEM, PT_DEV, PT_NC in our example
|
||||
r= (0xFF << 0) | // AttrIdx=0: normal, IWBWA, OWBWA, NTR
|
||||
(0x04 << 8) | // AttrIdx=1: device, nGnRE (must be OSH too)
|
||||
(0x44 <<16); // AttrIdx=2: non cacheable
|
||||
asm volatile ("msr mair_el1, %0" : : "r" (r));
|
||||
|
||||
// next, specify mapping characteristics in translate control register
|
||||
r= (0b00LL << 37) | // TBI=0, no tagging
|
||||
(b << 32) | // IPS=autodetected
|
||||
(0b10LL << 30) | // TG1=4k
|
||||
(0b11LL << 28) | // SH1=3 inner
|
||||
(0b01LL << 26) | // ORGN1=1 write back
|
||||
(0b01LL << 24) | // IRGN1=1 write back
|
||||
(0b0LL << 23) | // EPD1 enable higher half
|
||||
(25LL << 16) | // T1SZ=25, 3 levels (512G)
|
||||
(0b00LL << 14) | // TG0=4k
|
||||
(0b11LL << 12) | // SH0=3 inner
|
||||
(0b01LL << 10) | // ORGN0=1 write back
|
||||
(0b01LL << 8) | // IRGN0=1 write back
|
||||
(0b0LL << 7) | // EPD0 enable lower half
|
||||
(25LL << 0); // T0SZ=25, 3 levels (512G)
|
||||
asm volatile ("msr tcr_el1, %0; isb" : : "r" (r));
|
||||
|
||||
// tell the MMU where our translation tables are. TTBR_ENABLE bit not documented, but required
|
||||
// lower half, user space
|
||||
asm volatile ("msr ttbr0_el1, %0" : : "r" ((unsigned long)&_end + TTBR_ENABLE));
|
||||
// upper half, kernel space
|
||||
asm volatile ("msr ttbr1_el1, %0" : : "r" ((unsigned long)&_end + TTBR_ENABLE + PAGESIZE));
|
||||
|
||||
// finally, toggle some bits in system control register to enable page translation
|
||||
asm volatile ("dsb ish; isb; mrs %0, sctlr_el1" : "=r" (r));
|
||||
r|=0xC00800; // set mandatory reserved bits
|
||||
r&=~((1<<25) | // clear EE, little endian translation tables
|
||||
(1<<24) | // clear E0E
|
||||
(1<<19) | // clear WXN
|
||||
(1<<12) | // clear I, no instruction cache
|
||||
(1<<4) | // clear SA0
|
||||
(1<<3) | // clear SA
|
||||
(1<<2) | // clear C, no cache at all
|
||||
(1<<1)); // clear A, no aligment check
|
||||
r|= (1<<0); // set M, enable MMU
|
||||
asm volatile ("msr sctlr_el1, %0; isb" : : "r" (r));
|
||||
}
|
@ -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.
|
||||
*
|
||||
*/
|
||||
|
||||
void mmu_init();
|
@ -0,0 +1,81 @@
|
||||
/*
|
||||
* 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
|
||||
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
|
||||
// Setup SCTLR access
|
||||
mov x0, #(1 << 31) // AArch64
|
||||
orr x0, x0, #(1 << 1) // SWIO hardwired on Pi3
|
||||
msr hcr_el2, x0
|
||||
mrs x0, hcr_el2
|
||||
mov x2, #0x0800
|
||||
movk x2, #0x30d0, lsl #16
|
||||
msr sctlr_el1, x1
|
||||
// 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
|
@ -0,0 +1,126 @@
|
||||
/*
|
||||
* 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"
|
||||
|
||||
/* 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))
|
||||
|
||||
/**
|
||||
* 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|=(2<<12)|(2<<15); // alt5
|
||||
*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 uart_puts(char *s) {
|
||||
while(*s) {
|
||||
/* convert newline to carrige return + newline */
|
||||
if(*s=='\n')
|
||||
uart_send('\r');
|
||||
uart_send(*s++);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Display a binary value in hexadecimal
|
||||
*/
|
||||
void uart_hex(unsigned int d) {
|
||||
unsigned int n;
|
||||
int c;
|
||||
for(c=28;c>=0;c-=4) {
|
||||
// get highest tetrad
|
||||
n=(d>>c)&0xF;
|
||||
// 0-9 => '0'-'9', 10-15 => 'A'-'F'
|
||||
n+=n>9?0x37:0x30;
|
||||
uart_send(n);
|
||||
}
|
||||
}
|
@ -0,0 +1,30 @@
|
||||
/*
|
||||
* 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 uart_puts(char *s);
|
||||
void uart_hex(unsigned int d);
|
Loading…
Reference in New Issue