STM32 启动流程是怎样的?
根据启动模式,从不同的存储器加载程序运行。
STM32的启动代码在startup_stm32f10x_xx.s(xx根据微控制器所带的大、中、小容量存储器分别为hd、md、ld)中,其中的程序功能主要包括初始化堆栈、定义程序启动地址、中断向量表和中断服务程序入口地址,以及系统复位启动时,从启动代码跳转到用户main函数的入口地址。
原文链接:https://blog.csdn.net/wwt18811707971/article/details/78678059
SRAM和RAM的区别?
SRAM是静态RAM,速度快,价格贵。
SWD下载和调试程序时,boot引脚要怎么连接?
貌似不影响。
ISP是什么意思?
ISP(in-system programming)--在线系统编程
STM32的中断处理时怎样的?
从地址80000000开始执行,然后跑到reset中断,然后跳到main函数。
参考:https://www.cnblogs.com/long5683/p/9638866.html
STM32 IAP官方例子
https://www.st.com/en/embedded-software/x-cube-iap-usart.html
串口怎么判断数据结束的?
通过结束位和开始位,结束时高电平,如果后面继续时高电平,说明本次结束了。如果时低电平,说明是下一个数据到了。
HAL_Delay实现原理?
在一个while循环里面等待SysTick的滴答计时到达。注意不能放在中断里面,否则会卡死。
stm32 几个关键的地址
外设起始地址
define PERIPH_BASE 0x40000000UL /*!< Peripheral base address in the alias region */
define APB2PERIPH_BASE (PERIPH_BASE + 0x00010000UL)
define USART1_BASE (APB2PERIPH_BASE + 0x1000UL)
所以串口1的地址是0x40000000UL + 0x00010000UL + 0x1000UL = 0x40011000
typedef struct
{
__IO uint32_t SR; /*!< USART Status register, Address offset: 0x00 /
__IO uint32_t DR; /!< USART Data register, Address offset: 0x04 /
__IO uint32_t BRR; /!< USART Baud rate register, Address offset: 0x08 /
__IO uint32_t CR1; /!< USART Control register 1, Address offset: 0x0C /
__IO uint32_t CR2; /!< USART Control register 2, Address offset: 0x10 /
__IO uint32_t CR3; /!< USART Control register 3, Address offset: 0x14 /
__IO uint32_t GTPR; /!< USART Guard time and prescaler register, Address offset: 0x18 */
} USART_TypeDef;
可以看到,限制都是通过结构体的方式来操作寄存器了。
有什么常见的简称?
Interrupt Request,简称IRQ
NMI,不可屏蔽中断
什么是临界段代码?
代码的临界段也称为临界区,一旦这部分代码开始执行,则不允许任何中断打断。
stm32 如何关闭中断?
vPortRaiseBASEPRI
MRS与MSR寄存器是什么?
MRS: 状态寄存器到通用寄存器的传送指令。
MSR: 通用寄存器到状态寄存器的传送指令。
BASEPRI是什么?
设置为n后,屏蔽所有优先级数值大于等于n的中断和异常。Cortex-M的优先级数值越大其优先级越低。
参考:https://www.cnblogs.com/qiyuexin/p/8921718.html
HAL_NVIC_SetPriority的函数输入是怎么对应优先级的?
值越小,优先级越高
FreeRTOS任务切换过程?
https://blog.csdn.net/jiejiemcu/article/details/81039707
串口中断发送方式是怎样的?
起始就是给usart结构体先赋值,然后开中断
__HAL_UART_DISABLE_IT(huart, UART_IT_TXE);
一个个字节赋值给DR寄存器,然后发出去。
STM32为什么要把代码烧到flash的0x0800000中去?
STM32开机会进行地址映射,在访问0x0000000时,会通过memmap,转换成0x08000000,进而访问flash。
要记住两个关键的地址:flash起始地址:0x08000000, ram起始地址0x20000000
至于为什么要写到0x08000000,据说时这样就有两个地址对应同一个物理地址,可以加快访问速度。例如(0x00000000和0x08000000都是对应flash的0x08000000地址)
参考:https://blog.csdn.net/weixin_42231514/article/details/106178653?utm_medium=distribute.pc_relevant.none-task-blog-title-7&spm=1001.2101.3001.4242
stm32一个字是多少字节?
stm32是32位的,所以一个字是32位,4个字节。
FreeRTOS的启动原理
通过pendsv和systick中断,来进行切换的。
FreeRTOS临界区怎么操作
使用vPortEnterCritical,进而是调用vPortRaiseBASEPRI(),
实际是把寄存器basepri的值设置成了0x50了
Stm32 HAL库一般是怎么管理寄存器的?
一般是结构体管理,每个结构体都有一个基地址
例如系统配置寄存器
#define SCB ((SCB_Type *) SCB_BASE ) /*!< SCB configuration struct */
typedef struct
{
__IM uint32_t CPUID; /*!< Offset: 0x000 (R/ ) CPUID Base Register */
__IOM uint32_t ICSR; /*!< Offset: 0x004 (R/W) Interrupt Control and State Register */
#if defined (__VTOR_PRESENT) && (__VTOR_PRESENT == 1U)
__IOM uint32_t VTOR; /*!< Offset: 0x008 (R/W) Vector Table Offset Register */
#else
uint32_t RESERVED0;
#endif
__IOM uint32_t AIRCR; /*!< Offset: 0x00C (R/W) Application Interrupt and Reset Control Register */
__IOM uint32_t SCR; /*!< Offset: 0x010 (R/W) System Control Register */
__IOM uint32_t CCR; /*!< Offset: 0x014 (R/W) Configuration Control Register */
uint32_t RESERVED1;
__IOM uint32_t SHPR[2U]; /*!< Offset: 0x01C (R/W) System Handlers Priority Registers. [0] is RESERVED */
__IOM uint32_t SHCSR; /*!< Offset: 0x024 (R/W) System Handler Control and State Register */
} SCB_Type;
就规定了SCB这个SCB_Type结构体实例的地址是SCB_BASE
使能中断,实际修改的是什么寄存器呢?
HAL_NVIC_EnableIRQ修改的是ISER寄存器
FreeRTOS进行bootloader跳转时,需要注意什么?
需要关闭中断,一般我们都会关闭外设的中断,但其实了解FreeRTOS的切换任务流程后,可以知道任务切换时依赖systick中断的,所以我们一定要把systick中断也关闭掉。不然如果我们在app一开始调用__enable_irq()的时候,就会找不到中断处理函数,然后跑飞。关闭systick中断:
SysTick->CTRL = SysTick->CTRL & 0xFFFFFF00;
FreeRTOS的systick中断是在函数vPortSetupTimerInterrupt()中使能的。
stm32和freeRTOS的堆栈是怎样管理的?
在有freeRTOS时,他的map文件如下,可以看到堆栈时从0x0000000020015858开始,因为ram的基地址是0x0000000020000000,所以FreeRTOS总共占用了0x15858,转成10进制,约等于80K。从80K后面的就不属于freeRTOS管理。
从图片可以看出,堆和栈的空间是完全分开的。
这些不受freeRTOS管理的内存。
栈地址是:
0x0000000020015e58 到 0x0000000020015a58 可以看到是向下生长的。
堆地址是:
0x0000000020015858 到 0x0000000020015a58 可以看到是向上生长的。
下图是一个栈数据溢出到堆区,然后被堆区数据memset为0后,出现hard fatal的实际例子。
FreeRTOS堆和栈的配置如下,也可以单独配置Task的栈大小
什么是freertos的优先级继承?
就是低优先级A的拿到互斥锁之后,然后一个高优先级的任务B要来拿锁,但A现在持有,所以B只能挂起来,为了尽快拿到锁,得让低优先级尽快跑完,不然任务B可能一直阻塞(如果来了个比B低优先级的任务C,因为B在阻塞,C就先跑了,这就导致了优先级反转,明明B优先级高,却任务C先跑),于是系统就把A的优先级调高到B的水平。