Git Product home page Git Product logo

mini-arm-os's Introduction

Build a minimal multi-tasking OS kernel for ARM from scratch

Prerequisites

./configure --disable-werror --enable-debug \
    --target-list="arm-softmmu" \
    --extra-cflags=-DSTM32_UART_NO_BAUD_DELAY \
    --extra-cflags=-DSTM32_UART_ENABLE_OVERRUN \
    --disable-gtk
make

Steps

  • 00-Semihosting
    • Minimal semihosted ARM Cortex-M "Hello World"
  • 00-HelloWorld
    • Enable STM32 USART to print trivial greetings
  • 01-HelloWorld
    • Almost identical to the previous one but improved startup routines
  • 02-ContextSwitch-1
    • Basic switch between user and kernel mode
  • 03-ContextSwitch-2
    • system call is introduced as an effective method to return to kernel
  • 04-Multitasking
    • Two user tasks are interatively switching
  • 05-TimerInterrupt
    • Enable SysTick for future scheduler implementation
  • 06-Preemptive
    • Basic preemptive scheduling
  • 07-Threads
    • Implement user-level threads
  • 08-CMSIS
    • Illustrate hardware abstraction layer (HAL) by introducing CMSIS
    • Both emulator (based on stm32-p103) and real device (STM32F429i discovery) are supported.

Building and Verification

  • Changes the current working directory to the specified one and then
make
make qemu

Guide to Hacking 08-CMSIS

08-CMSIS implements preemptive round-robin scheduling with user-level threads for STM32F429i-Discovery (real device) and STM32-P103 (qemu).

Get the dependencies:

git submodule init
git submodule update

Install additional utilities:

Quick Start / Support Devices:

  • STM32F429i-Discovery(physical devices)
    • Details in Chinese by NCKU
    • STM32F429i-Discovery uses USART1(Tx=PA9,Rx=PA10,baud rate=115200) as default serial port here.
      • You would need a terminal emulator, such as screen
        • Installation on Ubuntu / Debian based systems: sudo apt-get install screen
        • Then, attach the device file where a serial to USB converter is attached: screen /dev/ttyUSB0 115200 8n1
        • Once you want to quit screen, press: Ctrl-a then k

Available commands:

Overall

  • make all
    • Build all target's bin,elf,objdump files in the "release" directory.
    • NOTE: make doe NOT equal to make all here because Makefile uses eval for targets.
  • make clean
    • Remove the entire "release" directory.

STM32-P103(QEMU)

  • make p103 or make target PLAT=p103
    • Build "p103.bin"
  • make qemu
    • Build "p103.bin" and run QEMU automatically.
  • make qemu_GDBstub
    • Build "p103.bin" and run QEMU with GDB stub and wait for remote GDB automatically.
  • make qemu_GDBconnect
    • Open remote GDB to connect to the QEMU GDB stub with port:1234 (the default port).

STM32F429i-Discovery(physical device)

  • make f429disco or make target PLAT=f429disco
    • Build "f429disco.bin"
  • make st-flash
    • Build "f429disco.bin" and flash the binary into STM32F429 with st-link.
  • make st-erase
    • Sometimes, STM32F429i-Discovery will not be able to flash new binary file, then you will need to erase flash memory with st-link.
    • Erase the entire flash on STM32F429.
  • make gdb_ST-UTIL
    • Using GDB with ST-LINK on STM32F429.
    • Remember to open another terminal,and type "st-util" to open "STLINK GDB Server"

Directory Tree:

  • core
    • Hardware independent source and header files.
  • platform
    • Hardware dependent source and header files.
  • cmsis
    • With cmsis,porting would be much easier!
  • release
    • This directory will be created after "Target" in Makefile is called.
    • Containing the elf,bin,objdump files in corresponding directory.
    • make clean will remove the entire directory,do not put personal files inside it!

Porting Guide:

You should know what CMSIS is and why it saves us a lot of efforts.

cmsis is a submodule from TibaChang/cmsis, maintained by Jia-Rung Chang.

The full project can be divided into two layer:

  • hardware-dependent part (HAL)
    • "platform" directory
  • hardware-indepentent part
    • "core" directory

