RT-Thread论坛
直播中

刘刚

8年用户 1120经验值
私信 关注
[问答]

MDK536 + SWM34S平台移植LVGL8.3.3 定义数组使用ALIGN()对齐时编译报错是什么原因导致的?

使用MDK536 SWM34S单片机 ENV下添加LVGL软件包8.3.3后,编译工程报错。提示出错在定义数组时使用ALIGN字节对齐,在lv_rt_thread_port.c中和一些样例代码文件中出现此错误,不知道是什么原因导致的,请教一下各位大神。
具体问题如下:
lv_rt_thread_port.c中  Line37:

  • static ALIGN(8) rt_uint8_t lvgl_thread_stack[PKG_LVGL_THREAD_STACK_SIZE];


会编译报错
img_cogwheel_indexed16.c等一些样例文件中,定义数组处,例如

  • const LV_ATTRIBUTE_MEM_ALIGN LV_ATTRIBUTE_IMG_IMG_COGWHEEL_INDEXED16 uint8_t img_cogwheel_indexed16_map[] = {...};


会编译报错。
查看 LV_ATTRIBUTE_MEM_ALIGN 是在lv_lv_rt_thread_conf.h文件中,Line74处定义

  • #define LV_ATTRIBUTE_MEM_ALIGN ALIGN(4)









回帖(1)

胖子的逆袭

2025-10-13 18:15:26

我们遇到的问题是在使用MDK5.36(Keil MDK版本5.36)和SWM34S单片机平台,在RT-Thread环境中添加LVGL 8.3.3软件包后,编译时出现了关于ALIGN()对齐宏的报错。

