This repository has no description
0

Configure Feed

Select the types of activity you want to include in your feed.

Add random number generator for aarch64

iilak (Jan 7, 2024, 6:32 PM +0100) 8966d638 8f8fcb83

+80 -21
+1
.gitignore
··· 1 1 .DS_Store 2 2 cmake/copy_img_to_sd.sh 3 3 4 + compile_commands.json 4 5 *.img 5 6 *.elf 6 7 *.a
+2 -1
CMakeLists.txt
··· 3 3 include(cmake/target.cmake) 4 4 setup("MODEL_1" ${CMAKE_CURRENT_SOURCE_DIR}) 5 5 message("Build Info:\n\t - Arch:\t${ARCH}\n\t - Model:\t${MODEL}") 6 + add_compile_options(-DUART_MODE=1) # Activate special mode where charater output gets redirected to UART_0 6 7 7 8 set(CMAKE_DEPENDS_USE_COMPILER ON) 8 9 ··· 20 21 21 22 set(CMAKE_EXPORT_COMPILE_COMMANDS ON) 22 23 23 - add_subdirectory(os) 24 + add_subdirectory(os)
+12 -4
README.md
··· 3 3 4 4 This project is trying to build a simple OS for the RaspberryPi Zero W. 5 5 I have zero experience with embedded SW-development and unfortunately also never had a change to look at it in university. This is a hobby project that I started to get some familiarity with the subject. 6 - I don't really have a clear goal, but I'm using other peoples projects on the internet as a reference and will see where it will take me... I have two RaspberryPi's (Zero W, Zero 2 W, and B+) and in the end I would like the code to run on all devices. 6 + I don't really have a clear goal, but I'm using other peoples projects on the internet as a reference and will see where it will take me... I have three RaspberryPi's (Zero W, Zero 2 W, and B+) and in the end I would like the code to run on all devices. 7 7 8 8 [[_TOC_]] 9 9 ··· 22 22 * [Learning operating system development using Linux kernel and Raspberry Pi (*Sergey Matyukevich*)](https://github.com/s-matyukevich/raspberry-pi-os) Lots of explenations about concepts related to OS developement using the Linux kernel and RPi OS as an example. Helps to understand some of the code out there doing things/solving things and seeing the bigger picture! 23 23 24 24 ## How to build the project? 25 - As often with embedded projects, the toolchain hassle is real. The tricky part for this project is the compiler. Since we are writing code that is supposed to run on an ARM processor, you will need the corresponding compiler. All compilers to build for ARM CPU's can be found on [ARM's website](https://developer.arm.com/downloads/-/arm-gnu-toolchain-downloads). You will most probably have to cross-compile (`x86`->`arm`) and you will need to be careful if you are compiling the kernel for a `32-bit` or a `64-bit` CPU (`arm-none-eabi` vs `aarch64-none-elf`). 25 + As often with embedded projects, the toolchain hassle is real. The tricky part for this project is the compiler. Since we are writing code that is supposed to run on an ARM processor, you will need the corresponding compiler. All compilers to build for ARM CPU's can be found on [ARM's website](https://developer.arm.com/downloads/-/arm-gnu-toolchain-downloads). You will most probably have to cross-compile (`x86`->`arm`) and you will need to be careful if you are compiling the kernel for a `32-bit` or a `64-bit` CPU (`arm-none-eabi` vs `aarch64-none-elf`). The `CMakeLists.txt` file has all the logic needed to handle which compiler to pick depending on the Raspberry Pi Model you want to compile this code for. You will find in the toplevel `CMakeLists.txt` file a variable thats called `MODEL_X`, where `X` can be `[0,1,2,3,4]`. `MODEL_3` and `MODEL_4` have a `64bit` CPU and thus need the `aarch64` compiler. 26 + 27 + *Note*: This project was started with a `32bit` board (RPi 0) and thus most of the code was initially written with the ARMv6 architecture in mind. For example, the entire memory management code was written with ATAGS (ARM Tags) in mind, which where replaced by DTB's (device tree blob's) in ARMv8-a and would thus need a refresh. I will do this at some point, but for now I will focus more on exploring some of the capabilities of the `32bit` version of the board. In short, the `64bit` boards have a lot less functionality compared to the `32bit` boards with this kernel as of now. 26 28 27 29 Once you have all of this setup, you should be able to simple `cd` into the root of this repo and run (assuming you have `cmake` and `ninja-build` installed on your system) 28 30 ```bash ··· 37 39 ## How to run the kernel? 38 40 While the ultimate goal of course is to run the kernel on a RaspberryPi, for development it is useful to also run it in `qemu`. For the `32-bit` version you can use 39 41 ```bash 40 - qemu-system-arm -M raspi0 -serial null stdio -kernel ${PATH_TO_ELF_FILE}/kernel7.elf 42 + # ARMv6 / 32 bit 43 + qemu-system-arm -M raspi0 -serial null -serial stdio -kernel $PATH_TO_ELF/kernel.elf 44 + # ARMv8-a / 64 bit 45 + qemu-system-aarch64 -M raspi3b -serial null -serial stdio -kernel $PATH_TO_ELF/kernel7.elf 41 46 ``` 42 47 48 + *Note:* To run the code with `qemu` you use the `.elf`, i.e. the full executable. If you want to test the kernel out on a real Raspberry Pi, then you need to move the `.img` file onto the SD card. 49 + 50 + 43 51 ## How to generate documentation? 44 52 To generate the documentation you can run 45 53 ```bash 46 54 doxygen .doxyfile 47 55 ``` 48 - Please make sure to install doxygen and graphviz. 56 + Please make sure to install doxygen and graphviz.
+1 -1
cmake/target.cmake
··· 1 1 macro(setup model path) 2 - set(BUILD_DIR ${path}/build/bin) 2 + set(BUILD_DIR ${CMAKE_BINARY_DIR}/bin) 3 3 4 4 if(${model} STREQUAL "MODEL_0" 5 5 OR ${model} STREQUAL "MODEL_1")
+2 -2
os/CMakeLists.txt
··· 8 8 set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -T ${ARCH_DIR}/linker.ld") 9 9 10 10 set(SOURCES 11 + src/kernel/random.c 11 12 src/kernel/kerio.c 12 13 src/kernel/gpu.c 13 14 src/kernel/mailbox.c ··· 31 32 target_include_directories(${KERNEL}.elf PUBLIC include) 32 33 target_link_libraries(${KERNEL}.elf PRIVATE common) 33 34 # target_link_libraries(${KERNEL}.elf PRIVATE utils) 34 - target_compile_definitions(${KERNEL}.elf PRIVATE UART_MODE=1) # Activate special mode where charater output gets redirected to UART_0 35 35 36 36 # Generates the binary with objcopy. 37 37 add_custom_command( ··· 42 42 ) 43 43 44 44 # Bind above objcopy custom command with `kernel_img` target. 45 - add_custom_target(kernel_img ALL DEPENDS ${KERNEL}.img) 45 + add_custom_target(kernel_img ALL DEPENDS ${KERNEL}.img)
+7
os/include/kernel/random.h
··· 1 + #ifndef RANDOM_H 2 + #define RANDOM_H 3 + 4 + void rand_init(); 5 + unsigned int rand(unsigned int min, unsigned int max); 6 + 7 + #endif
+1 -1
os/src/common/stdlib.c
··· 170 170 } 171 171 result = ((nptr[0] == '-') ? -result : result); 172 172 return result; 173 - } 173 + }
+21 -12
os/src/kernel/kernel.c
··· 2 2 3 3 #include "common/stdlib.h" 4 4 #include "common/string.h" 5 + #include "kernel/kerio.h" 6 + #include "kernel/uart.h" 7 + 8 + #if defined(AARCH_32) 5 9 6 10 #include "kernel/atag.h" 7 11 #include "kernel/gpu.h" 8 - #include "kernel/kerio.h" 9 12 #include "kernel/memory.h" 10 - #include "kernel/uart.h" 11 13 12 14 /*! 13 15 * @brief Entry point for the kernel ··· 15 17 * @param r1 Machine ID 16 18 * @param atags Start of ATAGS 17 19 */ 18 - #if defined(AARCH_32) 19 20 void kernel_main(uint32_t r0, uint32_t arm_m_type, uint32_t atags) 20 - #else 21 - void kernel_main(uint64_t dtb_ptr32, uint64_t x0, uint64_t x1, uint64_t x3) 22 - #endif 23 21 { 24 22 (void)r0; 25 23 (void)arm_m_type; ··· 41 39 uint32_t mem_size = get_mem_size((atag_t *)atags); 42 40 printf("RAM size: %d MB\n\n", mem_size / 1024 / 1024); 43 41 44 - #ifdef AARCH_32 45 - printf("Architecture: AARCH_%d\n\n", 32); 42 + print_atags(atags); 43 + 44 + while(1) 45 + { 46 + putc(getc()); 47 + } 48 + } 46 49 #else 47 - printf("Architecture: AARCH_%d\n\n", 64); 48 - #endif 49 50 50 - print_atags(atags); 51 + #include "kernel/random.h" 51 52 53 + void kernel_main(uint64_t dtb_ptr32, uint64_t x0, uint64_t x1, uint64_t x3) 54 + { 55 + printf("ATTENTION YOU ARE IN UART MODE\n\n"); 56 + uart_init(); 57 + printf("Architecture: AARCH_%d\n\n", 64); 58 + rand_init(); 59 + printf("%d", rand(100, 500)); 52 60 while(1) 53 61 { 54 62 putc(getc()); 55 63 } 56 - } 64 + } 65 + #endif
+33
os/src/kernel/random.c
··· 1 + #include "kernel/random.h" 2 + #include "peripherals/base.h" 3 + #include "kernel/mmio.h" 4 + #include "common/stdlib.h" 5 + 6 + enum 7 + { 8 + RNG_CTRL = (MMIO_BASE + 0x00104000), 9 + RNG_STATUS = (MMIO_BASE + 0x00104004), 10 + RNG_DATA = (MMIO_BASE + 0x00104008), 11 + RNG_INT_MASK = (MMIO_BASE + 0x00104010), 12 + }; 13 + 14 + void rand_init() 15 + { 16 + mmio_write(RNG_STATUS, 0x40000); 17 + // mask interrupt 18 + uint32_t mask = mmio_read(RNG_INT_MASK); 19 + mmio_write(RNG_INT_MASK, mask|=1); 20 + // enable 21 + uint32_t ctrl = mmio_read(RNG_CTRL); 22 + mmio_write(RNG_CTRL, ctrl|=1); 23 + } 24 + 25 + unsigned int rand(unsigned int min, unsigned int max) 26 + { 27 + // may need to wait for entropy: bits 24-31 store how many words are 28 + // available for reading; require at least one 29 + while(!(mmio_read(RNG_STATUS)>>24)) asm volatile("nop"); 30 + 31 + divmod_t rand = divmod(mmio_read(RNG_DATA), (max-min)); 32 + return rand.mod + min; 33 + }