Steps to launch the kernel on real devices:

STEP 1

Select a target name for your device, such as f429disco.

In this guide, we assume its name is example_device with vendor name "f429disco".

Create example_device directory in "platform" and f429disco directory in "cmsis" directory.

Create "include" and "src" directory in platform/example_device/

STEP 2

Introducing your CMSIS for your target, where it should be in the mbed repo.

For example, the CMSIS for STM32F429i-discovery could be found here.

We only need ".h" files, do not copy any ".c" files.

Put the header files into cmsis/f429discoexample_device.

cmsis is a submodule in this project, maintianed by Tiba Chang.

NOTE: You may encounter some error messages during building binary for your target. You need to solve it mannually. Usually, some files may be missing caused by some specific "define". You could just comment out that definition to resolve this problem.

STEP 3

This is the most difficult part.

You have to implement the files in platform/example_device/include/ and platform/example_device/src/.

According to different device vendor(such as STMicroelectronics, NXP, etc), the implementation is very different.

Please look into the current example:f429disco,and you will figure it out!

The function interface must be as same as the function interface in "platform/STM32F429/inc/" due to this is HAL for the entire project.

STEP 4

Add your target rules into Makefile.

Please look the example f429disco in the Makefile.

Most of the rules are reusable,so all you need is copy-n-paste, modifying the variable/target name and knowing what gcc arguments suit your target!

  • rules.mk
    • You should NOT modify this file! ย - All of the rules are encapsulated into macro, used in Makefile.
  • Makefile:
    • If your device vendor name does not exist, create new variable and assign a name to it!
      • E.g.STM32 := STM32
    • Add your device name
      • E.g.STM32F429_DEVICE := f429disco
    • Check your device CPU type(Cortex-M3/4)
      • In target_using_CM4_list
    • Will you use CMSIS?
      • If NOT,add to target_NOT_using_CMSIS_list
    • Use the predefined macro to produce the corresponding directory and device specific variable(device name,vendor name)
      • E.g. $(eval $(call eval_all_variable,$(STM32F429_DEVICE),$(STM32)))
      • The vendor name is used in the cmsis directory name. They must be associated with each other.
    • Use the predefined macro to produce the corresponding GCC commands
      • E.g.: $(eval $(call eval_build_command,$(STM32F429_DEVICE)))
      • This will derive lots of variables that you don't see in the Makefile.
    • Add your device name to all
      • In the specific form:$($(YOUR_DEVICE_NAME)_TARGET) , this variable will be automatic derived by rules.mk
      • E.g.: $($(STM32F429_DEVICE)_TARGET)

STEP 5

Congratulations!

Now, you can try the "Available commands" in this README.

Licensing

mini-arm-os is freely redistributable under the two-clause BSD License. Use of this source code is governed by a BSD-style license that can be found in the LICENSE file.

Reference

mini-arm-os's People

Contributors

adrianhuang avatar eddy0402 avatar jserv avatar kunhuahuang avatar lecopzer avatar rampant1018 avatar ryanpatiency avatar tibachang avatar yan-kuan avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

mini-arm-os's Issues

No actual guides for implementing and running OS

Hi, i forked this repo thinking that this was a tutorial for beginners but it seems that it requires experience using the ARM tool chain and stm32 stuff to even get started. If this is a tutorial for beginners, do you mind creating some additional documentation so i know where to begin? It's not a tutorial without the actual documentation being there to show you how running an OS in QEMU works. I'd really like to learn how i can develop kernels for the STM32 architecture, but this doesn't give me enough information to start with. CMSIS sounds great too! The idea of porting my OS that i ran on an emulator to a bare metal dev board sounds awesome. Thanks.

Question about naked attribute

