---
tags: sysprog2018
---
# STM32 作業系統開發共筆
contributed by <`ryanpatiency`>, <`hexrabbit`>
## 學習目標
* 發展 mini-arm-os,增加其功能。
## 這篇文件內容包含
* 重要資源
對我們有重大幫助的資源,網站,書籍,請確保你知道這些東西的存在,並且大概熟悉其目錄,方便找解決方案
* 重要提示
很重要的知識點
* 學習紀錄
開發過程的學習與紀錄,特別重要的部份會整理成前面的提示與資源
* 問題討論
我們卡關的地方和部份的解決辦法,作為紀錄,提供參考
## 重要資源
* The definitive guide to arm-cortex-m3 (book)
A book helps you understand the arm chip, including booting sequence, thumb mode vs arm mode, supervisor call (SVC)... .etc.
* CSAPP (book)
Ch 7 & Ch 8.4.6 in book CSAPP to help you understand the principle behind objdump and readelf. As well as background knowledge about linker and loader
* [discovery board datasheet](https://www.st.com/content/ccc/resource/technical/document/user_manual/6b/25/05/23/a9/45/4d/6a/DM00093903.pdf/files/DM00093903.pdf/jcr:content/translations/en.DM00093903.pdf)
* [stm32 datasheet](http://www.st.com/content/ccc/resource/technical/document/datasheet/03/b4/b2/36/4c/72/49/29/DM00071990.pdf/files/DM00071990.pdf/jcr:content/translations/en.DM00071990.pdf)
* [stm32 programming manual](http://www.st.com/content/ccc/resource/technical/document/programming_manual/6c/3a/cb/e7/e4/ea/44/9b/DM00046982.pdf/files/DM00046982.pdf/jcr:content/translations/en.DM00046982.pdf)
* [stm32 reference manual](http://www.st.com/content/ccc/resource/technical/document/reference_manual/3d/6d/5a/66/b4/99/40/d4/DM00031020.pdf/files/DM00031020.pdf/jcr:content/translations/en.DM00031020.pdf)
* [stm32 peripheral library](http://www.st.com/en/embedded-software/stm32-standard-peripheral-libraries.html?querycriteria=productId=LN1939)
* [library 使用筆記1](https://goo.gl/N2fE5H)
這個人的教學很清楚,能幫助了解如何使用 library
* [library 使用筆記2](http://www.emcu.it/STM32/STM32Library/TwoWordsConcerningSTM32Library.html)
這個人的教學很清楚,能幫助了解如何使用 library
* [Bomb lab](/RQ2wNvIIS_-nZjPb3y7zFw)
To understand gdb and arm assembly
* [GNU linker script document](http://www.scoberlin.de/content/media/http/informatik/gcc_docs/ld_toc.html)
To understand hello.ld
* [semihosting](http://www.keil.co)
To learn background knowledge about module 00-Semihosting
* [stm32 程式開發](https://docs.google.com/document/d/1Ygl6cEGPXUffhTJE0K6B8zEtGmIuIdCjlZBkFlijUaE/edit)
jserv 老師撰寫的筆記
* [arm cortex m3 document](http://www.st.com/content/ccc/resource/technical/document/reference_manual/3d/6d/5a/66/b4/99/40/d4/DM00031020.pdf/files/DM00031020.pdf/jcr:content/translations/en.DM00031020.pdf)
## 重要提示
* 沒辦法 compile/ build/ 燒錄(program)/ 執行 等等都沒有關係,先跳到程式碼閱讀和資料查詢的步驟,因為了解所有程式碼 e.g. Makefile, linker script, register file ...和其背後的知識後,前面那些問題就自然解決了
* screen 中輸入 enter 只有 '\r' 沒有 '\n'
* [STM32F429xx block diagram]()
在 datasheet 裡面找的到,對於判斷 那一個 peripheral 用那一個 clock 有幫助 (AHB, APB...)
* [I2C](http://www.ti.com/lit/an/slva704/slva704.pdf)
可以幫助你了解 bus, master, slave 等是必備的知識
* How to connect to stm32f429
```
(sudo) openocd -f board/stm32f429discovery.cfg \
-c "arm semihosting enable" \
-c "reset run"
// in another terminal
arm-none-eabi-gdb somewhere/f429disco.elf -ex "target remote:3333"
// use load in gdb to flash ROM
```
* How to open UART: (Also see README.md in mini-arm-os)
```
// After connect PA9, PA10 to PC by TTL to USB
(sudo) screen /dev/ttyUSB0 115200 8n1
```
Note that Uart needs to have the same baud rate 115200
* One don't need an extra usb-to-ttl line to talk with the board
by data sheet, the default st-link are connect to the usart1
## 學習紀錄
* [一個 stm 愛好者 的 blog](http://www.emcu.eu/tutorial-on-the-web/)
* malloc in 07-Threads is from the c programming language. it is really the pearl of programming
* when interupt happens in the middle of:
* ldm: it will load the current register, and store the next register index into ICI bits in ePSR (note there exist aPSR, iPSR, ePSR)
* ld in itete: it will abandon the execution and start from first when return;
> So ARM hardwares will do these things (save & resume the status) for us,
> and we don't need to bother considering it right?
> [name=HexRabbit][color=yellowgreen]
> Right [name=ryanpatiency]
* There is a document called "AAPCS", which means *<Procedure Call Standard for the Arm Architecture>* and has nothing to do with "APPCS"
* .data section is fetched by system bus, instead of data bus. The range of D-Code bus have the same range with I-Code bus. As a result, the .data section put on 0x20000000 and above can only be fetched by system bus
* 03-context-switch2, the key point is r0 in `context-switch.S`
* it, itt, ittt, itttt are all available. and t can be replaced with e, which means if then, if else, and which means it, ite, itet, itete are available as well.
* * flash alias to 0x0 from 0x08000000 is a special case in stm32, not required in arm-cortex-m3, and only happened at boot-from-flash mode, not the other 2 modes.
* qemu can be connected to gdb:
* terminal 1: `qemu-system-arm -M stm32-p103 -semihosting -nographic -kernel semi.bin -gdb tcp::1234 -S`
* terminal 2: `gdb` with command `target remote :1234`
* `ENTRY(reset_handler)` is unnecessary since there is no os yet, and the reset_handler's trigger is because of its address location (byte 4)
* the `*` in `*(.reset_headler)` is wildcard, before I think it is `*ptr`
* `uint32_t *isr_vectors[]` could be modified to `uint32_t isr_vectors[]`, and the latter is more meaningful. (at least to me), or modify it a `void *` since it holds pointer to stack, pointer to function, pointer to...etc
* module `semihosting` can be simulated, and one can use SYS_READ (0x06) for fun by qemu option `-serial null -monitor null`, see [semihosting](http://www.keil.com/support/man/docs/armcc/armcc_pge1358787056689.htm) and [qemu](https://qemu.weilnetz.de/doc/qemu-doc.html#Introduction)
* Change code to fit stm32-f4 according to reference manual
ex change RCC to 0x40023800 from 0x40021000
* [mini-arm-os study note](https://paper.dropbox.com/doc/mini-arm-os-Study-Notes-wzm2BNhqb3BNsfnVCe8Ij)
之前修課同學的共筆
* [Build minimal ARM Kernel from Scratch](https://paper.dropbox.com/doc/Build-minimal-ARM-Kernel-from-Scratch-9CQXvokHAXZSSlFMBp1t6)
* [Super Simple Tasker](https://paper.dropbox.com/doc/Super-Simple-Tasker-NRRE7IhmUkUxj2Je1vpI7)
* [mini-arm-os 2016](https://paper.dropbox.com/doc/mini-arm-os-WgaKbI3BslwGbVXQoXGEg)
* [mini-arm-os 問題紀錄](https://paper.dropbox.com/doc/mini-arm-os-kB7s5zAOq1KXLUefSQcMf)
* [嵌入式作業系統: mini-arm-os](https://mdbookspace.com/view/c0/README.md)
* [10分鐘讀懂-linker-scripts](https://blog.louie.lu/2016/11/06/10%E5%88%86%E9%90%98%E8%AE%80%E6%87%82-linker-scripts/)
* [Discovering the STM32 Microcontroller](https://www.cs.indiana.edu/~geobrown/book.pdf)
Geoffrey Brown 的授課講義
* [openocd](http://openocd.org/doc/pdf/openocd.pdf)
燒程式的重要工具
* [arm cortex m3 tutorial English](http://tinymicros.com/mediawiki/images/7/75/Definitive_Guide_To_The_ARM_Cortex_M3.pdf) / [Chinese](http://www.realsense.com.cn/download/20100617/175619_296.pdf)
* [arm-bare-metal tutorial](https://www.embedded.com/design/mcus-processors-and-socs/4007119/Building-Bare-Metal-ARM-Systems-with-GNU-Part-1--Getting-Started)
## 問題討論
- [ ] fail to emulate rtenv+ with QEMU
- [x] gdb will fail tracing svc call in content_switch (but I've succeeded once..)
=> needs to set breakpoint in svc handler
- [x] In 04,06,07 there's a
`stack += STACK_SIZE - 32; /* End of stack, minus what we are about to push */`
but actually, we only need place (9+8) * sizeof(int) = 17 byte above the end of stack, so what does that 32 mean ?
=> just a large number
- [x] Is there any benefit of `lr` register design in arm compared to intel's `push` instruction with no need of a register to save return address ?
- [x] In 06-Preemptive, I think `task_init()` is unnecessary, what is the meaning of calling `svc 0` in privileged mode ?
> Yes `task_init()` is unnecessary in this version, you could create a pull request.
[name=ryanpatiency][color=green]
- [x] in arm, mrs seems not available in v7? [link](http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0489c/CIHGJHHH.html)
=> it is supported, but the link given is in coprocessor section, which doesn't support by cortex-m3 [link](https://developer.arm.com/docs/103489453/latest/do-cortex-m-processors-support-coprocessors)
- [x] Why user_stack_start from -8 instead of 0
=> because beside the 8 callee saved register, there is still 8 caller saved register.
- [x] what does the 'i' in `sidata` means?
=> initializer
- [x] Where can one find that one can use `UART` through the `st-lint` to print `hello world`. And How?
=> by the study note given below
- [x] Different between bin and elf
=> All symbols and relocation information will be discarded in bin
- [x] Why `as file_name.s -o a.out` is different from `as file_name.s`
=> there is no different, but notice that `ld`'s default output is also `a.out`, thus a conflict
- [x] where is my dev/stlink
=> don't use stlink, use openocd
- [x] in arm-none-eabi, what does "none" means?
=> it means no os
- [x] exception table start from memory 0 (stack) and memory 4 (handler), and flash memory alias at memory 0?
=> detail is in the the definitive guide to arm-cortex-M3
- [x] 指定MSP為0x20001000,即堆疊大小為0x1000 -> 所以預設的stack上界是0x20000000 ?
=> detail is in the the definitive guide to arm-cortex-M3
- [x] Where can one find that how to enable and manipulate `UART` in reference manual? and the rcc-enable in 01-helloworld, and all the hardware related things in 00 to 08
=> `ctrl-F "UART" in reference manual` and finish it
=> `download the CMSIS and search the keyword inside`
- [x] What does [-2] means in `svc_number = ((char*)PSP[6])[-2];` refers to [SVC](http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dai0179b/ar01s02s07.html) and <guide> ch9 p.146
=> for example, the user call svc, the disassembly is like the following:, so [-2] means, from 800047e, we minus two, which is the svc number
```clike=
800047c: df00 svc 0
800047e: 4770 bx lr
```
> 要注意到使用`[-2]`而不是`[-1]`的原因是因為程式是運行在 little endian 環境且為 fixed-length instructions 架構下,所以實際上 .text 中真正的排列是 `00df`,這和一般 intel 的 variable-length instructions 架構下的排列不同
> [name=HexRabbit][color=orange]
- [x] <the definitive guide to arm> ch7 p128. figure 7.17, can systick interupt be pended? and will us use pendsv?
- [x] Is sp nether callee saved nor caller saved?
=> document
- [x] why save psr to ip(r12) when activate, it should be caller saved register. by AAPCS
=> no need
- [x] Why `-serial=null` work on qemu semihosting, (and what does it means?)
=> qemu document
- [x] is Ram(!rx) in linker script memory layout means not read-only and excutable?
=> it is !r and x
- [x] difference between `__attribute` and `__atribute__`
=> back is right
- [x] why use `-kernel` option, in qemu? its help: `-kernel bzImage use 'bzImage' as kernel image`
=> the manual lie
- [x] what is system boot and why will it use System memory which is from 0x1FFF F000 - 0x1FFF F7FF 2 Kbytes
=> it is corresponding to two pin which can boot from external source.
- [x] What does `ENTRY` exactly do in link stage, I don't see any?
=> [link](https://access.redhat.com/documentation/en-US/Red_Hat_Enterprise_Linux/4/html/Using_ld_the_GNU_Linker/simple-commands.html)
It will setup a symbol for the os to call, like `main`, or `_start`, and that is why when you didn't include a `_start` symbol, it will say something like `couldn't find _start, entry set at 0x4002800`
- [x] In content_switch_2, after svc call `lr` will be modified to an very large value, so what will happen when it returns(`bx lr`) ?
=> [**Exception return**](http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0497a/Babefdjc.html), `pc` and also `lr` will be restored from stack
- [x] Why there is `nop` in `syscall.S`? Is it used for optimization purpose?
=> According to jserv, this `nop` was added because `qemu`'s bug, and `qemu` might fix this bug already.