首先,我们需要了解ALIGN宏在RT-Thread中的定义。在RT-Thread中,ALIGN宏通常用于指定变量或数组的内存对齐。在RT-Thread的头文件(可能是rtdef.h或者其他)中,ALIGN宏通常定义为:
```c
#define ALIGN(n) __attribute__((aligned(n)))
```
或者对于某些编译器,它可能使用其他方式(如#pragma pack等)。

但是,在Keil MDK(ARMCC或ARMCLANG)中,对齐属性通常使用`__align(n)`(对于ARMCC)或`__attribute__((aligned(n)))`(对于ARMCLANG)来指定。

从错误信息来看,报错的位置是在`lv_rt_thread_port.c`文件中的第37行:
```c
static ALIGN(8) rt_uint8_t lvgl_thread_stack;
```
以及一些示例文件中的数组定义,如:
```c
const LV_ATTRIBUTE_MEM_ALIGN LV_ATTRIBUTE_IMG_IMG_COGWHEEL_INDEXED16 uint8_t img_cogwheel_indexed16_map[] = {...};
```

可能的错误原因和解决方法:

1. **编译器支持问题**:ALIGN宏可能没有被正确定义,或者当前使用的编译器不支持该宏的定义方式。

   在RT-Thread中,ALIGN宏通常在`rtdef.h`中定义。对于ARMCC(Keil的旧版编译器),它可能是这样定义的:
   ```c
   #if defined(__CC_ARM) || defined(__CLANG_ARM)
       #define ALIGN(n) __attribute__((aligned(n)))
   #elif defined (__IAR_SYSTEMS_ICC__)
       /* IAR */
       #define ALIGN(n) _Pragma(#n)
   #else
       /* 其他编译器 */
       #define ALIGN(n) __attribute__((aligned(n)))
   #endif
   ```
   但是,在MDK5.36中,默认使用的是ARMCLANG(基于Clang),它支持`__attribute__((aligned(n)))`。所以,如果定义不正确,可能会导致问题。

2. **宏定义冲突**:有可能ALIGN宏在其他地方被重复定义,或者与某些头文件中的定义冲突。

3. **LVGL的配置问题**:在LVGL中,`LV_ATTRIBUTE_MEM_ALIGN`宏用于指定对齐方式。在`lv_conf.h`中,这个宏通常定义为:
   ```c
   #define LV_ATTRIBUTE_MEM_ALIGN __attribute__((aligned(4)))
   ```
   但也可以根据需要进行修改。如果这个宏定义不正确,也会导致错误。

4. **编译器的版本问题**:MDK5.36使用的是ARMCLANG,它可能要求更严格的语法。例如,在C语言中,对齐属性应该放在变量名之前,但在某些情况下,如果放在类型前面可能不被接受(不过,GCC和Clang都支持放在类型前,但标准中更常见的是放在变量名后)。不过,在RT-Thread的代码中,ALIGN宏通常放在类型前面,这在GCC和Clang中都是允许的。

   **注意**:在C语言中,对齐属性可以放在类型之前或之后。例如:
   ```c
   // 方式1:放在类型前
   __attribute__((aligned(8))) static int a;
   // 方式2:放在变量后
   static int a __attribute__((aligned(8)));
   ```
   但是,如果宏定义的方式导致展开后语法错误,就会报错。

   在`lv_rt_thread_port.c`中,使用方式是:
   ```c
   static ALIGN(8) rt_uint8_t lvgl_thread_stack;
   ```
   展开后应该是:
   ```c
   static __attribute__((aligned(8))) rt_uint8_t lvgl_thread_stack;
   ```
   这种写法在Clang中是允许的。

5. **RT-Thread的ALIGN宏定义缺失或错误**:检查RT-Thread中ALIGN宏的定义。在rtdef.h文件中,应该有如下的定义:
   ```c
   #if defined(__CC_ARM)
       #define ALIGN(n) __align(n)
   #elif defined (__IAR_SYSTEMS_ICC__)
       #define ALIGN(n) _Pragma(#n)
   #elif defined (__GNUC__)
       #define ALIGN(n) __attribute__((aligned(n)))
   #endif
   ```
   然而,对于ARMCLANG(即MDK5.36使用的编译器,它使用`__ARMCC_VERSION`宏来标识),我们需要确认是否已经正确处理。

   实际上,在较新的RT-Thread版本中,对于ARMCLANG(即ARM Compiler 6)的支持已经添加。例如:
   ```c
   #ifdef __ARMCC_VERSION
       #define ALIGN(n) __attribute__((aligned(n)))
   #endif
   ```
   如果RT-Thread的版本较旧,可能没有对ARM Compiler 6(ARMCLANG)进行定义。

**解决方案:**

1. **检查RT-Thread中的ALIGN宏定义**:打开`rtdef.h`(通常在`components/libc/compilers/common`或类似路径),查看ALIGN宏的定义是否支持ARMCLANG。如果没有,可以手动添加:
   ```c
   #if defined(__ARMCC_VERSION) || defined(__CC_ARM)
       /* ARM Compiler 4/5/6 */
       #if defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)
           /* ARM Compiler 6 */
           #define ALIGN(n) __attribute__((aligned(n)))
       #else
           /* ARM Compiler 4/5 */
           #define ALIGN(n) __align(n)
       #endif
   #elif defined (__IAR_SYSTEMS_ICC__)
       /* IAR Compiler */
       #define ALIGN(n) _Pragma(#n)
   #elif defined (__GNUC__)
       /* GNU Compiler */
       #define ALIGN(n) __attribute__((aligned(n)))
   #else
       #error "Please specify the alignment attribute for your compiler."
   #endif
   ```

2. **检查LVGL的配置**:在`lv_conf.h`中,确保`LV_ATTRIBUTE_MEM_ALIGN`定义正确。对于ARMCLANG,应该使用:
   ```c
   #define LV_ATTRIBUTE_MEM_ALIGN __attribute__((aligned(4)))
   ```

3. **如果问题仍然存在**,可以尝试修改`lv_rt_thread_port.c`中的代码,将ALIGN宏放在变量名的后面(虽然RT-Thread中通常不这样写):
   ```c
   static rt_uint8_t lvgl_thread_stack ALIGN(8);
   ```
   但是,这种方法可能会引起代码风格不一致。或者,我们也可以直接使用`__attribute__((aligned(8)))`来替换ALIGN(8),以测试是否是宏定义的问题。

4. **确保RT-Thread的版本支持ARMCLANG**:如果RT-Thread版本较旧,可能需要更新RT-Thread版本,或者手动修改ALIGN宏的定义。

5. **检查编译器的宏定义**:在MDK5.36中,ARMCLANG定义的宏是`__ARMCC_VERSION`,其值是一个数字(例如6010050代表版本6.1)。可以在编译器设置中添加`--list_macros`来查看预定义的宏,或者在代码中打印`__ARMCC_VERSION`来确认。

6. **样例文件的错误处理**:对于样例文件(如img_cogwheel_indexed16.c)中的错误,同样是由于对齐宏`LV_ATTRIBUTE_MEM_ALIGN`引起的。因此,只要确保`LV_ATTRIBUTE_MEM_ALIGN`正确展开为编译器支持的对齐属性即可。

综上所述,请先检查并修改RT-Thread中`rtdef.h`关于ALIGN宏的定义,确保它支持ARMCLANG(ARM Compiler 6)。然后,检查`lv_conf.h`中的对齐宏定义。这样应该可以解决对齐编译错误。

在 MDK5.36 + SWM34S 平台上移植 LVGL 8.3.3 时遇到 ALIGN() 对齐导致的编译错误,通常由以下原因及解决方案引起:




问题原因




  1. 编译器兼容性问题

    MDK5.36 默认使用 ARMClang(AC6) 编译器,而 RT-Thread 的 ALIGN 宏可能未针对 AC6 适配:


    // RT-Thread 旧版本中 ALIGN 的定义可能未覆盖 AC6
    #if defined (__CC_ARM)
       #define ALIGN(n) __attribute__((aligned(n))) // ARMCC5
    #elif defined (__CLANG_ARM)
       #define ALIGN(n) __attribute__((aligned(n))) // AC6 需要此分支
    #else
       #error "Unsupported compiler"
    #endif



  2. LVGL 对齐宏冲突

    LV_ATTRIBUTE_MEM_ALIGNlv_conf.h 中的定义可能未适配 AC6:


    #define LV_ATTRIBUTE_MEM_ALIGN  // 默认可能为空或不适配



  3. 头文件包含顺序问题

    RT-Thread 的 rtdef.h(定义 ALIGN)可能未被正确包含。






解决方案


1. 更新 RT-Thread 的 ALIGN 宏定义


rtconfig.hrtdef.h 中显式添加 AC6 支持:


   #if defined(__ARMCC_VERSION) || defined(__CC_ARM)
       #if __ARMCC_VERSION >= 6000000
           /* ARM Compiler V6 (AC6) */
           #define ALIGN(n) __attribute__((aligned(n)))
       #else
           /* ARM Compiler V5 */
           #define ALIGN(n) __align(n)
       #endif
   #endif

2. 修正 LVGL 对齐宏


lv_conf.h 中明确定义对齐属性:


   #define LV_ATTRIBUTE_MEM_ALIGN __attribute__((aligned(4)))  // 4字节对齐

3. 修改代码中的对齐语法


ALIGN 移至变量名后(AC6 推荐写法):


   // 修改前
   static ALIGN(8) rt_uint8_t lvgl_thread_stack;

   // 修改后
   static rt_uint8_t lvgl_thread_stack ALIGN(8);

4. 检查头文件包含顺序


确保在包含 LVGL 文件前已包含 RT-Thread 核心头文件:


   #include   // 包含 rtdef.h
   #include "lvgl.h"      // 之后包含 LVGL

5. 样例文件的临时解决方案


若样例文件报错,可暂时禁用严格对齐:


   // 在 lv_conf.h 中
   #define LV_ATTRIBUTE_MEM_ALIGN  // 定义为空(不推荐长期使用)



验证步骤



  1. 修改 rtdef.hrtconfig.h 确保 ALIGN 支持 AC6。

  2. 更新 lv_conf.h 中的 LV_ATTRIBUTE_MEM_ALIGN

  3. 调整变量声明语法:type var ALIGN(n);

  4. 清理并重新编译工程(Rebuild All)。



注意:SWM34S 是 Cortex-M33 内核,对齐要求通常为 4/8 字节。确保对齐值符合硬件要求(如栈需 8 字节对齐)。



通过以上步骤,应能解决因对齐宏导致的编译错误。如问题仍存,请检查 MDK 的编译器选项是否已设置为 AC6(Project → Options → Target → ARM Compiler)。

举报

更多回帖

发帖
×
20
完善资料,
赚取积分