-
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
Conversation
/morph test |
This is roughly based on #4956 but with SysTick replaced entirely. |
Result: FAILUREYour command has finished executing! Here's what you wrote!
OutputBuild failed! |
6286c12
to
c6428a6
Compare
/morph test |
Result: FAILUREYour command has finished executing! Here's what you wrote!
OutputBuild failed! |
CC: @pan- |
Result: FAILUREYour command has finished executing! Here's what you wrote!
OutputBuild failed! |
/morph test |
Result: FAILUREYour command has finished executing! Here's what you wrote!
OutputTest failed! |
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.
Looks fine in general.
rtos/rtx5/mbed_rtx_idle.cpp
Outdated
using namespace mbed; | ||
|
||
#if (defined(NO_SYSTICK)) | ||
extern "C" IRQn_Type mbed_get_m0_tick_irqn(void); |
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.
Is this public API? targets that do not have systick (very few) should port this, should it be included in ticker api (is it related to tickers or own API just for nosystick rtos?)
missing the documentation what it should return
rtos/rtx5/mbed_rtx_idle.cpp
Outdated
/** | ||
* Get the time | ||
* | ||
* @return Current tmie in microseconds |
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.
typo time
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.
done
rtos/rtx5/mbed_rtx_idle.cpp
Outdated
schedule_tick(); | ||
} | ||
|
||
us_timestamp_t start_time; |
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.
private members should be prefixed _start_time
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.
done
rtos/rtx5/mbed_rtx_idle.cpp
Outdated
// 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); |
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.
What does this do? I would expect to only set a new ticker vector for systick handler, nothing else, so why do we need this systick setup?
Looking at the weak function provided by RTX, its only used in osRtxSysTimerSetup.
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.
This is only used to set the SysTick priority to the low value RTX expects (0xFF). I could put the code which sets the priority here, but to help with readability I called SysTick_Setup instead. Setting the priority is slightly different for each cortex variation and would look something like this:
#if ((__ARM_ARCH_8M_MAIN__ == 1U) || (defined(__CORTEX_M) && (__CORTEX_M == 7U)))
SCB->SHPR[11] = 0xFFU;
#elif (__ARM_ARCH_8M_BASE__ == 1U)
SCB->SHPR[1] |= 0xFF000000U;
#elif ((__ARM_ARCH_7M__ == 1U) || \
(__ARM_ARCH_7EM__ == 1U))
SCB->SHP[11] = 0xFFU;
#elif (__ARM_ARCH_6M__ == 1U)
SCB->SHP[1] |= 0xFF000000U;
#endif
rtos/rtx5/mbed_rtx_idle.cpp
Outdated
// Don't update to the current tick. | ||
// The RTOS must do this to properly | ||
// schedule tasks again. | ||
new_tick--; |
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.
It's not clear to me why we do -1
in case newtick > tick
? If ticks have increased since the last update tick, we substract one from the tick count?
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.
The function svcRtxKernelResume doesn't trigger a task switch if a thread is ready to run. To work around this and jump start scheduling after a tick has passed, one less than the number of ticks that have occurred are passed to svcRtxKernelResume and SysTick is set to pending. The SysTick interrupt then increments the os's tick count to the right value and performs task switching as normal.
After further analysis, it appears that PendSV may be more appropriate in this situation. It will trigger a thread switch without recomputing the tick count. I'll update the PR to use this instead.
rtos/rtx5/mbed_rtx_idle.cpp
Outdated
static uint64_t os_timer_data[sizeof(RtosTimer) / 8]; | ||
|
||
/// Setup System Timer. | ||
int32_t osRtxSysTimerSetup (void) |
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.
Isn't there CMSIS-RTOS for tick API? What I found is https://github.com/ARM-software/CMSIS_5/blob/6e5621b3bc4becf50ac5f29a07f30ff2081a5e70/CMSIS/RTOS2/Include/os_tick.h , but that seems to be not in our codebase - https://www.keil.com/pack/doc/CMSIS/RTOS2/html/group__CMSIS__RTOS__TickAPI.html. I guess we get this once we update RTOS
Just to be aware
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.
They've changed the names again, the API was there and is used by nrf51_dk
// ==== Public API ==== |
Fails for Ameba:
https://github.com/ARMmbed/mbed-os/pull/4991/files#diff-d9706ce53abe36e6bcaf49d927f4df58R169 |
@Archcady this PR fails for Ameba board, I've tried to see what the platform does around the SysTick, but I don't think it's int the sources (unless i've missed it). Can you have a look and see why would it fail? |
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.
Few observations:
- If the SysTick is tied to the us_ticker then an additional latency might be present. Is it a good thing ?
- RtosTimer shall take into account
OS_TICK_FREQ
. - It would be good to have a way to override the behavior in targets, the implementation exposed, on NRF51, is I believe significantly less precise than the old one (it would be good to benchmark it to verify that assertion).
This will cause the additional latency of a second interrupt call, but this should be fairly small when compared to a 1ms tick. The reason this is done is that the interrupt that runs SysTick must be run at a low priority. On most if not all platforms, the lp/us ticker interrupt is set to a higher priority than this.
Done
I'll compare this to the time reported by the us ticker as we discussed. Unfortunately I don't have a board with me so this might have to wait until another day. |
/morph test |
Summary of updates:
|
Result: FAILUREYour command has finished executing! Here's what you wrote!
OutputBuild failed! |
Both Ameba and GG boards are fixed. Great job @c1728p9 :) |
Ah that's because it's now disabled by default :) |
@pan- Can you review again please? |
Result: SUCCESSYour command has finished executing! Here's what you wrote!
OutputAll builds and test passed! |
@pan- are you ok with the state of things? |
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.
The idea looks good, will need some refinement in the future, but good enough for now. Ready for merge?
Closed and re-opened to kick off travis again |
|
||
core_util_critical_section_enter(); | ||
uint32_t ticks_to_sleep = svcRtxKernelSuspend(); | ||
MBED_ASSERT(os_timer->get_tick() == svcRtxKernelGetTickCount()); |
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."
RtosTimer class introduced with tickless support in ARMmbed#4991 had to be renamed because that name was already present in rtos namespace.
Add support for tickless by replacing RTX's SysTick timer code with with code which uses an mbed timer along with suspending and resuming the kernel in the idle loop.