Hi, everyboady,
I have used the app_easy timer to do a Led blink function. but the device reboot continuous after I flashed the code to spi flash. I debuged the code and see that porgram goes into the blink function and the invoked app_easy_timer function.
the program never goes forward to code ( req->delay=delay; req->timer_id=timer_id; ke_msg_send(req);)
after it excute the code (struct create_new_timer_struct *req = KE_MSG_ALLOC(APP_CREATE_NEW_TIMER, TASK_APP, TASK_APP, create_new_timer_struct);
is it mean that memory alloc error,and is the reboot caued by this reason? I never encountered this phenomenon ever before
Device:
Hi,
Do you try running the "prox_reporter" reference software with the app_easy_timer feature in SDK5 ? Your described observation cannot conclude the issue is due to "app_easy_timer" function. More information is required such as how you run your test, on what software, ....
Regards,
Hi, Wl_Dialog,
I know that the app_easy_timer is the issue , because before I add the code of led blink part to the dsps-host project which I also have a process that use a app-easy-timer, it works fine.
what I want to know is that I just use a app-easy-timer to toggle the led pin, why I have block at the code
struct create_new_timer_struct *req = KE_MSG_ALLOC(APP_CREATE_NEW_TIMER, TASK_APP, TASK_APP,create_new_timer_struct);
Follow is the source code of the led.c
#include "led.h"
#include "app_easy_timer.h"
/* LED control structure */
typedef struct {
uint8_t todo; /* Blink cycles left */
uint8_t percent; /* On cycle percentage */
uint16_t period; /* On/off cycle time (msec) */
uint32_t next; /* Time for next change */
} LedControl_t;
/***************************************************************************************************
* GLOBAL VARIABLES
***************************************************************************************************/
static LedControl_t ledCtrl __attribute__((section("retention_mem_area0"),zero_init));
/***************************************************************************************************
* LOCAL FUNCTION
***************************************************************************************************/
static void LedUpdate (void);
/***************************************************************************************************
* FUNCTIONS - API
***************************************************************************************************/
/***************************************************************************************************
* @fn LedInit
*
* @brief初始化服务
*
* @param init - pointer to void that contains the initialized value
*
* @return None
***************************************************************************************************/
void LedInit (void)
{
LED_INIT();
}
/***************************************************************************************************
* @fn LedBlink
*
* @brief Blink the leds
*
* @param leds - bit mask value of leds to be blinked
* numBlinks - number of blinks
* percent - the percentage in each period where the led
* will be on
* period - length of each cycle in milliseconds
*
* @return None
***************************************************************************************************/
void LedBlink (uint8_t numBlinks, uint8_t percent, uint16_t period)
{
ledCtrl.todo = 2*numBlinks-1;
ledCtrl.percent = percent;
ledCtrl.period = period;
LED_OFF();
if( percent && period )
{
if( percent < 100 )
{
app_easy_timer(1,LedUpdate);
}
else
{
LED_ON ();
}
}
else
{
//turn off
LED_OFF();
}
}
/***************************************************************************************************
* @fn LedUpdate
*
* @brief Update leds to work with blink
*
* @param none
*
* @return none
***************************************************************************************************/
static void LedUpdate (void)
{
LED_TOGGLE();
ledCtrl.todo--;
if( ledCtrl.todo /*|| LED_STATE()*/)
{
if(LED_STATE())
{
ledCtrl.next = ledCtrl.period*(100-ledCtrl.percent);
}
else
{
ledCtrl.next = ledCtrl.period*ledCtrl.percent;
}
app_easy_timer(ledCtrl.next/10,LedUpdate);
}
}
Can you help me to check if there is some error of the code, I really can't find the reason.
other more, I just used LedInit to initi the LED port and LedBlink(20,35,1000) to do the test in System_Init() .
a little more, I found that is i invoke LedBlink() in the system_init, I will get continuous reboot after I flash the code to the flash. But if I invoke the LedBlink() in the main_func() after system_init(), this phenomenon will not happen, but I never can get the LedUpdate() invoked. also I have start a timer when a button is pressed, and I can get the callback of this timer invoked when the timer expired. This really confused me, any suggestion will be much appreciated!
Hi,
Your issue is properly related to where you put your "LedBlink(20,35,1000)" statement. It is because app_easy_timer and malloc() require the kernel timer and heap service. Your function can only be called after the kernel is initialized and activated. It is suggested to put your statement after system_init() and make your LedBlink function blink forever to ease your debugging.
int main_func(void)
{
sleep_mode_t sleep_mode;
//global initialise
system_init();
LedBlink(20,35,1000);
/*
************************************************************************************
* Platform initialization
************************************************************************************
*/
while(1)
{
.....
}
}
Regards,
I already done as you suggested, but I still can't get led blink. now I have invoke LedBlink on the device connection event, and led blinks right. So is it because the ble is sleep so that we can't start a timer?
Hi,
Before going into sleep mode, it is supposed no more activity is alive including LED blinking. No matter in extended or deep sleep mode, all I/O blocks will be turned off including the timer service. So, the LED blink timer service is disabled.
To ease the debugging of new driver or function, the simple way is to add one statement as follows to disable going into sleep mode but idle mode to give the minimal impact on software behaviour.
// get the allowed sleep mode
// time from rwip_power_down() to WFI() must be kept as short as possible!!
sleep_mode = rwip_power_down();
/* statement added */ sleep_mode = mode_idle;
Then you should see your LED blink continuously.
Regards,
Hi,
Fixed the mistake as follows:
// get the allowed sleep mode
// time from rwip_power_down() to WFI() must be kept as short as possible!!
sleep_mode = rwip_power_down();
/* statement added */
if ((sleep_mode == mode_ext_sleep) || (sleep_mode == mode_deep_sleep))
{
sleep_mode = mode_idle;
}
Regards,
What confused me is that:
I invoke the LedBlink() after system_init(),at when the timer kernal has going up,. and in the LedBlink(), I has setup a timer which will wakeup the BLE, so why my timer callback still can't get triggled? if the BLE is sleep when I first create the timer in LedBlink(), if this is true? I think I can force ble wakeup before I create the timer for the first time. I have tried the API arch_ble_force_wakeup() 、arch_ble_ext_wakeup_on() etc. but still cant blink.Does these api can really force the device wakeup?
Hi,
The technique to verify your LedBlink() function and its behavior can be done by simply forcing the sleep_mode not going into mode_ext_sleep or mode_deep_sleep. To integrate the LED blinking function and let it behaves in what you intended, you need to understand how the software is structured.
In real application, there is two (2) threads running independently, BLE stack and User application. Kernel provides only the services and user application requires to manages and supervise all resources usage and monitor all activities to determine the device can go into sleep mode or not.
int main_func(void)
{
sleep_mode_t sleep_mode;
//global initialise
system_init();
/*
************************************************************************************
* Platform initialization
************************************************************************************
*/
while(1)
{
do {
// schedule all pending events
schedule_while_ble_on();
}
while (app_asynch_proc() != GOTO_SLEEP); //grant control to the application, try to go to power down
//if the application returns GOTO_SLEEP
.....
}
}
app_asynch_proc()函数是一个检查的用户application whether any activity is on-going that prevents the device goes into sleep mode while BLE stack thread is ready to go into sleep.
typedef enum {
GOTO_SLEEP = 0,
KEEP_POWERED
} arch_main_loop_callback_ret_t;
In your case, this function can return "KEEP_POWERED" as long as LED is blinking not allowing the device into sleep.
static inline void schedule_while_ble_on(void)
{
// BLE clock is enabled
while (ble_is_powered())
{
// BLE event end is set. conditional RF calibration can run.
uint8_t ble_evt_end_set = ke_event_get(KE_EVENT_BLE_EVT_END);
//execute messages and events
rwip_schedule();
if (ble_evt_end_set)
{
uint32_t sleep_duration = 0;
rcx20_read_freq();
//if you have enough time run a temperature calibration of the radio
if (lld_sleep_check(&sleep_duration, 4)) //6 slots -> 3.750 ms
// check time and temperature to run radio calibrations.
conditionally_run_radio_cals();
}
//grant control to the application, try to go to sleep
//if the application returns GOTO_SLEEP
if (app_asynch_trm() != GOTO_SLEEP)
{
continue; // so that rwip_schedule() is called again
}
else
{
arch_printf_process();
break;
}
}
}
The app_asynch_trm() function handles user application while BLE stack is running. The rwip_schedule() will process all messages in the queue till completion and the control will pass to app_asynch_trm() function and based on the returned value "KEEP_POWERED" or "GOTO_SLEEP" to decide to keep alive or go to sleep accordingly.
Please notice that there is no function to keep track any software timer is running or not. It is the responsibility of the owner of the soft timer is to keep track its activity.
To develop your application in SDK5, it is recommended to study the following structure and understand how it works as it is the key of the SDK5 structure.
struct arch_main_loop_callbacks {
void (*app_on_init)(void);
arch_main_loop_callback_ret_t (*app_on_ble_powered)(void);
arch_main_loop_callback_ret_t (*app_on_system_powered)(void);
void (*app_before_sleep)(void);
sleep_mode_t (*app_validate_sleep)(sleep_mode_t sleep_mode);
void (*app_going_to_sleep)(sleep_mode_t sleep_mode);
void (*app_resume_from_sleep)(void);
};
static const struct arch_main_loop_callbacks user_app_main_loop_callbacks = {
.app_on_init = default_app_on_init,
/ /默认情况下看门狗定时器重载和resumed when the system wakes up.
// The user has to take into account the watchdog timer handling (keep it running,
// freeze it, reload it, resume it, etc), when the app_on_ble_powered() is being
// called and may potentially affect the main loop.
.app_on_ble_powered = NULL,
/ /默认情况下看门狗定时器重载和resumed when the system wakes up.
// The user has to take into account the watchdog timer handling (keep it running,
// freeze it, reload it, resume it, etc), when the app_on_system_powered() is being
// called and may potentially affect the main loop.
.app_on_system_powered = NULL,
.app_before_sleep = NULL,
.app_validate_sleep = NULL,
.app_going_to_sleep = NULL,
.app_resume_from_sleep = NULL,
};
Regards,
really thanks very much, useful suggestion