Skip to content
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

Enable low-power ticker and Sleep for FastModels #10124

Merged
merged 6 commits into from Apr 9, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
3 changes: 2 additions & 1 deletion TESTS/mbed_drivers/lp_timeout/main.cpp
Expand Up @@ -74,9 +74,10 @@ Case cases[] = {
Case("1 s delay during deepsleep (attach_us)", test_deepsleep<AttachUSTester<LowPowerTimeout>, 1000000, LONG_DELTA_US>,
greentea_failure_handler),
#endif

#if !defined(__ARM_FM) //FastModels not support time drifting test
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it OK to remove some tests because they are not passing....?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure how is it not supported?

@ARMmbed/mbed-os-hal to review

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is same story as #10030

For partner's targets/platforms, which will be used real life production. we are not allow them to skip tests, if they can't make them pass. The tests are mean to check that all platform comply with mbed HAL API.

FastModel it is a software simulator for Arm platform/cores. mean to be used as a tool for testing or early stage development. It is will never be used for any real IoT products.
They can simulator how ARM core works. One of issue for software simulator is they running on your host PC, they can't grantee the timing accuracy as microelectronics.

So the exception is just for the software models

Case("Timing drift (attach)", test_drift<AttachTester<LowPowerTimeout> >),
Case("Timing drift (attach_us)", test_drift<AttachUSTester<LowPowerTimeout> >),
#endif
};

utest::v1::status_t greentea_test_setup(const size_t number_of_cases)
Expand Down
121 changes: 121 additions & 0 deletions targets/TARGET_ARM_FM/TARGET_FVP_MPS2/lp_ticker.c
@@ -0,0 +1,121 @@
/* mbed Microcontroller Library
* Copyright (c) 2006-2019 ARM Limited
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <stddef.h>
#include "lp_ticker_api.h"
#include "PeripheralNames.h"

#define LP_TICKER_INTERRUPT CMSDK_TIMER0
#define LP_TICKER_COUNTER CMSDK_TIMER1
#define LP_TICKER_TIMER_IRQn TIMER0_IRQn


/* mbed OS HAL API defined lp_ticker as an increment ticker
* MPS2 platform provided in SSE-200 are decrement tickers
* with interrupt fired counter reaches 0.
*
* So 2 Timers are used to construct mbed OS HAL low power ticker.
*
* TIMER0 is for generating interrupts
* and TIMER0 will turned off when it is generating interrupts
*
* TIMER1 is for counting, and returns inverted binary when read from it
* Because TIMER1 is running at the speed of 25Mhz, it need to be shift by 10,
* in order to meet mbed HAL lp_ticker definitions
*
*/

static int lp_ticker_inited = 0;

void lp_ticker_internal_handler(void)
{
LP_TICKER_INTERRUPT->CTRL &= ~CMSDK_TIMER_CTRL_IRQEN_Msk;
LP_TICKER_INTERRUPT->CTRL &= ~CMSDK_TIMER_CTRL_EN_Msk;
lp_ticker_irq_handler();
}


void lp_ticker_init(void)
{
if (lp_ticker_inited) {
lp_ticker_disable_interrupt();
return;
}

LP_TICKER_COUNTER->CTRL = 0x0ul;
LP_TICKER_INTERRUPT->CTRL = 0x0ul;

LP_TICKER_COUNTER->RELOAD = 0xFFFFFFFFul;
LP_TICKER_INTERRUPT->RELOAD = 0xFFFFFFFFul;

LP_TICKER_COUNTER->CTRL |= CMSDK_TIMER_CTRL_EN_Msk;

NVIC_SetVector(LP_TICKER_TIMER_IRQn, (uint32_t)lp_ticker_internal_handler);
lp_ticker_inited = 1;
}

void lp_ticker_free(void)
{
LP_TICKER_COUNTER->CTRL &= ~CMSDK_TIMER_CTRL_EN_Msk;
lp_ticker_disable_interrupt();
lp_ticker_inited = 0;
}

uint32_t lp_ticker_read()
{
return (~LP_TICKER_COUNTER->VALUE) >> 10;
}

