Merge pull request #3837 from ARMmbed/release-candidate

Release candidate for mbed-os-5.3.6
mbed-os-5.3 mbed_lib_rev137
Martin Kojtal 2017-02-27 14:51:58 +01:00 committed by GitHub
commit 5faf4b26c5
30 changed files with 292 additions and 295 deletions

View File

@ -70,7 +70,7 @@ SIMPLE_POSTS_TEST(0)
void time_func(Timer *t, int ms) {
TEST_ASSERT_INT_WITHIN(2, ms, t->read_ms());
TEST_ASSERT_INT_WITHIN(5, ms, t->read_ms());
t->reset();
}

View File

@ -0,0 +1,122 @@
#include "mbed_events.h"
#include "mbed.h"
#include "rtos.h"
#include "greentea-client/test_env.h"
#include "unity.h"
#include "utest.h"
#include <cstdlib>
#include <cmath>
using namespace utest::v1;
// Test delay
#ifndef TEST_EVENTS_TIMING_TIME
#define TEST_EVENTS_TIMING_TIME 20000
#endif
#ifndef TEST_EVENTS_TIMING_MEAN
#define TEST_EVENTS_TIMING_MEAN 25
#endif
#ifndef M_PI
#define M_PI 3.14159265358979323846264338327950288
#endif
// Random number generation to skew timing values
float gauss(float mu, float sigma) {
float x = (float)rand() / ((float)RAND_MAX+1);
float y = (float)rand() / ((float)RAND_MAX+1);
float x2pi = x*2.0*M_PI;
float g2rad = sqrt(-2.0 * log(1.0-y));
float z = cos(x2pi) * g2rad;
return mu + z*sigma;
}
float chisq(float sigma) {
return pow(gauss(0, sqrt(sigma)), 2);
}
Timer timer;
DigitalOut led(LED1);
equeue_sema_t sema;
// Timer timing test
void timer_timing_test() {
timer.reset();
timer.start();
int prev = timer.read_us();
while (prev < TEST_EVENTS_TIMING_TIME*1000) {
int next = timer.read_us();
if (next < prev) {
printf("backwards drift %d -> %d (%08x -> %08x)\r\n",
prev, next, prev, next);
}
TEST_ASSERT(next >= prev);
prev = next;
}
}
// equeue tick timing test
void tick_timing_test() {
unsigned start = equeue_tick();
int prev = 0;
while (prev < TEST_EVENTS_TIMING_TIME) {
int next = equeue_tick() - start;
if (next < prev) {
printf("backwards drift %d -> %d (%08x -> %08x)\r\n",
prev, next, prev, next);
}
TEST_ASSERT(next >= prev);
prev = next;
}
}
// equeue semaphore timing test
void semaphore_timing_test() {
srand(0);
timer.reset();
timer.start();
int err = equeue_sema_create(&sema);
TEST_ASSERT_EQUAL(0, err);
while (timer.read_ms() < TEST_EVENTS_TIMING_TIME) {
int delay = chisq(TEST_EVENTS_TIMING_MEAN);
int start = timer.read_us();
equeue_sema_wait(&sema, delay);
int taken = timer.read_us() - start;
printf("delay %dms => error %dus\r\n", delay, abs(1000*delay - taken));
TEST_ASSERT_INT_WITHIN(5000, taken, delay * 1000);
led = !led;
}
equeue_sema_destroy(&sema);
}
// Test setup
utest::v1::status_t test_setup(const size_t number_of_cases) {
GREENTEA_SETUP((number_of_cases+1)*TEST_EVENTS_TIMING_TIME, "default_auto");
return verbose_test_setup_handler(number_of_cases);
}
const Case cases[] = {
Case("Testing accuracy of timer", timer_timing_test),
Case("Testing accuracy of equeue tick", tick_timing_test),
Case("Testing accuracy of equeue semaphore", semaphore_timing_test),
};
Specification specification(test_setup, cases);
int main() {
return !Harness::run(specification);
}

View File

@ -26,15 +26,15 @@
// Ticker operations
static bool equeue_tick_inited = false;
static unsigned equeue_minutes = 0;
static volatile unsigned equeue_minutes = 0;
static unsigned equeue_timer[
(sizeof(Timer)+sizeof(unsigned)-1)/sizeof(unsigned)];
static unsigned equeue_ticker[
(sizeof(Ticker)+sizeof(unsigned)-1)/sizeof(unsigned)];
static void equeue_tick_update() {
equeue_minutes += reinterpret_cast<Timer*>(equeue_timer)->read_ms();
reinterpret_cast<Timer*>(equeue_timer)->reset();
equeue_minutes += 1;
}
static void equeue_tick_init() {
@ -48,7 +48,7 @@ static void equeue_tick_init() {
equeue_minutes = 0;
reinterpret_cast<Timer*>(equeue_timer)->start();
reinterpret_cast<Ticker*>(equeue_ticker)
->attach_us(equeue_tick_update, (1 << 16)*1000);
->attach_us(equeue_tick_update, 1000 << 16);
equeue_tick_inited = true;
}
@ -58,8 +58,15 @@ unsigned equeue_tick() {
equeue_tick_init();
}
unsigned equeue_ms = reinterpret_cast<Timer*>(equeue_timer)->read_ms();
return (equeue_minutes << 16) + equeue_ms;
unsigned minutes;
unsigned ms;
do {
minutes = equeue_minutes;
ms = reinterpret_cast<Timer*>(equeue_timer)->read_ms();
} while (minutes != equeue_minutes);
return minutes + ms;
}

View File

