嗨,everyboady,
我已经使用app_easy定时器来做一个Led闪烁功能。但在我闪过spi flash的代码后,设备继续重新启动。我调试了代码,看到程序进入blink函数和被调用的app_easy_timer函数。
程序永远不会进入代码(req->delay=delay;申请- > timer_id = timer_id;ke_msg_send(要求的);
在它执行代码(struct create_new_timer_struct *req = KE_MSG_ALLOC(APP_CREATE_NEW_TIMER, TASK_APP, TASK_APP, create_new_timer_struct);
这是否意味着内存分配错误,是否因为这个原因导致重新启动?我以前从未遇到过这种现象
设备:
你好,
您是否尝试在SDK5中运行带有app_easy_timer特性的“prox_reporter”参考软件?您所描述的观察结果不能得出这个问题是由“app_easy_timer”函数引起的。您需要更多的信息,例如如何运行您的测试,在什么软件上,....
当做
你好,我是瓦鲁对话,
我知道app_easy_timer是问题所在,因为在我将led blink部分的代码添加到dsps-host项目之前,我也有一个使用app-easy-timer的进程,它工作得很好。
我想知道的是,我只是使用一个app-easy-timer来切换led引脚,为什么我有块在代码
struct create_new_timer_struct *req = KE_MSG_ALLOC(APP_CREATE_NEW_TIMER, TASK_APP, TASK_APP,create_new_timer_struct);
下面是led的源代码
#包括“led.h”
# include“app_easy_timer.h”
/* LED控制结构*/
typedef struct {
uint8_t待办事项;/*闪烁周期左*/
uint8_t百分比;/*周期百分比*/
uint16_t时期;/*打开/关闭周期时间(msec) */
uint32_t下;/*下一次修改的时间
} LedControl_t;
/***************************************************************************************************
*全局变量
***************************************************************************************************/
static LedControl_t leddctrl __attribute__((section("retention_mem_area0"),zero_init));
/***************************************************************************************************
*本地函数
***************************************************************************************************/
static void LedUpdate (void);
/***************************************************************************************************
*函数- API
***************************************************************************************************/
/***************************************************************************************************
* @fn LedInit
*
* @brief初始化LED服务
*
* @param init -指向void的指针,包含初始化的值
*
* @return没有
***************************************************************************************************/
空白LedInit(空白)
{
LED_INIT ();
}
/***************************************************************************************************
* @fn LedBlink
*
* @brief闪烁led灯
*
* @param leds - led闪烁的位掩码值
* numBlinks -闪烁次数
* percent -每段时间内领先的百分比
*将会开始
* period -每个周期的长度,单位为毫秒
*
* @return没有
***************************************************************************************************/
void LedBlink (uint8_t numBlinks, uint8_t percent, uint16_t period)
{
ledCtrl。todo = 2 * numBlinks-1;
ledCtrl。% = %;
ledCtrl。时间=时期;
LED_OFF ();
If (percent && period)
{
If (percent < 100)
{
LedUpdate app_easy_timer(1日);
}
其他的
{
LED_ON ();
}
}
其他的
{
/ /关闭
LED_OFF ();
}
}
/***************************************************************************************************
* @fn LedUpdate
*
* @brief更新led与blink工作
*
* @param没有
*
* @return没有
***************************************************************************************************/
static void LedUpdate (void)
{
LED_TOGGLE ();
ledCtrl.todo——;
如果(ledCtrl。todo / * | | LED_STATE () * /)
{
如果(LED_STATE ())
{
ledCtrl。下一个= ledCtrl.period * (100 - ledctrl.percent);
}
其他的
{
ledCtrl。下一个= ledCtrl.period * ledCtrl.percent;
}
app_easy_timer (LedUpdate ledCtrl.next / 10日);
}
}
你能帮我检查一下代码是否有错误吗,我真的找不到原因。
另外,我只是使用LedInit初始化LED端口和LedBlink(20,35,1000)在System_Init()中做测试。
再多一点,我发现我在system_init中调用LedBlink(),我将得到持续重启后,我的flash代码到flash。但是如果我在system_init()之后的main_func()中调用LedBlink(),这种现象不会发生,但我永远无法调用LedUpdate()。当按钮被按下时,我还启动了一个计时器,当计时器过期时,我可以得到这个计时器的回调。这真的让我很困惑,任何建议都将不胜感激!
你好,
你的问题与你的“LedBlink(20,351000)”声明的位置有着恰当的关联。这是因为app_easy_timer和malloc()需要内核计时器和堆服务。您的函数只能在内核初始化和激活后调用。建议将语句放在system_init()之后,并使LedBlink函数永远闪烁,以便于调试。
int main_func(空白)
{
sleep_mode_t sleep_mode;
/ /全局初始化
系统初始化();
LedBlink (20, 1000);
/*
************************************************************************************
*平台初始化
************************************************************************************
*/
而(1)
{
.....
}
}
当做
我已经按照你的建议做了,但我还是看不出来。现在我在设备连接事件上调用了LedBlink, led右闪。所以是不是因为祝福让我们睡觉了所以我们不能启动计时器?
你好,
在进入睡眠模式之前,应该没有任何活动,包括LED闪烁。无论在扩展或深度睡眠模式下,所有的I/O块都将被关闭,包括定时器服务。因此,LED blink定时器服务被禁用。
为了简化新驱动程序或函数的调试,最简单的方法是添加如下语句:禁用进入睡眠模式但进入空闲模式,以使对软件行为的影响降到最低。
//获取允许的睡眠模式
//从rwip_power_down()到WFI()的时间必须尽可能短!!
sleep_mode = rwip_power_down ();
/*语句添加*/ sleep_mode = mode_idle;
然后你应该看到你的LED连续闪烁。
当做
你好,
修正错误如下:
//获取允许的睡眠模式
//从rwip_power_down()到WFI()的时间必须尽可能短!!
sleep_mode = rwip_power_down ();
/* * * * * *
If ((sleep_mode == mode_ext_sleep) || (sleep_mode == mode_deep_sleep)) / /将睡眠模式设置为睡眠模式
{
sleep_mode = mode_idle;
}
当做
让我困惑的是:
我在system_init()之后调用LedBlink(),当计时器内核上升时。在LedBlink()中,我设置了一个定时器来唤醒BLE,那么为什么我的定时器回调仍然不能被触发?当我第一次在LedBlink()中创建定时器时,如果BLE是睡眠的,如果这是真的?我想在我第一次创造计时器之前我可以强迫ble醒来。我已经尝试了API arch_ble_force_wakeup(), arch_ble_ext_wakeup_on()等,但仍然不能闪烁。这些api真的能强制设备唤醒吗?
你好,
验证LedBlink()函数及其行为的技术可以通过简单地强制sleep_mode不进入mode_ext_sleep或mode_deep_sleep来实现。为了集成LED闪烁功能,并让它按照您的预期运行,您需要了解软件是如何构造的。
在实际应用中,有两个独立运行的线程,BLE栈和User应用。内核只提供服务和用户应用程序需要管理和监督所有资源的使用和监控所有活动,以确定设备是否可以进入睡眠模式。
int main_func(空白)
{
sleep_mode_t sleep_mode;
/ /全局初始化
系统初始化();
/*
************************************************************************************
*平台初始化
************************************************************************************
*/
而(1)
{
{做
//调度所有挂起的事件
schedule_while_ble_on ();
}
while (app_asynch_proc() != GOTO_SLEEP);//将控制权限授予应用程序,尝试关闭电源
//如果应用程序返回GOTO_SLEEP
.....
}
}
app_asynch_proc()函数用于检查用户应用程序是否正在进行任何活动,以防止设备在BLE堆栈线程准备进入睡眠时进入睡眠模式。
typedef enum {
GOTO_SLEEP=0,
KEEP_POWERED
} arch_main_loop_callback_ret_t;
在您的情况下,只要LED闪烁不允许设备进入睡眠状态,此功能就可以返回“保持供电”。
静态内联void schedule_while_ble_on(void)
{
//开启BLE时钟
而(ble_is_powered ())
{
//设置BLE事件结束。有条件的射频校准可以运行。
uint8_t ble_end_set = ke_event_get(KE_EVENT_BLE_EVT_END);
//执行消息和事件
rwip_schedule ();
如果(ble_evt_end_set)
{
Uint32_t sleep_duration = 0;
rcx20_read_freq ();
//如果你有足够的时间,对收音机进行温度校准
如果(lld_sleep_check(&sleep_duration, 4)) //6个槽-> 3.750 ms . If (lld_sleep_check(&sleep_duration, 4)
//检查运行无线电校准的时间和温度。
conditionally_run_radio_cals ();
}
//将控制权授予应用程序,尝试进入睡眠
//如果应用程序返回GOTO_SLEEP
if (app_asynch_trm() != GOTO_SLEEP)
{
继续;//再次调用rwip_schedule(
}
其他的
{
arch_printf_process ();
打破;
}
}
}
app_asynch_trm()函数在BLE堆栈运行时处理用户应用程序。rwip_schedule()将处理队列中的所有消息,直到完成,控制将传递给app_asynch_trm()函数,并根据返回的值“KEEP_POWERED”或“GOTO_SLEEP”决定保持活动状态或进入睡眠状态。
请注意,没有跟踪任何软件定时器是否运行的功能。软计时器的所有者的责任是跟踪它的活动。
要在SDK5中开发应用程序,建议学习以下结构并理解其工作原理,因为它是SDK5结构的关键。
struct arch_main_loop_callbacks {
空白(* app_on_init)(空白);
arch_main_loop_callback_ret_t (* app_on_ble_powered)(空白);
arch_main_loop_callback_ret_t (* app_on_system_powered)(空白);
空白(* app_before_sleep)(空白);
sleep_mode_t (* app_validate_sleep) (sleep_mode_t sleep_mode);
空白(* app_going_to_sleep) (sleep_mode_t sleep_mode);
空白(* app_resume_from_sleep)(空白);
};
Static const struct arch_main_loop_callbacks user_app_main_loop_callbacks = {
.app_on_init = default_app_on_init,
//默认情况下,看门狗定时器在系统唤醒时重新加载并恢复。
//用户必须考虑看门狗定时器的处理(保持它运行,
//冻结它,重新加载它,恢复它,等等),当app_on_ble_powered()正在
//调用,并可能潜在地影响主循环。
.app_on_ble_powered=NULL,
//默认情况下,看门狗定时器在系统唤醒时重新加载并恢复。
//用户必须考虑看门狗定时器的处理(保持它运行,
//冻结它,重新加载它,恢复它,等等),当app_on_system_powered()正在
//调用,并可能潜在地影响主循环。
.app_on_system_powered =零,
.app_before_sleep =零,
.app_validate_sleep =零,
.app_going_to_sleep =零,
.app_resume_from_sleep =零,
};
当做
非常感谢,非常有用的建议