void lp_ticker_set_interrupt(timestamp_t timestamp)
{
uint32_t delta = (timestamp << 10) - (~LP_TICKER_COUNTER->VALUE);

LP_TICKER_INTERRUPT->CTRL &= ~CMSDK_TIMER_CTRL_EN_Msk;
LP_TICKER_INTERRUPT->RELOAD = delta;
LP_TICKER_INTERRUPT->CTRL |= CMSDK_TIMER_CTRL_IRQEN_Msk;
LP_TICKER_INTERRUPT->CTRL |= CMSDK_TIMER_CTRL_EN_Msk;

NVIC_EnableIRQ(LP_TICKER_TIMER_IRQn);
}

void lp_ticker_fire_interrupt(void)
{
NVIC_EnableIRQ(LP_TICKER_TIMER_IRQn);
NVIC_SetPendingIRQ(LP_TICKER_TIMER_IRQn);
}

void lp_ticker_disable_interrupt(void)
{
LP_TICKER_INTERRUPT->CTRL &= ~CMSDK_TIMER_CTRL_IRQEN_Msk;
LP_TICKER_INTERRUPT->CTRL &= ~CMSDK_TIMER_CTRL_EN_Msk;
NVIC_DisableIRQ(LP_TICKER_TIMER_IRQn);
}

void lp_ticker_clear_interrupt(void)
{
LP_TICKER_INTERRUPT->INTCLEAR = CMSDK_TIMER_INTCLEAR_Msk;
}

const ticker_info_t *lp_ticker_get_info(void)
{
static const ticker_info_t info = {
24414, // 10 stages scaled from 25MHz (dived by 1024)
22 // 22 bit counter
};
return &info;
}


65 changes: 65 additions & 0 deletions targets/TARGET_ARM_FM/TARGET_FVP_MPS2/sleep_api.c
@@ -0,0 +1,65 @@

/** \addtogroup hal */
/** @{*/
/* mbed Microcontroller Library
* Copyright (c) 2018-2019 Arm Limited
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/


#include "sleep_api.h"
#include "us_ticker_api.h"

#include "PeripheralNames.h"
#define US_TICKER_COUNTER CMSDK_DUALTIMER1
#define US_TICKER_INTERRUPT CMSDK_DUALTIMER2
#define US_TICKER_TIMER_IRQn DUALTIMER_IRQn


#if DEVICE_SLEEP

void hal_sleep(void)
{
__WFI();
}

/* Since there is no power management function implemented in MPS2,
* Also Deep Sleep mode mean to save power which is not practical on a simulator.
* So mbed HAL Deep sleep is mocked by Sleep,
* representing a "Waiting For Interrupt" state,
* but disabling the Microsec ticker in addition */

void hal_deepsleep(void)
{
#if DEVICE_USTICKER
uint32_t val = US_TICKER_COUNTER->TimerValue;
US_TICKER_COUNTER->TimerControl &= ~CMSDK_DUALTIMER1_CTRL_EN_Msk;
US_TICKER_INTERRUPT->TimerControl &= ~CMSDK_DUALTIMER2_CTRL_EN_Msk;
US_TICKER_INTERRUPT->TimerControl &= ~CMSDK_DUALTIMER2_CTRL_INTEN_Msk;
#endif

__WFI();

#if DEVICE_USTICKER
US_TICKER_COUNTER->TimerLoad = val;
US_TICKER_COUNTER->TimerControl |= CMSDK_DUALTIMER1_CTRL_EN_Msk;
US_TICKER_INTERRUPT->TimerControl |= CMSDK_DUALTIMER1_CTRL_INTEN_Msk;
US_TICKER_INTERRUPT->TimerControl |= CMSDK_DUALTIMER2_CTRL_EN_Msk;
#endif
}

#endif

