--- 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.