@ -135,7 +135,7 @@ USBHAL::USBHAL(void) {
/* bulk/int 64 bytes in FS */
HAL_PCDEx_SetTxFiFo(&hpcd, 0, (MAX_PACKET_SIZE_EP0/4)+1);
/* bulk/int bytes in FS */
HAL_PCDEx_SetTxFiFo(&hpcd, 1, (MAX_PACKET_SIZE_EP1/4));
HAL_PCDEx_SetTxFiFo(&hpcd, 1, (MAX_PACKET_SIZE_EP1/4)+1);
HAL_PCDEx_SetTxFiFo(&hpcd, 2, (MAX_PACKET_SIZE_EP2/4));
/* ISOchronous */
HAL_PCDEx_SetTxFiFo(&hpcd, 3, (MAX_PACKET_SIZE_EP3/4));

View File

@ -131,7 +131,7 @@ USBHAL::USBHAL(void) {
/* bulk/int 64 bytes in FS */
HAL_PCDEx_SetTxFiFo(&hpcd, 0, (MAX_PACKET_SIZE_EP0/4)+1);
/* bulk/int bytes in FS */
HAL_PCDEx_SetTxFiFo(&hpcd, 1, (MAX_PACKET_SIZE_EP1/4));
HAL_PCDEx_SetTxFiFo(&hpcd, 1, (MAX_PACKET_SIZE_EP1/4)+1);
HAL_PCDEx_SetTxFiFo(&hpcd, 2, (MAX_PACKET_SIZE_EP2/4));
/* ISOchronous */
HAL_PCDEx_SetTxFiFo(&hpcd, 3, (MAX_PACKET_SIZE_EP3/4));

View File

@ -121,7 +121,7 @@ USBHAL::USBHAL(void) {
/* bulk/int 64 bytes in FS */
HAL_PCDEx_SetTxFiFo(&hpcd, 0, (MAX_PACKET_SIZE_EP0/4)+1);
/* bulk/int bytes in FS */
HAL_PCDEx_SetTxFiFo(&hpcd, 1, (MAX_PACKET_SIZE_EP1/4));
HAL_PCDEx_SetTxFiFo(&hpcd, 1, (MAX_PACKET_SIZE_EP1/4)+1);
HAL_PCDEx_SetTxFiFo(&hpcd, 2, (MAX_PACKET_SIZE_EP2/4));
/* ISOchronous */
HAL_PCDEx_SetTxFiFo(&hpcd, 3, (MAX_PACKET_SIZE_EP3/4));

View File

@ -27,6 +27,10 @@
//#define __packed __attribute__ ((__packed__))
//#endif
#ifdef __GNUC__
#define __packed __attribute__ ((__packed__))
#endif
class USBHAL {
public:
/* Configuration */

4
mbed.h
View File

@ -16,13 +16,13 @@
#ifndef MBED_H
#define MBED_H
#define MBED_LIBRARY_VERSION 136
#define MBED_LIBRARY_VERSION 137
#if MBED_CONF_RTOS_PRESENT
// RTOS present, this is valid only for mbed OS 5
#define MBED_MAJOR_VERSION 5
#define MBED_MINOR_VERSION 3
#define MBED_PATCH_VERSION 5
#define MBED_PATCH_VERSION 6
#else
// mbed 2

View File

@ -65,7 +65,7 @@ void spi_format(spi_t *obj, int bits, int mode, int slave)
spi_master_config_t master_config;
spi_slave_config_t slave_config;
if ((bits != 8) || (bits != 16)) {
if ((bits != 8) && (bits != 16)) {
error("Only 8bits and 16bits SPI supported");
return;
}

View File

@ -65,7 +65,7 @@ void spi_format(spi_t *obj, int bits, int mode, int slave)
spi_master_config_t master_config;
spi_slave_config_t slave_config;
if ((bits != 8) || (bits != 16)) {
if ((bits != 8) && (bits != 16)) {
error("Only 8bits and 16bits SPI supported");
return;
}

View File

@ -117,9 +117,6 @@ struct pwmout_s {
};
struct sleep_s {
uint32_t start_us;
uint32_t end_us;
uint32_t period_us;
int powerdown;
};

View File

@ -11,10 +11,13 @@
#include "M451Series.h"
#include <errno.h>
#include "nu_miscutil.h"
extern uint32_t __mbed_sbrk_start;
extern uint32_t __mbed_krbs_start;
#define NU_HEAP_ALIGN 32
/**
* The default implementation of _sbrk() (in common/retarget.cpp) for GCC_ARM requires one-region model (heap and stack share one region), which doesn't
* fit two-region model (heap and stack are two distinct regions), for example, NUMAKER-PFM-NUC472 locates heap on external SRAM. Define __wrap__sbrk() to
@ -23,8 +26,8 @@ extern uint32_t __mbed_krbs_start;
void *__wrap__sbrk(int incr)
{
static uint32_t heap_ind = (uint32_t) &__mbed_sbrk_start;
uint32_t heap_ind_old = heap_ind;
uint32_t heap_ind_new = (heap_ind_old + incr + 7) & ~7;
uint32_t heap_ind_old = NU_ALIGN_UP(heap_ind, NU_HEAP_ALIGN);
uint32_t heap_ind_new = NU_ALIGN_UP(heap_ind_old + incr, NU_HEAP_ALIGN);
if (heap_ind_new > &__mbed_krbs_start) {
errno = ENOMEM;

View File

@ -25,8 +25,6 @@
#include "objects.h"
#include "PeripheralPins.h"
void us_ticker_prepare_sleep(struct sleep_s *obj);
void us_ticker_wakeup_from_sleep(struct sleep_s *obj);
static void mbed_enter_sleep(struct sleep_s *obj);
static void mbed_exit_sleep(struct sleep_s *obj);
@ -57,8 +55,7 @@ void deepsleep(void)
mbed_exit_sleep(&sleep_obj);
}
void mbed_enter_sleep(struct sleep_s *obj)
static void mbed_enter_sleep(struct sleep_s *obj)
{
// Check if serial allows entering power-down mode
if (obj->powerdown) {
@ -77,16 +74,7 @@ void mbed_enter_sleep(struct sleep_s *obj)
obj->powerdown = pwmout_allow_powerdown();
}
// TODO: Check if other peripherals allow entering power-down mode
obj->start_us = lp_ticker_read();
// Let us_ticker prepare for power-down or reject it.
us_ticker_prepare_sleep(obj);
// NOTE(STALE): To pass mbed-drivers test, timer requires to be fine-grained, so its implementation needs HIRC rather than LIRC/LXT as its clock source.
// But as CLK_PowerDown()/CLK_Idle() is called, HIRC will be disabled and timer cannot keep counting and alarm. To overcome the dilemma,
// just make CPU halt and compromise power saving.
// NOTE: As CLK_PowerDown()/CLK_Idle() is called, HIRC/HXT will be disabled in normal mode, but not in ICE mode. This may cause confusion in development.
if (obj->powerdown) { // Power-down mode (HIRC/HXT disabled, LIRC/LXT enabled)
SYS_UnlockReg();
CLK_PowerDown();
@ -101,14 +89,9 @@ void mbed_enter_sleep(struct sleep_s *obj)
__NOP();
__NOP();
__NOP();
obj->end_us = lp_ticker_read();
obj->period_us = (obj->end_us > obj->start_us) ? (obj->end_us - obj->start_us) : (uint32_t) ((uint64_t) obj->end_us + 0xFFFFFFFFu - obj->start_us);
// Let us_ticker recover from power-down.
us_ticker_wakeup_from_sleep(obj);
}
void mbed_exit_sleep(struct sleep_s *obj)
static void mbed_exit_sleep(struct sleep_s *obj)
{
// TODO: TO BE CONTINUED

View File

@ -27,29 +27,22 @@
#define TMR0HIRES_CLK_PER_SEC (1000 * 1000)
#define TMR1HIRES_CLK_PER_SEC (1000 * 1000)
#define TMR1LORES_CLK_PER_SEC (__LIRC)
#define US_PER_TMR0HIRES_CLK (US_PER_SEC / TMR0HIRES_CLK_PER_SEC)
#define US_PER_TMR1HIRES_CLK (US_PER_SEC / TMR1HIRES_CLK_PER_SEC)
#define US_PER_TMR1LORES_CLK (US_PER_SEC / TMR1LORES_CLK_PER_SEC)
#define US_PER_TMR0HIRES_INT (1000 * 1000 * 10)
#define TMR0HIRES_CLK_PER_TMR0HIRES_INT ((uint32_t) ((uint64_t) US_PER_TMR0HIRES_INT * TMR0HIRES_CLK_PER_SEC / US_PER_SEC))
// Determine to use lo-res/hi-res timer according to CD period
#define US_TMR_SEP_CD 1000
static void tmr0_vec(void);
static void tmr1_vec(void);
static void us_ticker_arm_cd(void);
static int us_ticker_inited = 0;
static volatile uint32_t counter_major = 0;
static volatile uint32_t pd_comp_us = 0; // Power-down compenstaion for normal counter
static volatile uint32_t cd_major_minor_us = 0;
static volatile uint32_t cd_minor_us = 0;
static volatile int cd_hires_tmr_armed = 0; // Flag of armed or not of hi-res timer for CD counter
// NOTE: PCLK is set up in mbed_sdk_init(), invocation of which must be before C++ global object constructor. See init_api.c for details.
// NOTE: Choose clock source of timer:
@ -58,7 +51,6 @@ static volatile int cd_hires_tmr_armed = 0; // Flag of armed or not of hi-res ti
// 3. PCLK(HXT): Less accurate but can pass mbed-drivers test.
// NOTE: TIMER_0 for normal counter, TIMER_1 for countdown.
static const struct nu_modinit_s timer0hires_modinit = {TIMER_0, TMR0_MODULE, CLK_CLKSEL1_TMR0SEL_PCLK0, 0, TMR0_RST, TMR0_IRQn, (void *) tmr0_vec};
static const struct nu_modinit_s timer1lores_modinit = {TIMER_1, TMR1_MODULE, CLK_CLKSEL1_TMR1SEL_LIRC, 0, TMR1_RST, TMR1_IRQn, (void *) tmr1_vec};
static const struct nu_modinit_s timer1hires_modinit = {TIMER_1, TMR1_MODULE, CLK_CLKSEL1_TMR1SEL_PCLK0, 0, TMR1_RST, TMR1_IRQn, (void *) tmr1_vec};
#define TMR_CMP_MIN 2
@ -71,22 +63,20 @@ void us_ticker_init(void)
}
counter_major = 0;
pd_comp_us = 0;
cd_major_minor_us = 0;
cd_minor_us = 0;
cd_hires_tmr_armed = 0;
us_ticker_inited = 1;
// Reset IP
SYS_ResetModule(timer0hires_modinit.rsetidx);
SYS_ResetModule(timer1lores_modinit.rsetidx);
SYS_ResetModule(timer1hires_modinit.rsetidx);
// Select IP clock source
CLK_SetModuleClock(timer0hires_modinit.clkidx, timer0hires_modinit.clksrc, timer0hires_modinit.clkdiv);
CLK_SetModuleClock(timer1lores_modinit.clkidx, timer1lores_modinit.clksrc, timer1lores_modinit.clkdiv);
CLK_SetModuleClock(timer1hires_modinit.clkidx, timer1hires_modinit.clksrc, timer1hires_modinit.clkdiv);
// Enable IP clock
CLK_EnableModuleClock(timer0hires_modinit.clkidx);
CLK_EnableModuleClock(timer1lores_modinit.clkidx);
CLK_EnableModuleClock(timer1hires_modinit.clkidx);
// Timer for normal counter
uint32_t clk_timer0 = TIMER_GetModuleClock((TIMER_T *) NU_MODBASE(timer0hires_modinit.modname));
@ -100,10 +90,10 @@ void us_ticker_init(void)
((TIMER_T *) NU_MODBASE(timer0hires_modinit.modname))->CMP = cmp_timer0;
NVIC_SetVector(timer0hires_modinit.irq_n, (uint32_t) timer0hires_modinit.var);
NVIC_SetVector(timer1lores_modinit.irq_n, (uint32_t) timer1lores_modinit.var);
NVIC_SetVector(timer1hires_modinit.irq_n, (uint32_t) timer1hires_modinit.var);
NVIC_EnableIRQ(timer0hires_modinit.irq_n);
NVIC_EnableIRQ(timer1lores_modinit.irq_n);
NVIC_EnableIRQ(timer1hires_modinit.irq_n);
TIMER_EnableInt((TIMER_T *) NU_MODBASE(timer0hires_modinit.modname));
TIMER_Start((TIMER_T *) NU_MODBASE(timer0hires_modinit.modname));
@ -141,26 +131,24 @@ uint32_t us_ticker_read()
}
while (minor_us == 0 || minor_us == US_PER_TMR0HIRES_INT);
// Add power-down compensation
return (major_minor_us + pd_comp_us) / US_PER_TICK;
return (major_minor_us / US_PER_TICK);
}
while (0);
}
void us_ticker_disable_interrupt(void)
{
TIMER_DisableInt((TIMER_T *) NU_MODBASE(timer1lores_modinit.modname));
TIMER_DisableInt((TIMER_T *) NU_MODBASE(timer1hires_modinit.modname));
}
void us_ticker_clear_interrupt(void)
{
TIMER_ClearIntFlag((TIMER_T *) NU_MODBASE(timer1lores_modinit.modname));
TIMER_ClearIntFlag((TIMER_T *) NU_MODBASE(timer1hires_modinit.modname));
}
void us_ticker_set_interrupt(timestamp_t timestamp)
{
TIMER_Stop((TIMER_T *) NU_MODBASE(timer1lores_modinit.modname));
cd_hires_tmr_armed = 0;
TIMER_Stop((TIMER_T *) NU_MODBASE(timer1hires_modinit.modname));
int delta = (int) (timestamp - us_ticker_read());
if (delta > 0) {
@ -173,42 +161,10 @@ void us_ticker_set_interrupt(timestamp_t timestamp)
* This event was in the past. Set the interrupt as pending, but don't process it here.
* This prevents a recurive loop under heavy load which can lead to a stack overflow.
*/
NVIC_SetPendingIRQ(timer1lores_modinit.irq_n);
NVIC_SetPendingIRQ(timer1hires_modinit.irq_n);
}
}
void us_ticker_prepare_sleep(struct sleep_s *obj)
{
// Reject power-down if hi-res timer (HIRC/HXT) is now armed for CD counter.
if (obj->powerdown) {
obj->powerdown = ! cd_hires_tmr_armed;
}
core_util_critical_section_enter();
if (obj->powerdown) {
// NOTE: On entering power-down mode, HIRC/HXT will be disabled in normal mode, but not in ICE mode. This may cause confusion in development.
// To not be inconsistent due to above, always disable clock source of normal counter, and then re-enable it and make compensation on wakeup from power-down.
CLK_DisableModuleClock(timer0hires_modinit.clkidx);
}
core_util_critical_section_exit();
}
void us_ticker_wakeup_from_sleep(struct sleep_s *obj)
{
core_util_critical_section_enter();
if (obj->powerdown) {
// Calculate power-down compensation
pd_comp_us += obj->period_us;
CLK_EnableModuleClock(timer0hires_modinit.clkidx);
}
core_util_critical_section_exit();
}
static void tmr0_vec(void)
{
TIMER_ClearIntFlag((TIMER_T *) NU_MODBASE(timer0hires_modinit.modname));
@ -217,9 +173,8 @@ static void tmr0_vec(void)
static void tmr1_vec(void)
{
TIMER_ClearIntFlag((TIMER_T *) NU_MODBASE(timer1lores_modinit.modname));
TIMER_ClearIntFlag((TIMER_T *) NU_MODBASE(timer1hires_modinit.modname));
cd_major_minor_us = (cd_major_minor_us > cd_minor_us) ? (cd_major_minor_us - cd_minor_us) : 0;
cd_hires_tmr_armed = 0;
if (cd_major_minor_us == 0) {
// NOTE: us_ticker_set_interrupt() may get called in us_ticker_irq_handler();
us_ticker_irq_handler();
@ -231,49 +186,22 @@ static void tmr1_vec(void)
static void us_ticker_arm_cd(void)
{
TIMER_T * timer1_base = (TIMER_T *) NU_MODBASE(timer1lores_modinit.modname);
uint32_t tmr1_clk_per_sec;
uint32_t us_per_tmr1_clk;
/**
* Reserve US_TMR_SEP_CD-plus alarm period for hi-res timer
* 1. period >= US_TMR_SEP_CD * 2. Divide into two rounds:
* US_TMR_SEP_CD * n (lo-res timer)
* US_TMR_SEP_CD + period % US_TMR_SEP_CD (hi-res timer)
* 2. period < US_TMR_SEP_CD * 2. Just one round:
* period (hi-res timer)
*/
if (cd_major_minor_us >= US_TMR_SEP_CD * 2) {
cd_minor_us = cd_major_minor_us - cd_major_minor_us % US_TMR_SEP_CD - US_TMR_SEP_CD;
CLK_SetModuleClock(timer1lores_modinit.clkidx, timer1lores_modinit.clksrc, timer1lores_modinit.clkdiv);
tmr1_clk_per_sec = TMR1LORES_CLK_PER_SEC;
us_per_tmr1_clk = US_PER_TMR1LORES_CLK;
cd_hires_tmr_armed = 0;
}
else {
cd_minor_us = cd_major_minor_us;
CLK_SetModuleClock(timer1hires_modinit.clkidx, timer1hires_modinit.clksrc, timer1hires_modinit.clkdiv);
tmr1_clk_per_sec = TMR1HIRES_CLK_PER_SEC;
us_per_tmr1_clk = US_PER_TMR1HIRES_CLK;
cd_hires_tmr_armed = 1;
}
TIMER_T * timer1_base = (TIMER_T *) NU_MODBASE(timer1hires_modinit.modname);
cd_minor_us = cd_major_minor_us;
// Reset 8-bit PSC counter, 24-bit up counter value and CNTEN bit
timer1_base->CTL |= TIMER_CTL_RSTCNT_Msk;
// One-shot mode, Clock = 1 MHz
uint32_t clk_timer1 = TIMER_GetModuleClock((TIMER_T *) NU_MODBASE(timer1lores_modinit.modname));
uint32_t prescale_timer1 = clk_timer1 / tmr1_clk_per_sec - 1;
uint32_t clk_timer1 = TIMER_GetModuleClock((TIMER_T *) NU_MODBASE(timer1hires_modinit.modname));
uint32_t prescale_timer1 = clk_timer1 / TMR1HIRES_CLK_PER_SEC - 1;
MBED_ASSERT((prescale_timer1 != (uint32_t) -1) && prescale_timer1 <= 127);
MBED_ASSERT((clk_timer1 % tmr1_clk_per_sec) == 0);
MBED_ASSERT((clk_timer1 % TMR1HIRES_CLK_PER_SEC) == 0);
// NOTE: TIMER_CTL_CNTDATEN_Msk exists in NUC472, but not in M451. In M451, TIMER_CNT is updated continuously by default.
timer1_base->CTL &= ~(TIMER_CTL_OPMODE_Msk | TIMER_CTL_PSC_Msk/* | TIMER_CTL_CNTDATEN_Msk*/);
timer1_base->CTL |= TIMER_ONESHOT_MODE | prescale_timer1/* | TIMER_CTL_CNTDATEN_Msk*/;
uint32_t cmp_timer1 = cd_minor_us / us_per_tmr1_clk;
uint32_t cmp_timer1 = cd_minor_us / US_PER_TMR1HIRES_CLK;
cmp_timer1 = NU_CLAMP(cmp_timer1, TMR_CMP_MIN, TMR_CMP_MAX);
timer1_base->CMP = cmp_timer1;

View File

@ -118,9 +118,6 @@ struct pwmout_s {
};
struct sleep_s {
uint32_t start_us;
uint32_t end_us;
uint32_t period_us;
int powerdown;
};

View File

@ -11,10 +11,13 @@
#include "NUC472_442.h"
#include <errno.h>
#include "nu_miscutil.h"
extern uint32_t __mbed_sbrk_start;
extern uint32_t __mbed_krbs_start;
#define NU_HEAP_ALIGN 32
/**
* The default implementation of _sbrk() (in common/retarget.cpp) for GCC_ARM requires one-region model (heap and stack share one region), which doesn't
* fit two-region model (heap and stack are two distinct regions), for example, NUMAKER-PFM-NUC472 locates heap on external SRAM. Define __wrap__sbrk() to
@ -23,8 +26,8 @@ extern uint32_t __mbed_krbs_start;
void *__wrap__sbrk(int incr)
{
static uint32_t heap_ind = (uint32_t) &__mbed_sbrk_start;
uint32_t heap_ind_old = heap_ind;
uint32_t heap_ind_new = (heap_ind_old + incr + 7) & ~7;
uint32_t heap_ind_old = NU_ALIGN_UP(heap_ind, NU_HEAP_ALIGN);
uint32_t heap_ind_new = NU_ALIGN_UP(heap_ind_old + incr, NU_HEAP_ALIGN);
if (heap_ind_new > &__mbed_krbs_start) {
errno = ENOMEM;

View File

@ -25,8 +25,6 @@
#include "objects.h"
#include "PeripheralPins.h"
void us_ticker_prepare_sleep(struct sleep_s *obj);
void us_ticker_wakeup_from_sleep(struct sleep_s *obj);
static void mbed_enter_sleep(struct sleep_s *obj);
static void mbed_exit_sleep(struct sleep_s *obj);
@ -77,15 +75,6 @@ static void mbed_enter_sleep(struct sleep_s *obj)
}
// TODO: Check if other peripherals allow entering power-down mode
obj->start_us = lp_ticker_read();
// Let us_ticker prepare for power-down or reject it.
us_ticker_prepare_sleep(obj);
// NOTE(STALE): To pass mbed-drivers test, timer requires to be fine-grained, so its implementation needs HIRC rather than LIRC/LXT as its clock source.
// But as CLK_PowerDown()/CLK_Idle() is called, HIRC will be disabled and timer cannot keep counting and alarm. To overcome the dilemma,
// just make CPU halt and compromise power saving.
// NOTE: As CLK_PowerDown()/CLK_Idle() is called, HIRC/HXT will be disabled in normal mode, but not in ICE mode. This may cause confusion in development.
if (obj->powerdown) { // Power-down mode (HIRC/HXT disabled, LIRC/LXT enabled)
SYS_UnlockReg();
CLK_PowerDown();
@ -103,11 +92,6 @@ static void mbed_enter_sleep(struct sleep_s *obj)
__NOP();
__NOP();
__NOP();
obj->end_us = lp_ticker_read();
obj->period_us = (obj->end_us > obj->start_us) ? (obj->end_us - obj->start_us) : (uint32_t) ((uint64_t) obj->end_us + 0xFFFFFFFFu - obj->start_us);
// Let us_ticker recover from power-down.
us_ticker_wakeup_from_sleep(obj);
}
static void mbed_exit_sleep(struct sleep_s *obj)

View File

@ -27,29 +27,22 @@
#define TMR0HIRES_CLK_PER_SEC (1000 * 1000)
#define TMR1HIRES_CLK_PER_SEC (1000 * 1000)
#define TMR1LORES_CLK_PER_SEC (__LIRC)
#define US_PER_TMR0HIRES_CLK (US_PER_SEC / TMR0HIRES_CLK_PER_SEC)
#define US_PER_TMR1HIRES_CLK (US_PER_SEC / TMR1HIRES_CLK_PER_SEC)
#define US_PER_TMR1LORES_CLK (US_PER_SEC / TMR1LORES_CLK_PER_SEC)
#define US_PER_TMR0HIRES_INT (1000 * 1000 * 10)
#define TMR0HIRES_CLK_PER_TMR0HIRES_INT ((uint32_t) ((uint64_t) US_PER_TMR0HIRES_INT * TMR0HIRES_CLK_PER_SEC / US_PER_SEC))
// Determine to use lo-res/hi-res timer according to CD period
#define US_TMR_SEP_CD 1000
static void tmr0_vec(void);
static void tmr1_vec(void);
static void us_ticker_arm_cd(void);
static int us_ticker_inited = 0;
static volatile uint32_t counter_major = 0;
static volatile uint32_t pd_comp_us = 0; // Power-down compenstaion for normal counter
static volatile uint32_t cd_major_minor_us = 0;
static volatile uint32_t cd_minor_us = 0;
static volatile int cd_hires_tmr_armed = 0; // Flag of armed or not of hi-res timer for CD counter
// NOTE: PCLK is set up in mbed_sdk_init(), invocation of which must be before C++ global object constructor. See init_api.c for details.
// NOTE: Choose clock source of timer:
@ -58,7 +51,6 @@ static volatile int cd_hires_tmr_armed = 0; // Flag of armed or not of hi-res ti
// 3. PCLK(HXT): Less accurate but can pass mbed-drivers test.
// NOTE: TIMER_0 for normal counter, TIMER_1 for countdown.
static const struct nu_modinit_s timer0hires_modinit = {TIMER_0, TMR0_MODULE, CLK_CLKSEL1_TMR0SEL_PCLK, 0, TMR0_RST, TMR0_IRQn, (void *) tmr0_vec};
static const struct nu_modinit_s timer1lores_modinit = {TIMER_1, TMR1_MODULE, CLK_CLKSEL1_TMR1SEL_LIRC, 0, TMR1_RST, TMR1_IRQn, (void *) tmr1_vec};
static const struct nu_modinit_s timer1hires_modinit = {TIMER_1, TMR1_MODULE, CLK_CLKSEL1_TMR1SEL_PCLK, 0, TMR1_RST, TMR1_IRQn, (void *) tmr1_vec};
#define TMR_CMP_MIN 2
@ -71,22 +63,20 @@ void us_ticker_init(void)
}
counter_major = 0;
pd_comp_us = 0;
cd_major_minor_us = 0;
cd_minor_us = 0;
cd_hires_tmr_armed = 0;
us_ticker_inited = 1;
// Reset IP
SYS_ResetModule(timer0hires_modinit.rsetidx);
SYS_ResetModule(timer1lores_modinit.rsetidx);
SYS_ResetModule(timer1hires_modinit.rsetidx);
// Select IP clock source
CLK_SetModuleClock(timer0hires_modinit.clkidx, timer0hires_modinit.clksrc, timer0hires_modinit.clkdiv);
CLK_SetModuleClock(timer1lores_modinit.clkidx, timer1lores_modinit.clksrc, timer1lores_modinit.clkdiv);
CLK_SetModuleClock(timer1hires_modinit.clkidx, timer1hires_modinit.clksrc, timer1hires_modinit.clkdiv);
// Enable IP clock
CLK_EnableModuleClock(timer0hires_modinit.clkidx);
CLK_EnableModuleClock(timer1lores_modinit.clkidx);
CLK_EnableModuleClock(timer1hires_modinit.clkidx);
// Timer for normal counter
uint32_t clk_timer0 = TIMER_GetModuleClock((TIMER_T *) NU_MODBASE(timer0hires_modinit.modname));
@ -99,10 +89,10 @@ void us_ticker_init(void)
((TIMER_T *) NU_MODBASE(timer0hires_modinit.modname))->CMP = cmp_timer0;
NVIC_SetVector(timer0hires_modinit.irq_n, (uint32_t) timer0hires_modinit.var);
NVIC_SetVector(timer1lores_modinit.irq_n, (uint32_t) timer1lores_modinit.var);
NVIC_SetVector(timer1hires_modinit.irq_n, (uint32_t) timer1hires_modinit.var);
NVIC_EnableIRQ(timer0hires_modinit.irq_n);
NVIC_EnableIRQ(timer1lores_modinit.irq_n);
NVIC_EnableIRQ(timer1hires_modinit.irq_n);
TIMER_EnableInt((TIMER_T *) NU_MODBASE(timer0hires_modinit.modname));
TIMER_Start((TIMER_T *) NU_MODBASE(timer0hires_modinit.modname));
@ -140,26 +130,24 @@ uint32_t us_ticker_read()
}
while (minor_us == 0 || minor_us == US_PER_TMR0HIRES_INT);
// Add power-down compensation
return (major_minor_us + pd_comp_us) / US_PER_TICK;
return (major_minor_us / US_PER_TICK);
}
while (0);
}
void us_ticker_disable_interrupt(void)
{
TIMER_DisableInt((TIMER_T *) NU_MODBASE(timer1lores_modinit.modname));
TIMER_DisableInt((TIMER_T *) NU_MODBASE(timer1hires_modinit.modname));
}
void us_ticker_clear_interrupt(void)
{
TIMER_ClearIntFlag((TIMER_T *) NU_MODBASE(timer1lores_modinit.modname));
TIMER_ClearIntFlag((TIMER_T *) NU_MODBASE(timer1hires_modinit.modname));
}
void us_ticker_set_interrupt(timestamp_t timestamp)
{
TIMER_Stop((TIMER_T *) NU_MODBASE(timer1lores_modinit.modname));
cd_hires_tmr_armed = 0;
TIMER_Stop((TIMER_T *) NU_MODBASE(timer1hires_modinit.modname));
int delta = (int) (timestamp - us_ticker_read());
if (delta > 0) {
@ -172,42 +160,10 @@ void us_ticker_set_interrupt(timestamp_t timestamp)
* This event was in the past. Set the interrupt as pending, but don't process it here.
* This prevents a recurive loop under heavy load which can lead to a stack overflow.
*/
NVIC_SetPendingIRQ(timer1lores_modinit.irq_n);
NVIC_SetPendingIRQ(timer1hires_modinit.irq_n);
}
}
void us_ticker_prepare_sleep(struct sleep_s *obj)
{
// Reject power-down if hi-res timer (HIRC/HXT) is now armed for CD counter.
if (obj->powerdown) {
obj->powerdown = ! cd_hires_tmr_armed;
}
core_util_critical_section_enter();
if (obj->powerdown) {
// NOTE: On entering power-down mode, HIRC/HXT will be disabled in normal mode, but not in ICE mode. This may cause confusion in development.
// To not be inconsistent due to above, always disable clock source of normal counter, and then re-enable it and make compensation on wakeup from power-down.
CLK_DisableModuleClock(timer0hires_modinit.clkidx);
}
core_util_critical_section_exit();
}
void us_ticker_wakeup_from_sleep(struct sleep_s *obj)
{
core_util_critical_section_enter();
if (obj->powerdown) {
// Calculate power-down compensation
pd_comp_us += obj->period_us;
CLK_EnableModuleClock(timer0hires_modinit.clkidx);
}
core_util_critical_section_exit();
}
static void tmr0_vec(void)
{
TIMER_ClearIntFlag((TIMER_T *) NU_MODBASE(timer0hires_modinit.modname));
@ -216,9 +172,8 @@ static void tmr0_vec(void)
static void tmr1_vec(void)
{
TIMER_ClearIntFlag((TIMER_T *) NU_MODBASE(timer1lores_modinit.modname));
TIMER_ClearIntFlag((TIMER_T *) NU_MODBASE(timer1hires_modinit.modname));
cd_major_minor_us = (cd_major_minor_us > cd_minor_us) ? (cd_major_minor_us - cd_minor_us) : 0;
cd_hires_tmr_armed = 0;
if (cd_major_minor_us == 0) {
// NOTE: us_ticker_set_interrupt() may get called in us_ticker_irq_handler();
us_ticker_irq_handler();
@ -230,48 +185,21 @@ static void tmr1_vec(void)
static void us_ticker_arm_cd(void)
{
TIMER_T * timer1_base = (TIMER_T *) NU_MODBASE(timer1lores_modinit.modname);
uint32_t tmr1_clk_per_sec;
uint32_t us_per_tmr1_clk;
/**
* Reserve US_TMR_SEP_CD-plus alarm period for hi-res timer
* 1. period >= US_TMR_SEP_CD * 2. Divide into two rounds:
* US_TMR_SEP_CD * n (lo-res timer)
* US_TMR_SEP_CD + period % US_TMR_SEP_CD (hi-res timer)
* 2. period < US_TMR_SEP_CD * 2. Just one round:
* period (hi-res timer)
*/
if (cd_major_minor_us >= US_TMR_SEP_CD * 2) {
cd_minor_us = cd_major_minor_us - cd_major_minor_us % US_TMR_SEP_CD - US_TMR_SEP_CD;
CLK_SetModuleClock(timer1lores_modinit.clkidx, timer1lores_modinit.clksrc, timer1lores_modinit.clkdiv);
tmr1_clk_per_sec = TMR1LORES_CLK_PER_SEC;
us_per_tmr1_clk = US_PER_TMR1LORES_CLK;
cd_hires_tmr_armed = 0;
}
else {
cd_minor_us = cd_major_minor_us;
CLK_SetModuleClock(timer1hires_modinit.clkidx, timer1hires_modinit.clksrc, timer1hires_modinit.clkdiv);
tmr1_clk_per_sec = TMR1HIRES_CLK_PER_SEC;
us_per_tmr1_clk = US_PER_TMR1HIRES_CLK;
cd_hires_tmr_armed = 1;
}
TIMER_T * timer1_base = (TIMER_T *) NU_MODBASE(timer1hires_modinit.modname);
cd_minor_us = cd_major_minor_us;
// Reset 8-bit PSC counter, 24-bit up counter value and CNTEN bit
timer1_base->CTL |= TIMER_CTL_RSTCNT_Msk;
// One-shot mode, Clock = 1 MHz
uint32_t clk_timer1 = TIMER_GetModuleClock((TIMER_T *) NU_MODBASE(timer1lores_modinit.modname));
uint32_t prescale_timer1 = clk_timer1 / tmr1_clk_per_sec - 1;
uint32_t clk_timer1 = TIMER_GetModuleClock((TIMER_T *) NU_MODBASE(timer1hires_modinit.modname));
uint32_t prescale_timer1 = clk_timer1 / TMR1HIRES_CLK_PER_SEC - 1;
MBED_ASSERT((prescale_timer1 != (uint32_t) -1) && prescale_timer1 <= 127);
MBED_ASSERT((clk_timer1 % tmr1_clk_per_sec) == 0);
MBED_ASSERT((clk_timer1 % TMR1HIRES_CLK_PER_SEC) == 0);
timer1_base->CTL &= ~(TIMER_CTL_OPMODE_Msk | TIMER_CTL_PSC_Msk | TIMER_CTL_CNTDATEN_Msk);
timer1_base->CTL |= TIMER_ONESHOT_MODE | prescale_timer1 | TIMER_CTL_CNTDATEN_Msk;
uint32_t cmp_timer1 = cd_minor_us / us_per_tmr1_clk;
uint32_t cmp_timer1 = cd_minor_us / US_PER_TMR1HIRES_CLK;
cmp_timer1 = NU_CLAMP(cmp_timer1, TMR_CMP_MIN, TMR_CMP_MAX);
timer1_base->CMP = cmp_timer1;

View File

@ -24,6 +24,8 @@ extern "C" {
#define NU_MAX(a,b) ((a)>(b)?(a):(b))
#define NU_MIN(a,b) ((a)<(b)?(a):(b))
#define NU_CLAMP(x, min, max) NU_MIN(NU_MAX((x), (min)), (max))
#define NU_ALIGN_DOWN(X, ALIGN) ((X) & ~((ALIGN) - 1))
#define NU_ALIGN_UP(X, ALIGN) (((X) + (ALIGN) - 1) & ~((ALIGN) - 1))
void nu_nop(uint32_t n);

View File

@ -83,14 +83,18 @@
#define I2C_APB_CLK_DIVIDER_VAL_MASK 0x1FE0
/* Error check */
#define I2C_UFL_CHECK (d->membase->STATUS.WORD & 0x80)
#define FIFO_OFL_CHECK (d->membase->STATUS.WORD & 0x10)
#define I2C_BUS_ERR_CHECK (d->membase->STATUS.WORD & 0x04)
#define RD_DATA_READY (d->membase->STATUS.WORD & 0x02)
#define I2C_UFL_CHECK (obj->membase->STATUS.WORD & 0x80)
#define I2C_FIFO_FULL (obj->membase->STATUS.WORD & 0x20)
#define FIFO_OFL_CHECK (obj->membase->STATUS.WORD & 0x10)
#define I2C_BUS_ERR_CHECK (obj->membase->STATUS.WORD & 0x04)
#define RD_DATA_READY (obj->membase->STATUS.WORD & 0x02)
#define I2C_FIFO_EMPTY (obj->membase->STATUS.WORD & 0x01)
#define I2C_API_STATUS_SUCCESS 0
#define PAD_REG_ADRS_BYTE_SIZE 4
#define SEND_COMMAND(cmd) while(!I2C_FIFO_EMPTY); wait_us(1); obj->membase->CMD_REG = cmd;
/** Init I2C device.
* @details
* Sets the necessary registers. The baud rate is set default to 100K
@ -154,4 +158,4 @@ extern int32_t fI2cReadB(i2c_t *d, char *buf, int len);
*/
extern int32_t fI2cWriteB(i2c_t *d, const char *buf, int len);
#endif /* I2C_H_ */
#endif /* I2C_H_ */

View File

@ -31,6 +31,7 @@
#include "i2c.h"
#include "i2c_api.h"
#include "wait_api.h"
#define I2C_READ_WRITE_BIT_MASK 0xFE
@ -151,10 +152,10 @@ int i2c_byte_read(i2c_t *obj, int last) /* TODO return size can be uint8_t */
}
if(last) {
/* ACK */
obj->membase->CMD_REG = I2C_CMD_WDAT0;
SEND_COMMAND(I2C_CMD_WDAT0);
} else {
/* No ACK */
obj->membase->CMD_REG = I2C_CMD_WDAT1;
SEND_COMMAND(I2C_CMD_WDAT1);
}
return data;
}
@ -168,8 +169,6 @@ int i2c_byte_write(i2c_t *obj, int data)
return Count;
}
obj->membase->CMD_REG = I2C_CMD_VRFY_ACK; /* Verify ACK */
while(obj->membase->STATUS.WORD & I2C_STATUS_CMD_FIFO_OFL_BIT); /* Wait till command overflow ends */
if(obj->membase->STATUS.WORD & I2C_STATUS_BUS_ERR_BIT) {
@ -181,4 +180,4 @@ int i2c_byte_write(i2c_t *obj, int data)
}
}
#endif /* DEVICE_I2C */
#endif /* DEVICE_I2C */

View File

@ -60,6 +60,7 @@
*/
#if DEVICE_I2C
#include "i2c.h"
#include "wait_api.h"
/* See i2c.h for details */
void fI2cInit(i2c_t *obj,PinName sda,PinName scl)
@ -135,7 +136,7 @@ void fI2cFrequency(i2c_t *obj, uint32_t hz)
int32_t fI2cStart(i2c_t *obj)
{
/* Send start bit */
obj->membase->CMD_REG = I2C_CMD_START;
SEND_COMMAND(I2C_CMD_START);
return I2C_API_STATUS_SUCCESS;
}
@ -143,7 +144,7 @@ int32_t fI2cStart(i2c_t *obj)
int32_t fI2cStop(i2c_t *obj)
{
/* Send stop bit */
obj->membase->CMD_REG = I2C_CMD_STOP;
SEND_COMMAND(I2C_CMD_STOP);
if (obj->membase->STATUS.WORD & (I2C_STATUS_CMD_FIFO_FULL_BIT |
I2C_STATUS_CMD_FIFO_OFL_BIT |
I2C_STATUS_BUS_ERR_BIT)) {
@ -154,23 +155,26 @@ int32_t fI2cStop(i2c_t *obj)
}
/* See i2c.h for details */
int32_t fI2cReadB(i2c_t *d, char *buf, int len)
int32_t fI2cReadB(i2c_t *obj, char *buf, int len)
{
int32_t read = 0;
while (read < len) {
/* Send read command */
d->membase->CMD_REG = I2C_CMD_RDAT8;
SEND_COMMAND(I2C_CMD_RDAT8);
while(!RD_DATA_READY) {
if (I2C_BUS_ERR_CHECK) {
/* Bus error occured */
return I2C_ERROR_BUS_BUSY;
}
}
buf[read++] = d->membase->RD_FIFO_REG; /**< Reading 'read FIFO register' will clear status register */
buf[read++] = obj->membase->RD_FIFO_REG; /**< Reading 'read FIFO register' will clear status register */
if(!(read>=len)) { /* No ACK will be generated for the last read, upper level I2C protocol should generate */
d->membase->CMD_REG=I2C_CMD_WDAT0; /* TODO based on requirement generate ACK or NACK Based on the requirement. */
SEND_COMMAND(I2C_CMD_WDAT0); /* TODO based on requirement generate ACK or NACK Based on the requirement. */
} else {
/* No ack */
SEND_COMMAND(I2C_CMD_WDAT1);
}
/* check for FIFO underflow */
@ -187,42 +191,49 @@ int32_t fI2cReadB(i2c_t *d, char *buf, int len)
}
/* See i2c.h for details */
int32_t fI2cWriteB(i2c_t *d, const char *buf, int len)
int32_t fI2cWriteB(i2c_t *obj, const char *buf, int len)
{
int32_t write = 0;
while (write < len) {
/* Send write command */
d->membase->CMD_REG = I2C_CMD_WDAT8;
SEND_COMMAND(I2C_CMD_WDAT8);
if(buf[write] == I2C_CMD_RDAT8) {
/* SW work around to counter FSM issue. If the only command in the CMD FIFO is the WDAT8 command (data of 0x13)
then as the command is read out (i.e. the FIFO goes empty), the WDAT8 command will be misinterpreted as a
RDAT8 command by the data FSM; resulting in an I2C bus error (NACK instead of an ACK). */
/* Send 0x13 bit wise */
d->membase->CMD_REG = I2C_CMD_WDAT0;
d->membase->CMD_REG = I2C_CMD_WDAT0;
d->membase->CMD_REG = I2C_CMD_WDAT0;
d->membase->CMD_REG = I2C_CMD_WDAT1;
SEND_COMMAND(I2C_CMD_WDAT0);
d->membase->CMD_REG = I2C_CMD_WDAT0;
d->membase->CMD_REG = I2C_CMD_WDAT0;
d->membase->CMD_REG = I2C_CMD_WDAT1;
d->membase->CMD_REG = I2C_CMD_WDAT1;
SEND_COMMAND(I2C_CMD_WDAT0);
SEND_COMMAND(I2C_CMD_WDAT0);
SEND_COMMAND(I2C_CMD_WDAT1);
SEND_COMMAND(I2C_CMD_WDAT0);
SEND_COMMAND(I2C_CMD_WDAT0);
SEND_COMMAND(I2C_CMD_WDAT1);
SEND_COMMAND(I2C_CMD_WDAT1);
} else {
/* Send data */
d->membase->CMD_REG = buf[write++];
SEND_COMMAND(buf[write++]);
}
d->membase->CMD_REG = I2C_CMD_VRFY_ACK; /* TODO Verify ACK based on requirement, Do we need? */
while(FIFO_OFL_CHECK); /* Wait till command overflow ends */
SEND_COMMAND(I2C_CMD_VRFY_ACK); /* TODO Verify ACK based on requirement, Do we need? */
if (I2C_BUS_ERR_CHECK) {
/* Bus error */
return I2C_ERROR_BUS_BUSY;
}
while(FIFO_OFL_CHECK); /* Wait till command overflow ends */
}
return write;
}
#endif /* DEVICE_I2C */
#endif /* DEVICE_I2C */

View File

@ -37,7 +37,7 @@ static int us_ticker_inited = 0;
static void us_timer_init(void);
static uint32_t us_ticker_int_counter = 0;
static uint32_t us_ticker_target = 0;
static volatile uint32_t msb_counter = 0;
void us_ticker_init(void)
@ -168,20 +168,25 @@ extern void us_ticker_isr(void)
/* Clear IRQ flag */
TIM1REG->CLEAR = 0;
/* If this is a longer timer it will take multiple full hw counter cycles */
if (us_ticker_int_counter > 0) {
ticker_set(0xFFFF);
us_ticker_int_counter--;
} else {
int32_t delta = us_ticker_target - us_ticker_read();
if (delta <= 0) {
TIM1REG->CONTROL.BITS.ENABLE = False;
us_ticker_irq_handler();
} else {
// Clamp at max value of timer
if (delta > 0xFFFF) {
delta = 0xFFFF;
}
ticker_set(delta);
}
}
/* Set timer 1 ticker interrupt */
void us_ticker_set_interrupt(timestamp_t timestamp)
{
int32_t delta = (uint32_t)timestamp - us_ticker_read();
us_ticker_target = (uint32_t)timestamp;
int32_t delta = us_ticker_target - us_ticker_read();
if (delta <= 0) {
/* This event was in the past */
@ -195,10 +200,10 @@ void us_ticker_set_interrupt(timestamp_t timestamp)
return;
}
/* Calculate how much delta falls outside the 16-bit counter range. */
/* You will have to perform a full timer overflow for each bit above */
/* that range. */
us_ticker_int_counter = (uint32_t)(delta >> 16);
// Clamp at max value of timer
if (delta > 0xFFFF) {
delta = 0xFFFF;
}
ticker_set(delta);
}

View File

@ -166,7 +166,6 @@ int gpio_irq_init(gpio_irq_t *obj, PinName pin, gpio_irq_handler handler, uint32
InterruptHandlerRegister((IRQn_Type)(nIRQn_h+obj->ch), (void (*)(uint32_t))irq_tbl[obj->ch]);
INTCICR1 &= ~(0x3 << shift);
GIC_SetPriority((IRQn_Type)(nIRQn_h+obj->ch), 5);
GIC_EnableIRQ((IRQn_Type)(nIRQn_h+obj->ch));
obj->int_enable = 1;
__enable_irq();

View File

@ -83,7 +83,9 @@
HAL_StatusTypeDef HAL_Init(void);
#define HSE_VALUE ((uint32_t)25000000) /*!< Default value of the External oscillator in Hz */
#if !defined (HSE_VALUE)
#define HSE_VALUE ((uint32_t)25000000) /*!< Value of the External oscillator in Hz */
#endif /* HSE_VALUE */
#if !defined (HSI_VALUE)
#define HSI_VALUE ((uint32_t)16000000) /*!< Value of the Internal oscillator in Hz*/

View File

@ -83,7 +83,9 @@
HAL_StatusTypeDef HAL_Init(void);
#define HSE_VALUE ((uint32_t)25000000) /*!< Default value of the External oscillator in Hz */
#if !defined (HSE_VALUE)
#define HSE_VALUE ((uint32_t)25000000) /*!< Value of the External oscillator in Hz */
#endif /* HSE_VALUE */
#if !defined (HSI_VALUE)
#define HSI_VALUE ((uint32_t)16000000) /*!< Value of the Internal oscillator in Hz*/

View File

@ -103,9 +103,12 @@
* This value is used by the RCC HAL module to compute the system frequency
* (when HSE is used as system clock source, directly or through the PLL).
*/
#if !defined (HSE_VALUE)
#define HSE_VALUE 8000000U /*!< Value of the External oscillator in Hz */
#endif /* HSE_VALUE */
//#if !defined (HSE_VALUE)
#if defined(TARGET_DISCO_F746NG) || defined(TARGET_DISCO_F769NI)
#define HSE_VALUE 25000000U /*!< Value of the External oscillator in Hz */
#else
#define HSE_VALUE 8000000U /*!< Default value of the External oscillator in Hz */
#endif
#if !defined (HSE_STARTUP_TIMEOUT)
#define HSE_STARTUP_TIMEOUT 200U /*!< Time out for HSE start up, in ms */

View File

@ -1123,9 +1123,12 @@ HAL_StatusTypeDef HAL_RTCEx_SetWakeUpTimer_IT(RTC_HandleTypeDef *hrtc, uint32_t
}
}
}
/* Disable the Wake-Up timer */
__HAL_RTC_WAKEUPTIMER_DISABLE(hrtc);
/* Clear flag Wake-Up */
__HAL_RTC_WAKEUPTIMER_CLEAR_FLAG(hrtc, RTC_FLAG_WUTF);
tickstart = HAL_GetTick();
/* Wait till RTC WUTWF flag is set and if Time out is reached exit */

View File

@ -291,23 +291,28 @@ void spi_frequency(spi_t *obj, int hz) {
struct spi_s *spiobj = SPI_S(obj);
int spi_hz = 0;
uint8_t prescaler_rank = 0;
uint8_t last_index = (sizeof(baudrate_prescaler_table)/sizeof(baudrate_prescaler_table[0])) - 1;
SPI_HandleTypeDef *handle = &(spiobj->handle);
/* Get the clock of the peripheral */
spi_hz = spi_get_clock_freq(obj);
/* Calculate the spi clock for prescaler_rank 0: SPI_BAUDRATEPRESCALER_2 */
spi_hz = spi_get_clock_freq(obj) / 2;
/* Define pre-scaler in order to get highest available frequency below requested frequency */
while ((spi_hz > hz) && (prescaler_rank < sizeof(baudrate_prescaler_table)/sizeof(baudrate_prescaler_table[0]))){
while ((spi_hz > hz) && (prescaler_rank < last_index)) {
spi_hz = spi_hz / 2;
prescaler_rank++;
}
if (prescaler_rank <= sizeof(baudrate_prescaler_table)/sizeof(baudrate_prescaler_table[0])) {
handle->Init.BaudRatePrescaler = baudrate_prescaler_table[prescaler_rank-1];
} else {
error("Couldn't setup requested SPI frequency");
/* Use the best fit pre-scaler */
handle->Init.BaudRatePrescaler = baudrate_prescaler_table[prescaler_rank];
/* In case maximum pre-scaler still gives too high freq, raise an error */
if (spi_hz > hz) {
error("Couldn't set suitable spi freq: request:%d, lowest:%d\r\n", hz, spi_hz);
}
DEBUG_PRINTF("spi_frequency, request:%d, select:%d\r\n", hz, spi_hz);
init_spi(obj);
}

View File

@ -167,5 +167,11 @@
},
"NCS36510":{
"OGChipSelectEditMenu": "NCS36510\tONSemiconductor NCS36510"
},
"NUC472HI8AE": {
"OGChipSelectEditMenu": "NUC400AE series\tNuvoton NUC400AE series (NUC442AE,NUC472AE)"
},
"M453VG6AE": {
"OGChipSelectEditMenu": "M451AE series\tNuvoton M451AE series (M451AE,M452AE,M453AE,M451MAE)"
}
}