/* Caution: Without naked attribute, GCC will normally push r7 which is used

In the comment linked by, it indicate r7 is for sp, but sp is r13 instead. Also quoting from Arm-Cortex-M3 technical reference:

"After returning from the ISR, the processor automatically pops the eight registers from the stack. Interrupt return is passed as a data field in the LR, so ISR functions can be normal C/C++ functions, and do not require a veneer."

So I wonder if we need naked attribute at all

Wrong processor mode in first time exception return

According to https://www.ptt.cc/bbs/ASM/M.1534260340.A.DC5.html

3d4ea33 is buggy due to reset is in privilege level and thread mode.

But the commit assume reset_handler is in Handler mode and makes undefined behavior when first calling activate except 06-Preemptive.

By some experiment, I acknowledge that it can still work well in QEMU but fail in real HW (STMF429), and that misled me during checking 3d4ea33.

I've solving it in my local by hacking activate or thread_start.
After cleanup the code, I will make a PR to solve it.

Weird FIXME

Most of pendsv_handler() have the comment above it:

/* FIXME: Without naked attribute, GCC will corrupt r7 which is used for stack
 * pointer. If so, after restoring the tasks' context, we will get wrong stack
 * pointer.
 */

Issue of r7 is due to calling convention of ARM.
So why we use naked attribute to make code work should be FIXED?

I think it not a bug or something needs to be fixed, it just a kind of solution.

Should not force LR to specific EXC_RETURN value

We have always set LR to 0xFFFFFFFD at the end of context switch, but this is a redundant or dangerous work.

Exception entry will store EXC_RETURN to LR automatically by hardware according to previous operation mode.

ARM DUI 0533A 2-27:
The processor writes an EXC_RETURN value to the LR.
This indicates which stack pointer corresponds to the stack frame and
what operation mode the processor was in before the entry occurred

It may cause some unpredictable result as someone might intend to utilize other function of EXC_RETURN.

01-HelloWorld cannot use "Press Ctrl-A and then X to exit QEMU" in ubuntu 14.04 x86_64 guest by virtualbox

I found issue that why 01-HelloWorld cannot use "Press Ctrl-A and then X to exit QEMU" in my environment. After add "-cpu arm926", it works as well.

patch as bellow.

diff --git a/01-HelloWorld/Makefile b/01-HelloWorld/Makefile
index cb4d2eb..a88d386 100644
--- a/01-HelloWorld/Makefile
+++ b/01-HelloWorld/Makefile
@@ -21,7 +21,7 @@ startup.o: startup.S
 qemu: $(TARGET)
        @echo "Press Ctrl-A and then X to exit QEMU"
        @echo
-       qemu-system-arm -M versatilepb -m 128M -nographic -kernel $(TARGET)
+       qemu-system-arm -M versatilepb -cpu arm926 -m 128M -nographic -kernel $(TARGET)

 clean:
        rm -f *.o *.bin *.elf

Irrational exception return behavior

Let's take 04-Multitasking for example. I provide three doubts on exception return.

  • First, Is it correctly to use assembly instruction control to replace exception return? In my opinion, control is only used when we want to change the state from privileged thread mode to unprivileged thread mode. We would change the state from handler mode to unprivileged mode when first task is created.
/*context_switch.S*/
activate:
    ...
	/* switch to process stack */
	msr psp, r0
	mov r0, #3
	msr control, r0
	isb
    ...
  • Second, I can not figure it out why we need to change the state from handler mode to unprivileged thread mode before we exception return. We can just launch exception return directly.
/*context_switch.S*/
activate:
    ...
	/* switch to process stack */
	msr psp, r0
	mov r0, #3
	msr control, r0
	isb

	/* load user state */
	pop {r4, r5, r6, r7, r8, r9, r10, r11, lr}

	/* jump to user task */
	bx lr
  • Third, I think it is not enough to deal with the register, "psr" by msr psr_nzcvq, ip. If the interrupt occurred when we are in IT block, It would enable the flag in "ipsr". But we could not restore the state by mrs because of the specification. However, to my best of my knowledge, It can only be restored completely by exception return.
/*context_switch.S*/
svc_handler:
     ...
	/* load kernel state */
	pop {r4, r5, r6, r7, r8, r9, r10, r11, ip, lr}
	msr psr_nzcvq, ip
    ...

By the way, I'm working on these problem. I would send the PR recently.

Support for MPU

HI,
After 08-CMSIS, is there any plan for MPU support?

MPU is common and basic to protect .text, .rodata and other custom regions.
I think nowadays memory protection is the fundamental OS concept and
should be implemented due to not only secure issue but modifying memory content accidentally.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.