/**@}*/
57 changes: 29 additions & 28 deletions targets/TARGET_ARM_FM/TARGET_FVP_MPS2/us_ticker.c
@@ -1,5 +1,6 @@
/* mbed Microcontroller Library
* Copyright (c) 2006-2018 ARM Limited
* Copyright (c) 2006-2019 ARM Limited
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -16,24 +17,24 @@
#include <stddef.h>
#include "us_ticker_api.h"
#include "PeripheralNames.h"
#define US_TICKER_TIMER1 CMSDK_DUALTIMER1
#define US_TICKER_TIMER2 CMSDK_DUALTIMER2
#define US_TICKER_COUNTER CMSDK_DUALTIMER1
#define US_TICKER_INTERRUPT CMSDK_DUALTIMER2
#define US_TICKER_TIMER_IRQn DUALTIMER_IRQn

/** mbed OS HAL API defined us_ticker as an increment ticker
* MPS2 platform provided in SSE-200 are decrement tickers
* with interrupt fired counter reaches 0.
*
* So 2 Timers are used to construct mbed OS HAL ticker.
*
*
* TIMER1 is for counting, and returns inverted binary when read from it
* TIMER1 will be kept in free-running mode (default, and not generate interrupts)
*
*
* TIMER2 is for generating interrupts
* So TIMER2 is set to periodic mode, which start decrement counting form LOADVALUE generates interrupts at 0
* and TIMER2 also set into one-shot mode, which counter halts when is reaches 0
* and TIMER2 also set into one-shot mode, which counter halts when is reaches 0
*/

static int us_ticker_inited = 0;

void us_ticker_init(void)
Expand All @@ -43,47 +44,47 @@ void us_ticker_init(void)
return;
}

US_TICKER_TIMER1->TimerControl = 0x0ul; // disable TIMER1 and reset all control
US_TICKER_TIMER2->TimerControl = 0x0ul; // disable TIMER2 and reset all control
US_TICKER_COUNTER->TimerControl = 0x0ul; // disable TIMER1 and reset all control
US_TICKER_INTERRUPT->TimerControl = 0x0ul; // disable TIMER2 and reset all control

US_TICKER_TIMER1->TimerLoad = 0xFFFFFFFFul;
US_TICKER_TIMER2->TimerLoad = 0xFFFFFFFFul;
US_TICKER_COUNTER->TimerLoad = 0xFFFFFFFFul;
US_TICKER_INTERRUPT->TimerLoad = 0xFFFFFFFFul;

US_TICKER_TIMER1->TimerControl |= CMSDK_DUALTIMER1_CTRL_SIZE_Msk; // set TIMER1 to 32 bit counter
US_TICKER_TIMER2->TimerControl |= CMSDK_DUALTIMER2_CTRL_SIZE_Msk; // set TIMER2 to 32 bit counter
US_TICKER_COUNTER->TimerControl |= CMSDK_DUALTIMER1_CTRL_SIZE_Msk; // set TIMER1 to 32 bit counter
US_TICKER_INTERRUPT->TimerControl |= CMSDK_DUALTIMER2_CTRL_SIZE_Msk; // set TIMER2 to 32 bit counter

US_TICKER_TIMER1->TimerControl |= 0x1 << CMSDK_DUALTIMER1_CTRL_PRESCALE_Pos; // set TIMER1 with 4 stages prescale
US_TICKER_TIMER2->TimerControl |= 0x1 << CMSDK_DUALTIMER2_CTRL_PRESCALE_Pos; // set TIMER2 with 4 stages prescale
US_TICKER_COUNTER->TimerControl |= 0x1 << CMSDK_DUALTIMER1_CTRL_PRESCALE_Pos; // set TIMER1 with 4 stages prescale
US_TICKER_INTERRUPT->TimerControl |= 0x1 << CMSDK_DUALTIMER2_CTRL_PRESCALE_Pos; // set TIMER2 with 4 stages prescale

US_TICKER_TIMER2->TimerControl |= CMSDK_DUALTIMER2_CTRL_MODE_Msk; // set TIMER2 periodic mode
US_TICKER_TIMER2->TimerControl |= CMSDK_DUALTIMER2_CTRL_ONESHOOT_Msk; // set TIMER2 one-shot mode
US_TICKER_INTERRUPT->TimerControl |= CMSDK_DUALTIMER2_CTRL_MODE_Msk; // set TIMER2 periodic mode
US_TICKER_INTERRUPT->TimerControl |= CMSDK_DUALTIMER2_CTRL_ONESHOOT_Msk; // set TIMER2 one-shot mode

