# Stm32 Tutorial - [NCRL_hackmd](https://hackmd.io/6OnKZUSkRd2wwnXzdQjXsA?view) - [NCRL_video](https://www.youtube.com/watch?v=HlAw-NBprQk&list=PLe8KWt_uj6-MP0VAuhI_jwjfT6QTO4jBG&index=1) - [NCRL_example](https://github.com/shengwen-tw/stm32f4-examples) - [Develop Environment Setup](https://c-shengwen-tw.gitbook.io/ncrl-flight-controller/guide/development-environment?fbclid=IwAR28Afm-zPUvVhX_YtfErMcRYPclOvfknNt3BVCdR1-72E1E4-ZYQd--0JI) - [成大资工wiki](http://wiki.csie.ncku.edu.tw/embedded/GPIO) - [成大嵌入式系统教材](http://wiki.csie.ncku.edu.tw/embedded/Lab19/stm32-prog.pdf) - [data sheet](https://www.st.com/resource/en/datasheet/stm32f415rg.pdf) - [github library](https://github.com/espruino/Espruino/tree/master/targetlibs/stm32f4/lib) ## Table of Content [TOC] ## Lecture 1 **STM32產品線概要** <!-- ![](https://i.imgur.com/TrIx77c.png) --> ![](https://i.imgur.com/4k2eKIY.png) ![](https://i.imgur.com/OWOzn91.png) - 补充: - ARM Cortox-A for cellphone market - ARM Cortex-M for micro controller market - ARM Cortex-R between Cortox-A and Cortex-M - the device we use: STM32F407 - feature: - MCU with 168 MHz/210 DMIPS - Arm Cortex -M4 core + floating point unit (FPU) - 封装: stm32f407 VGT6U - Not the strongest, but the fittest will survive. **Device Overview (Page.20 in data sheet)** ![](https://i.imgur.com/ibGc0wX.png) **AMBA匯流排介绍** ![](https://i.imgur.com/LyUUobc.png) 1. Advanced High-performance Bus (AHB) (适用于连接系统中的高速模组) 2. Advanced System Bus (ASB) (功能同AHB,但性能略差于AHB) 3. Advanced Peripheral Bus (APB) (用于低功耗的周边硬体模组,适用于低速模组) **Clock** ![](https://i.imgur.com/hAaMhye.png) ## Lecture 2 **GPIO 用途 (in register)** ![](https://i.imgur.com/JuirOl2.png) - moder: - input, output for digital io - analog for alalog io - alternate function for periphery usage - Set Moder of GPIO(stored in register of CPU) ![](https://i.imgur.com/OAfdHQY.png) - OType (output type) - push-pull and open-drain ![](https://i.imgur.com/0gZc377.png) - [reference](http://cary1120.blogspot.com/2013/11/open-drain-push-pull.html) - [reference](https://tfing.blogspot.com/2019/10/gpio-input-pull-uppull-downoutput-push.html) - PuPd (pull up or pull down) ![](https://i.imgur.com/ytbkahU.png) - OSpeed (output speed) - example: ![](https://i.imgur.com/OAAiO83.png) **practical transformation when changing moder** ![](https://i.imgur.com/iMyAA7H.png) - [Schmitt trigger](https://zh.wikipedia.org/wiki/%E6%96%BD%E5%AF%86%E7%89%B9%E8%A7%A6%E5%8F%91%E5%99%A8) **What is Memory Mapped IO (MMIO)** ![](https://i.imgur.com/zGRvoKl.png) [example to control LED](https://github.com/shengwen-tw/stm32f4-examples/blob/master/firmware/peripheral/gpio_led/main.c) ## Lecture 3 [Linux Coding Style](https://github.com/torvalds/linux/blob/master/Documentation/process/coding-style.rst) **git project** ```sh= # create a git project directory mkdir (project name) # init your directory cd (project name) git init # it will create a .git file # setup your git user information git config --global user.name "user name" git config --global user.email "email address" # add your new file git add (your file) # commit git commit -m "what you want to said" # cheke current status git status #view history modification sudo apt install tig tig ``` ![](https://i.imgur.com/09jb8H1.png) [reference](https://ithelp.ithome.com.tw/articles/10156301) [reference](https://medium.com/@brianwu291/basic-git-command-line-collections-2242c03c870ehttps://medium.com/@brianwu291/basic-git-command-line-collections-2242c03c870e) **gcc** ```sh= gcc -g -o ${target name} ${file name} # -o 可指定编译后的可执行档名称(预设是a.out) # -g 可加入符号表(用于除错) ``` **debug** use gdb ```sh= # start gdb gdb -q (path of file) # gdb -q ./hello.elf ``` in gdb ```sh= # open file file (path of file) # file ./hello.elf # view variance list (variance) # list main # run run # break point b (行数) # b 12 # modify the value of variance / print p (variance = ?) # p num = 90 # go ito function for the details / step s # next step n # continue to next break point c ``` **deep copy and shallow copy** ```c= include <stdio.h> include <stdint.h> /* deep copy */ int face_detection(uint8_t img[100][100]) { img[5][5] = 100; return 0; } int main(void) { uint8_t img[100][100] = {0}; int ret = face_detection(img); print("%d", img[5][5]); return 0; } ``` ```c= include <stdio.h> include <stdint.h> /* shallow copy */ int face_detection(unit8_t *img) { *(img + 5*100 + 5) = 100; return 0; } int main(void) { uint8_t img[100][100] = {0}; int ret = face_detection((uint8_t *)img); printf("%d", img[5][5]); return 0; } ``` ## Lecture 4 **UART - Universal Asynchronous Reciever/Transmitter** **USART - Universal Synchronous Asynchronous Reciever/Transmitter** [detail](http://wiki.csie.ncku.edu.tw/embedded/USART) 通讯协定 RS-232 ![](https://i.imgur.com/yGlDPw9.png) ![](https://i.imgur.com/k6qPdrO.png) **Pin fot TX RX in stm32f4** ![](https://i.imgur.com/hIdoV5Z.png) **use usart to recieve and translate data in stm32** [example for using usart](https://github.com/shengwen-tw/stm32f4-examples/tree/master/firmware/peripheral/usart) - enable clock tree - enable clock tree of GPIO portC - enable clock tree of USART3 - enable the alternate function of GPIO - initialize - initial port - initial USART ![](https://i.imgur.com/WhAkUcF.png) **Interrupt in stm32** ```sh= # check what interrupt you can use vi starup_stm32f4xx.s # under external interrupts ``` - clock: 168MHz [example to use SysTick_Handler to count](https://github.com/shengwen-tw/stm32f4-examples/tree/master/firmware/peripheral/systick) **Functions of Files** ![](https://i.imgur.com/lwTWlMt.png) - lib: 在编译器link時需要明顯地指出.o文件名,這對於編譯很不方便,所以我們要給中間目標文件打個包,在Windows下這種包叫“庫文件”(Library File),也就是 .lib 文件。 - *.f (header file): 标头档 - *.c (source file): 直接编辑的原文件(c/c++)。 - *.o (object file): source file被compiled后产生的中间代码文件。 - *.s : source file被compiled后产生的组合语言文件。 - *.elf : source file被compiled后产生的可执行档,另外可用于gdb除错时引入的档案。 - *.bin : 将资料传入stm32时所需要的档案。 - *.ld : ? - makefile : 需要大量编译source file时可直接使用的脚本。 ## Lecture 6 **MMIO** **DMA** ## Lecture 7 **PWM (Pulse Width Modulation)** ![](https://i.imgur.com/gmameON.png) **Use PWM in stm32** - enable clock tree - enable clock tree of GPIO portD - enable clock tree of TIM - enable the alternate function of GPIO - initialize - initial port - initial time period, time prescaler (除频器) and time countermode - initial PWM ![](https://i.imgur.com/oZ1b0Eq.png) **Clock in stm32CubeIDE** ![](https://i.imgur.com/m6OwXc8.png) - internal clock source (RC circuit) - LSI (low speed internally) : 32kHz - HSI (high speed internally) : 16MHz - not accurate, becuase of its physical limit - external clock source (quartz crystal resonator) - LSE (low speed externally) : 0 - 1000 kHz - HSE (high speed externally) : 4 - 26 MHz - more accurate, but more energy consumption - [PLL (Phase-locked loops)](https://zh.wikipedia.org/wiki/%E9%94%81%E7%9B%B8%E7%8E%AF) - if you want to enable external clock source in stm32CubeIDE - under Pinout & Configuration -> System Core -> (check) RCC(reset clock control) -> High Speed Clock (or High Speed Clock) -> Crystal/Ceramic Resonator - set the value according to your hardware (we set 8) - ![](https://i.imgur.com/j5Jr5l1.png) - ![](https://i.imgur.com/lLlIUZe.png) - adjust other arguements - ![](https://i.imgur.com/nIA1I4F.png) - purple colors means your arguement violate its constraints - after adjusting - ![](https://i.imgur.com/IrTxkov.png) - complement - the input frequency of HSE in stm32f407 is 8MHz, so we define PLL_M is 8 in system_stm32f4xx.c. - [参考资料](https://lolikitty.pixnet.net/blog/post/142926586) [参考资料](https://blog.csdn.net/tcjy1000/article/details/50554312) - example - /home/ncrl/stm_ws/stm32f4-examples/firmware/peripheral/gpio_led/lib/CMSIS/system_stm32f4xx.c ![](https://i.imgur.com/XpXBpGv.png) - result of APB1 timer clock ![](https://i.imgur.com/MH5R81j.png) - /home/ncrl/stm_ws/stm32f4-examples/firmware/peripheral/pwm/main.c ![](https://i.imgur.com/PeOC0Ik.png) TIM_CounterMode_Up 上数计时器 每经过一个executing period, counter会+1。 - therefore, the executing frequency = frequancy of APB1 / (Period_Counter * Prescaler) the executing fequency = 84000000 / (1680 * 500) = 100 (Hz) the executing period = 10 ms [example for using PWM](https://github.com/shengwen-tw/stm32f4-examples/tree/master/firmware/peripheral/pwm) ![](https://i.imgur.com/XlDFoMl.png) ## Lecture 8 and Lecture 9 ### FreeRTOS (free real-time operating system) ###### [官方原始码](https://sourceforge.net/projects/freertos/) Realitime: 如果有一個任務需要執行,實時作業系統會馬上(在較短時間內)執行該任務,不會有較長的延時。 Schedule: 按照排序執行、管理系統資源 Introduce: FreeRTOS 是一個相對其他作業系統而言較小的作業系統。最小化的 FreeRTOS 核心僅包括 3 個 .c 文件(tasks.c、queue.c、list.c)和少數標頭檔,總共不到 9000 行程式碼,還包括了註解和空行。一個典型的編譯後 binary(二進位碼)小於 10 KB。 FreeRTOS 的程式碼可以分為三個主要區塊: - task: - 任務是擁有優先權的用戶所定義的 C 函數。task.c 和 task.h 負責所有關於建立、排程和維護任務的繁重工作。 - communication: - 任務間可以互相通訊則更為重要!FreeRTOS 核心程式碼大約有 40% 是用來處理通訊的。queue.c 和 queue.h 負責處理 FreeRTOS 的通訊,任務和中斷(interrupt)使用佇列(佇列,queue)互相發送數據,並且使用 semaphore 和 mutex 來派發 critical section 的使用信號。 - hardware interface: - 根据不同的硬体(arm, intel, IBM ...),软体与硬体间的沟通都不一样。 **Task** - example ```c= void task1() { int digitStatus = 1; while(1) { GPIO_WriteBit(GPIOD, GPIO_Pin_12, digitStatus); GPIO_WriteBit(GPIOD, GPIO_Pin_13, digitStatus); digitStatus = (digitStatus + 1) % 2; vTaskDelay(MILLI_SECOND_TICK * 1000); } } void task2() { int digitStatus = 1; while(1) { GPIO_WriteBit(GPIOD, GPIO_Pin_14, digitStatus); GPIO_WriteBit(GPIOD, GPIO_Pin_15, digitStatus); digitStatus = (digitStatus + 1) % 2; vTaskDelay(MILLI_SECOND_TICK * 1000); } } int main() { init_GPIO(); xTaskCreate(task1, "task1", 256, NULL, tskIDLE_PRIORITY + 2, NULL); xTaskCreate(task2, "task2", 256, NULL, tskIDLE_PRIORITY + 1, NULL); vTaskStartScheduler(); return 0; } ``` - explanation - xTaskCreate(function_pointer, task_name, memory_size, NULL, priority, NULL) - memory_size单位為word(在不同硬体平台中,实际大小不一样),这裡大小為4Bytes。 - 在freertos中,priority值越大,优先度越高。(在stm32中,priority值越小,优先度越高。) - 排程器 vTaskStartScheduler() : 决定哪个task被执行,哪个task不要被执行。 - scheduler对于资源(记忆体)的使用权限( kernel > user )。 ![](https://i.imgur.com/CuoiJNd.png) - SysTick决定什么时候schedule应该接受context switch的指令,将CPU资源给予task或从task拿回CPU资源。 - context switch : Context switch 是指 task A 要交出 CPU 使用權給 task B 時,OS 會將 task A 當前的狀態和暫存器內的資料存放到記憶體,再將先前 task B 的狀態從記憶體讀取至暫存器的過程。 **mutex 互斥锁 (用于资源管理)** 互斥锁是一种特殊的二值信号量,用于控制在两个或多个任务间访问共享资源。 ![](https://i.imgur.com/jlmIamv.png) - 优先权反转 **semaphore (用于资源同步)** semaphore可以是binary型态或者是counter型态。(在freertos中,semaphore跟mutex是一样的,只有API不一样而已。) * 事件技计数 * 资源管理 **deadlock** 当两个任务都在等待被对方持有的资源时,两个任务都无法再继续执行,这种情况就被称为死锁。 **schedule** 每个task都会被schedule定义成不同state task ![](https://i.imgur.com/giZQjmS.png) - Ready:準備好要執行的狀態 - Running:正在由 CPU 執行的狀態 - Blocked:等待中的狀態(通常是在等待某個事件) - Suspended:等待中的狀態(透過 API 來要求退出排程) ## Lecture 10 **logic analyzer** [saleae官网](https://www.saleae.com/) ![](https://i.imgur.com/4gWOhFc.png) ```sh= # start logic cd /home/ncrl/Downloads/Logic 1.2.18 (64-bit) sudo ./Logic ``` **NCRL - Flight Controller** ![](https://i.imgur.com/XmzHhnZ.png) ## Others **compile** ```sh= gcc (file name) ``` options: * -c : 只把程序做成obj文件。 ex: gcc -c (file name) * -o : 定义gcc编译出来的档案名称(预设是a.out)。 ex: gcc -o hello.exe hello.c * -g : 只是编译器,在编译的时候,产生调试信息。 **make file** * [make file学习教程](https://blog.xuite.net/tzeng015/twblog/113272267-Makefile%E5%AD%B8%E7%BF%92%E6%95%99%E7%A8%8B%3A+%E8%B7%9F%E6%88%91%E4%B8%80%E8%B5%B7%E5%AF%AB+Makefile) * [make file学习教程](https://hackmd.io/@sysprog/SySTMXPvl) **grep 基本用法** [UNIX 常用指令 - grep](https://marco79423.net/articles/unix-%E5%B8%B8%E7%94%A8%E6%8C%87%E4%BB%A4-grep/) **SPI** [参考网址](https://www.coderbridge.com/@bcewang/8d4643dff39e4dc4aadd022ac8fac517) [参考网址](http://www.ec66.com/article/list.asp?indexid=4538) [参考网址](https://youboook.pixnet.net/blog/post/98305922) [SPI Standard Driver Library](https://www.st.com/resource/en/user_manual/dm00023896-description-of-stm32f2xx-standard-peripheral-library-stmicroelectronics.pdf) ###### tags: `ncrl` `stm32`