-
Notifications
You must be signed in to change notification settings - Fork 3k
Add tickless to some mbed-os devices #4991
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
4 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,230 @@ | ||
/* mbed Microcontroller Library | ||
* Copyright (c) 2006-2012 ARM Limited | ||
* | ||
* Permission is hereby granted, free of charge, to any person obtaining a copy | ||
* of this software and associated documentation files (the "Software"), to deal | ||
* in the Software without restriction, including without limitation the rights | ||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
* copies of the Software, and to permit persons to whom the Software is | ||
* furnished to do so, subject to the following conditions: | ||
* | ||
* The above copyright notice and this permission notice shall be included in | ||
* all copies or substantial portions of the Software. | ||
* | ||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
* SOFTWARE. | ||
*/ | ||
|
||
#include "rtos/rtos_idle.h" | ||
#include "platform/mbed_sleep.h" | ||
#include "TimerEvent.h" | ||
#include "lp_ticker_api.h" | ||
#include "core_cm.h" | ||
#include "mbed_critical.h" | ||
#include "mbed_assert.h" | ||
#include <new> | ||
#include "rtx_os.h" | ||
extern "C" { | ||
#include "rtx_lib.h" | ||
} | ||
|
||
using namespace mbed; | ||
|
||
#ifdef MBED_TICKLESS | ||
|
||
#if (defined(NO_SYSTICK)) | ||
/** | ||
* Return an IRQ number that can be used in the absence of SysTick | ||
* | ||
* @return Free IRQ number that can be used | ||
*/ | ||
extern "C" IRQn_Type mbed_get_m0_tick_irqn(void); | ||
#endif | ||
|
||
class RtosTimer : private TimerEvent { | ||
public: | ||
RtosTimer(): TimerEvent(get_lp_ticker_data()), _start_time(0), _tick(0) { | ||
_start_time = ticker_read_us(_ticker_data); | ||
#if (defined(NO_SYSTICK)) | ||
NVIC_SetVector(mbed_get_m0_tick_irqn(), (uint32_t)SysTick_Handler); | ||
NVIC_SetPriority(mbed_get_m0_tick_irqn(), 0xFF); /* RTOS requires lowest priority */ | ||
NVIC_EnableIRQ(mbed_get_m0_tick_irqn()); | ||
#else | ||
// Ensure SysTick has the correct priority as it is still used | ||
// to trigger software interrupts on each tick. The period does | ||
// not matter since it will never start counting. | ||
SysTick_Setup(16); | ||
#endif | ||
}; | ||
|
||
/** | ||
* Schedule an os tick to fire | ||
* | ||
* @param delta Tick to fire at relative to current tick | ||
*/ | ||
void schedule_tick(uint32_t delta=1) { | ||
insert_absolute(_start_time + (_tick + delta) * 1000000 / OS_TICK_FREQ); | ||
} | ||
|
||
|
||
/** | ||
* Prevent any scheduled ticks from triggering | ||
*/ | ||
void cancel_tick() { | ||
remove(); | ||
} | ||
|
||
/** | ||
* Get the current tick count | ||
* | ||
* @return The number of ticks since boot. This should match RTX's tick count | ||
*/ | ||
uint32_t get_tick() { | ||
return _tick & 0xFFFFFFFF; | ||
} | ||
|
||
/** | ||
* Update the internal tick count | ||
* | ||
* @return The number of ticks incremented | ||
*/ | ||
uint32_t update_tick() { | ||
uint64_t new_tick = ticker_read_us(_ticker_data) * OS_TICK_FREQ / 1000000; | ||
if (new_tick > _tick) { | ||
// Don't update to the current tick. Instead, update to the | ||
// previous tick and let the SysTick handler increment it | ||
// to the current value. This allows scheduling restart | ||
// successfully after the OS is resumed. | ||
new_tick--; | ||
} | ||
uint32_t elapsed_ticks = new_tick - _tick; | ||
_tick = new_tick; | ||
return elapsed_ticks; | ||
} | ||
|
||
/** | ||
* Get the time | ||
* | ||
* @return Current time in microseconds | ||
*/ | ||
us_timestamp_t get_time() { | ||
return ticker_read_us(_ticker_data); | ||
} | ||
|
||
~RtosTimer() { | ||
|
||
}; | ||
|
||
protected: | ||
|
||
void handler() { | ||
#if (defined(NO_SYSTICK)) | ||
NVIC_SetPendingIRQ(mbed_get_m0_tick_irqn()); | ||
#else | ||
SCB->ICSR = SCB_ICSR_PENDSTSET_Msk; | ||
#endif | ||
_tick++; | ||
} | ||
|
||
us_timestamp_t _start_time; | ||
uint64_t _tick; | ||
}; | ||
|
||
static RtosTimer *os_timer; | ||
static uint64_t os_timer_data[sizeof(RtosTimer) / 8]; | ||
|
||
/// Setup System Timer. | ||
int32_t osRtxSysTimerSetup (void) | ||
{ | ||
// Do not use SingletonPtr since this relies on the RTOS | ||
if (NULL == os_timer) { | ||
os_timer = new (os_timer_data) RtosTimer(); | ||
} | ||
return -1; | ||
} | ||
|
||
/// Enable System Timer. | ||
void osRtxSysTimerEnable (void) | ||
{ | ||
// set to fire interrupt on next tick | ||
os_timer->schedule_tick(); | ||
} | ||
|
||
/// Disable System Timer. | ||
void osRtxSysTimerDisable (void) | ||
{ | ||
os_timer->cancel_tick(); | ||
} | ||
|
||
/// Acknowledge System Timer IRQ. | ||
void osRtxSysTimerAckIRQ (void) | ||
{ | ||
os_timer->schedule_tick(); | ||
} | ||
|
||
/// Get System Timer count. | ||
uint32_t osRtxSysTimerGetCount (void) | ||
{ | ||
return os_timer->get_time() & 0xFFFFFFFF; | ||
} | ||
|
||
static void default_idle_hook(void) | ||
{ | ||
uint32_t elapsed_ticks = 0; | ||
|
||
core_util_critical_section_enter(); | ||
uint32_t ticks_to_sleep = svcRtxKernelSuspend(); | ||
MBED_ASSERT(os_timer->get_tick() == svcRtxKernelGetTickCount()); | ||
if (ticks_to_sleep) { | ||
os_timer->schedule_tick(ticks_to_sleep); | ||
|
||
sleep_manager_lock_deep_sleep(); | ||
sleep(); | ||
sleep_manager_unlock_deep_sleep(); | ||
|
||
os_timer->cancel_tick(); | ||
// calculate how long we slept | ||
elapsed_ticks = os_timer->update_tick(); | ||
} | ||
svcRtxKernelResume(elapsed_ticks); | ||
core_util_critical_section_exit(); | ||
} | ||
|
||
#else | ||
|
||
static void default_idle_hook(void) | ||
{ | ||
// critical section to complete sleep with locked deepsleep | ||
core_util_critical_section_enter(); | ||
sleep_manager_lock_deep_sleep(); | ||
sleep(); | ||
sleep_manager_unlock_deep_sleep(); | ||
core_util_critical_section_exit(); | ||
} | ||
|
||
#endif // MBED_TICKLESS | ||
|
||
static void (*idle_hook_fptr)(void) = &default_idle_hook; | ||
|
||
void rtos_attach_idle_hook(void (*fptr)(void)) | ||
{ | ||
//Attach the specified idle hook, or the default idle hook in case of a NULL pointer | ||
if (fptr != NULL) { | ||
idle_hook_fptr = fptr; | ||
} else { | ||
idle_hook_fptr = default_idle_hook; | ||
} | ||
} | ||
|
||
extern "C" void rtos_idle_loop(void) | ||
{ | ||
//Continuously call the idle hook function pointer | ||
while (1) { | ||
idle_hook_fptr(); | ||
} | ||
} |
This file was deleted.
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
breaks debugger
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@saedelman Can you provide more details, or create an issue to reference this line there so we can review?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Using gdb and single stepping through the RTX code causes the assert to be triggered. This may be related to the "Gotcha" related to in https://github.com/nuket/mbed-memory-status although I am using SEGGER RTT debug output not serial output:
"On mbed 5.5 and up, there may be a Heisenbug when calling print_thread_info() inside of osKernelLock()!
This error sometimes appears on the serial console shortly after chip startup, but not always: mbed assertation failed: os_timer->get_tick() == svcRtxKernelGetTickCount(), file: .\mbed-os\rtos\TARGET_CORTEX\mbed_rtx_idle.c
The RTOS seems to be asserting an idle constraint violation due to the slowness of sending data through the serial port, but it does not happen consistently."