1. 结构体的对齐

也就是数据对齐问题,可以说很经典了。按照其他人的总结,有以下3条规则:

  1. 每个结构体成员其起始位置,是它自身大小的整数倍。
  2. 如果成员中含有结构体(暂称为A),则该成员A的起始位置,是A这个结构体中的成员中最大的成员,的整数倍。
  3. 这个结构体的最终大小,必须是其所有成员,包括规则2中的A的成员,中最大的成员的整数倍。

举例:

typedef struct A{
	short a;
	char b;
	int c;
	char d;
}structA;


typedef struct B{
	int e;
	structA f;
	char g;
}structB;

在32位的STM32F1中,sizeof的结果是12个字节和20个字节。其中,structA是这么排的:首位的short为2个字节直接排,到了第二个的char时,起始位置是,2,因为char是1字节,2是1的整数倍,所以直接排,如下图:

接着是int,起始位置是3,而int字节为4,则需要补1位,使得int在4开始排。接下来的char因为字节是1,对正整数都是1的整数倍所以就不需要补位了。到这一共是2+1+1(补位)+4+1=9个字节,根据规则3,在这些成员中最大的字节数是4,2x4=8<9,3x4=12>9,所以再补3位,最终的结果就是12个字节如下图:

接下来看structB,e起始不管直接排,到f时,由于structA中最大的成员是int c, 也就是4个字节,所以要从4的整数倍开始排,刚好此时就是位置就是4,所以不用补,接下来排char g, 排完后此时是4+12+1=17个字节,由于a、b、c、d、e、f、g中最大的是4个字节,而4x4=16<17,4x5=20>17,所以再补3位最终的结果就是20个字节如下图:


 

 

2. tips若干

  • 在使用CMSIS-RTOS2封装的FreeRTOS时,特别注意修改stm32标准库中的HSE和system_stm32f10x.c中的分频系数,否则打印串口出现乱码或嘀嗒中断不标准。
  • 注意创建线程osThreadNew时分配足够的栈空间,否则会硬件中断。
  • RTX中的内存管理和FreeRTOS不同,前者需要先创建一个内存池对象后,再从这个对象中取出一块(block)来Alloc,后者是需要的时候直接Alloc,我的理解就是相当于后者在初始化操作系统的同时就已经创建好了内存池对象。
  • 在使用CMSIS-RTOS2封装的FreeRTOS时,调用osThreadNew传递的stack_size单位是字节,但是在osThreadNew函数中调用xTaskCreate创建任务前,根据

    Stack size should be therefore 4 byte aligned in order to avoid division caused side effects

    堆栈大小应4字节对齐

    会被除以4。在使用uxTaskGetSystemState函数调试时,得到的最小剩余堆栈usStackHighWaterMark同样是以字为单位而不是字节。