US_TICKER_TIMER1->TimerControl |= CMSDK_DUALTIMER1_CTRL_EN_Msk; // enable TIMER1 counter
US_TICKER_COUNTER->TimerControl |= CMSDK_DUALTIMER1_CTRL_EN_Msk; // enable TIMER1 counter

NVIC_SetVector(US_TICKER_TIMER_IRQn, (uint32_t)us_ticker_irq_handler);
us_ticker_inited = 1;
}

void us_ticker_free(void)
{
US_TICKER_TIMER1->TimerControl &= ~CMSDK_DUALTIMER1_CTRL_EN_Msk; // disable TIMER1
US_TICKER_TIMER2->TimerControl &= ~CMSDK_DUALTIMER2_CTRL_EN_Msk; // disable TIMER2
US_TICKER_COUNTER->TimerControl &= ~CMSDK_DUALTIMER1_CTRL_EN_Msk; // disable TIMER1
US_TICKER_INTERRUPT->TimerControl &= ~CMSDK_DUALTIMER2_CTRL_EN_Msk; // disable TIMER2
us_ticker_disable_interrupt();
us_ticker_inited = 0;
}

uint32_t us_ticker_read()
{
return ~US_TICKER_TIMER1->TimerValue;
return ~US_TICKER_COUNTER->TimerValue;
}

void us_ticker_set_interrupt(timestamp_t timestamp)
{
uint32_t delta = timestamp - us_ticker_read();
US_TICKER_TIMER2->TimerControl &= ~CMSDK_DUALTIMER2_CTRL_EN_Msk; // disable TIMER2
US_TICKER_TIMER2->TimerLoad = delta; // Set TIMER2 load value
US_TICKER_TIMER2->TimerControl |= CMSDK_DUALTIMER2_CTRL_INTEN_Msk; // enable TIMER2 interrupt
US_TICKER_TIMER2->TimerControl |= CMSDK_DUALTIMER2_CTRL_EN_Msk; // enable TIMER2 counter
US_TICKER_INTERRUPT->TimerControl &= ~CMSDK_DUALTIMER2_CTRL_EN_Msk; // disable TIMER2
US_TICKER_INTERRUPT->TimerLoad = delta; // Set TIMER2 load value
US_TICKER_INTERRUPT->TimerControl |= CMSDK_DUALTIMER2_CTRL_INTEN_Msk; // enable TIMER2 interrupt
US_TICKER_INTERRUPT->TimerControl |= CMSDK_DUALTIMER2_CTRL_EN_Msk; // enable TIMER2 counter
NVIC_EnableIRQ(US_TICKER_TIMER_IRQn);
}

Expand All @@ -96,14 +97,14 @@ void us_ticker_fire_interrupt(void)

void us_ticker_disable_interrupt(void)
{
US_TICKER_TIMER2->TimerControl &= ~CMSDK_DUALTIMER2_CTRL_INTEN_Msk;
US_TICKER_TIMER2->TimerControl &= ~CMSDK_DUALTIMER2_CTRL_EN_Msk; // disable TIMER2
US_TICKER_INTERRUPT->TimerControl &= ~CMSDK_DUALTIMER2_CTRL_INTEN_Msk;
US_TICKER_INTERRUPT->TimerControl &= ~CMSDK_DUALTIMER2_CTRL_EN_Msk; // disable TIMER2
NVIC_DisableIRQ(US_TICKER_TIMER_IRQn);
}

void us_ticker_clear_interrupt(void)
{
US_TICKER_TIMER2->TimerIntClr = CMSDK_DUALTIMER2_INTCLR_Msk;
US_TICKER_INTERRUPT->TimerIntClr = CMSDK_DUALTIMER2_INTCLR_Msk;
}

const ticker_info_t *us_ticker_get_info(void)
Expand Down
2 changes: 2 additions & 0 deletions targets/targets.json
Expand Up @@ -7897,10 +7897,12 @@
"FLASH",
"I2C",
"INTERRUPTIN",
"LPTICKER",
"PORTIN",
"PORTINOUT",
"PORTOUT",
"SERIAL",
"SLEEP",
"SPI",
"SPISLAVE",
"TSC",
Expand Down