打印
[APM32F0]

APM32F003应用实例: 在keil MDK中定义非初始化(noini)变量的实际应用

[复制链接]
1229|2
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
david-lau|  楼主 | 2024-8-8 17:44 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 david-lau 于 2024-8-8 17:53 编辑

在单片机编程中,变量未初始化是一个常见的问题,有时会导致程序出现一些难以预料的行为。不过,在某些情况下,这种"未初始化"的特性也可能会带来一些意想不到的好处。本文将探讨APM32F003微控制器中,未初始化变量得的一些实际应用场景。

APM32F003 RAM的特殊初始化机制

APM32F003是一款基于ARM Cortex-M0+内核的32位微控制器。对于RAM存储区有一个特殊的初始化机制,如果芯片保持不断电,APM32F003的RAM在复位或休眠唤醒时并不一定要是全部初始化为0,还可以保留之前的值。这意味着未初始化的变量会保留上次程序运行时的值。

这种行为可能会在某些情况下引起困扰,但如果善加利用,也可以派上用场。让我们看看几个实际应用例子:

1. 状态机实现

在实现状态机时,未初始化的状态变量可以用来表示系统的初始状态。程序上电后,状态变量的值就是未定义的,恰好可以用来标识系统刚刚启动的初始状态。这样就无需在代码中专门定义一个"初始状态"变量。
typedef enum {
    STATE_INIT,
    STATE_RUN,
    STATE_STOP,
    STATE_POWERON
} system_state_t;

system_state_t current_state __attribute__((section("NoInit"), zero_init));

void main() {
    // 上电后,current_state自动处于初始状态STATE_INIT
    while (1) {
        switch (current_state) {
            case STATE_INIT:
                // 初始化逻辑
                current_state = STATE_RUN;
                break;
            case STATE_RUN:
                // 运行逻辑
                break;
            case STATE_STOP:
                // 停止逻辑
                break;
            case STATE_POWERON:
                // 上电逻辑
                break;
            default:
                // 未知状态处理
                break;
        }
    }
}



2. 断电恢复

在需要断电恢复的场景中,未初始化的变量可以用来判断系统是否刚刚从断电状态恢复。例如,你可以将一个标志位变量设置为未初始化状态,在恢复逻辑中检查该变量的值,来决定是否需要执行特殊的恢复操作。
uint16_t power_restored_flag __attribute__((section("NoInit"), zero_init));

void main() {
    // 检查power_restored_flag是否处于未初始化状态
    if (power_restored_flag != 0x55AA) {
        // 执行断电恢复逻辑
        power_restored_flag = 0x55AA; // 设置标志位为特定值
    } else {
        // 正常运行逻辑
    }
}

3. 低功耗模式

在低功耗模式下,MCU会进入睡眠状态,只有在特定事件发生时才会被唤醒。未初始化的变量可以用来标记唤醒原因,避免在唤醒后需要重新初始化状态。

uint8_t wakeup_source __attribute__((section("NoInit"), zero_init));

void main() {
    while (1) {
        // 正常运行逻辑
        enter_low_power_mode();

        // 检查唤醒源
        if (wakeup_source == 0xFF) { // 未初始化时为0xFF
            // 由定时器唤醒
        } else if (wakeup_source == 0x55) {
            // 由外部中断唤醒
        } else {
            // 未知唤醒源
        }

        // 根据唤醒源执行相应的恢复操作
        switch (wakeup_source) {
            case 0xFF:
                // 定时器唤醒恢复逻辑
                break;
            case 0x55:
                // 外部中断唤醒恢复逻辑
                break;
            default:
                // 未知唤醒源处理逻辑
                break;
        }

        // 重置唤醒源标志
        wakeup_source = 0;
    }
}

4. 关闭只能复位才能关闭的外设

某些外设,比如独立看门狗(IWDT,WWDT)在正常运行过程中无法被关闭,只能通过复位才能关闭。但在某些情况下,我们需要在程序运行时关闭这些外设,比如在系统需要进入低功耗或出现故障时。

利用未初始化变量的特性,我们可以通过检查变量的值来判断系统是否刚刚复位,从而决定是否需要关闭IWDT等外设。
uint16_t iwdt_disabled_flag __attribute__((section("NoInit"), zero_init));

void main() {
    // 检查iwdt_disabled_flag是否处于未初始化状态
    if (iwdt_disabled_flag != 0x55aa) {
        // 启动独立看门狗(IWDT)
        IWDT_Init(freqLIRC);
    }

    // 正常运行逻辑
    while (1) {
        // 其他工作...

        if (sleep_flag) {
            // 进入睡眠模式
            iwdt_disabled_flag = 0x55aa; // 设置标志位,下次不启动IWDT
            enter_low_power_mode();
        }
    }
}


以上几个例子展示了如何利用APM32F003 RAM未初始化的特性来简化代码逻辑,提高程序的健壮性。当然,在实际应用中还需要结合具体需求来权衡使用。合理利用这一特性,可以让你的APM32F003项目获得意想不到的收益。

如下是在Keil中的具体用法:1,修改SCT文件:
; *************************************************************
; *** Scatter-Loading Description File generated by uVision ***
; *************************************************************

LR_IROM1 0x00000000 0x00008000  {    ; load region size_region
  ER_IROM1 0x00000000 0x00008000  {  ; load address = execution address
   *.o (RESET, +First)
   *(InRoot$Sections)
   .ANY (+RO)
   .ANY (+XO)
  }
<font color="#ff0000">  RW_IRAM1 0x20000000 UNINIT 0x00000100  { ;no init section
   *(NoInit)
  }</font>
  RW_IRAM2 0x20000100 0x00000F00  {                ;all other RW data
   .ANY(+RW +ZI)
  }
}
2,在代码中声明变量:

unsigned char NI_charVar __attribute__( ( section( "NoInit"),zero_init) ) ;


使用特权

评论回复
沙发
caigang13| | 2024-8-9 07:55 | 只看该作者
所以在定一个变量时最好同时赋值一个初值。

使用特权

评论回复
板凳
dalong-168| | 2024-8-9 11:41 | 只看该作者
学习了

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

7

主题

42

帖子

1

粉丝