From 7697432377e85e17f3c21d2158ba958760fedb9a Mon Sep 17 00:00:00 2001 From: pbrier Date: Sat, 6 Apr 2013 15:50:57 +0200 Subject: [PATCH 01/16] Added __packed macro to be compatible with GCC compiler, in order to build USB libs with GCC_ARM --- features/unsupported/USBDevice/USBDevice/USBHAL.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/features/unsupported/USBDevice/USBDevice/USBHAL.h b/features/unsupported/USBDevice/USBDevice/USBHAL.h index a1bf27a84d..e51dd54d26 100644 --- a/features/unsupported/USBDevice/USBDevice/USBHAL.h +++ b/features/unsupported/USBDevice/USBDevice/USBHAL.h @@ -27,6 +27,10 @@ //#define __packed __attribute__ ((__packed__)) //#endif +#ifdef __GNUC__ +#define __packed __attribute__ ((__packed__)) +#endif + class USBHAL { public: /* Configuration */ From 684e5f059d63f6500a82010053f1da221d25a793 Mon Sep 17 00:00:00 2001 From: ccli8 Date: Thu, 22 Dec 2016 09:58:27 +0800 Subject: [PATCH 02/16] Remove power-down support from us_ticker --- .../TARGET_NUMAKER_PFM_M453/objects.h | 3 - targets/TARGET_NUVOTON/TARGET_M451/sleep.c | 23 +--- .../TARGET_NUVOTON/TARGET_M451/us_ticker.c | 108 +++--------------- .../TARGET_NUMAKER_PFM_NUC472/objects.h | 3 - targets/TARGET_NUVOTON/TARGET_NUC472/sleep.c | 16 --- .../TARGET_NUVOTON/TARGET_NUC472/us_ticker.c | 108 +++--------------- 6 files changed, 39 insertions(+), 222 deletions(-) diff --git a/targets/TARGET_NUVOTON/TARGET_M451/TARGET_NUMAKER_PFM_M453/objects.h b/targets/TARGET_NUVOTON/TARGET_M451/TARGET_NUMAKER_PFM_M453/objects.h index eee0c0bf77..7191422fa0 100644 --- a/targets/TARGET_NUVOTON/TARGET_M451/TARGET_NUMAKER_PFM_M453/objects.h +++ b/targets/TARGET_NUVOTON/TARGET_M451/TARGET_NUMAKER_PFM_M453/objects.h @@ -117,9 +117,6 @@ struct pwmout_s { }; struct sleep_s { - uint32_t start_us; - uint32_t end_us; - uint32_t period_us; int powerdown; }; diff --git a/targets/TARGET_NUVOTON/TARGET_M451/sleep.c b/targets/TARGET_NUVOTON/TARGET_M451/sleep.c index bd6f08fcd4..49ff02008a 100644 --- a/targets/TARGET_NUVOTON/TARGET_M451/sleep.c +++ b/targets/TARGET_NUVOTON/TARGET_M451/sleep.c @@ -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 diff --git a/targets/TARGET_NUVOTON/TARGET_M451/us_ticker.c b/targets/TARGET_NUVOTON/TARGET_M451/us_ticker.c index aecb2373c7..2dc12d2f1c 100644 --- a/targets/TARGET_NUVOTON/TARGET_M451/us_ticker.c +++ b/targets/TARGET_NUVOTON/TARGET_M451/us_ticker.c @@ -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; diff --git a/targets/TARGET_NUVOTON/TARGET_NUC472/TARGET_NUMAKER_PFM_NUC472/objects.h b/targets/TARGET_NUVOTON/TARGET_NUC472/TARGET_NUMAKER_PFM_NUC472/objects.h index 59f3d654ca..2f0596770b 100644 --- a/targets/TARGET_NUVOTON/TARGET_NUC472/TARGET_NUMAKER_PFM_NUC472/objects.h +++ b/targets/TARGET_NUVOTON/TARGET_NUC472/TARGET_NUMAKER_PFM_NUC472/objects.h @@ -118,9 +118,6 @@ struct pwmout_s { }; struct sleep_s { - uint32_t start_us; - uint32_t end_us; - uint32_t period_us; int powerdown; }; diff --git a/targets/TARGET_NUVOTON/TARGET_NUC472/sleep.c b/targets/TARGET_NUVOTON/TARGET_NUC472/sleep.c index 4a51b10184..591e00d560 100644 --- a/targets/TARGET_NUVOTON/TARGET_NUC472/sleep.c +++ b/targets/TARGET_NUVOTON/TARGET_NUC472/sleep.c @@ -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) diff --git a/targets/TARGET_NUVOTON/TARGET_NUC472/us_ticker.c b/targets/TARGET_NUVOTON/TARGET_NUC472/us_ticker.c index de647ecf4a..386ee44d9b 100644 --- a/targets/TARGET_NUVOTON/TARGET_NUC472/us_ticker.c +++ b/targets/TARGET_NUVOTON/TARGET_NUC472/us_ticker.c @@ -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; From d60057e9ef4150a4f7e1585a0084dee7b5755eb0 Mon Sep 17 00:00:00 2001 From: ccli8 Date: Tue, 27 Dec 2016 15:53:51 +0800 Subject: [PATCH 03/16] Change sbrk() allocation to be 32-byte aligned --- .../TARGET_M451/device/TOOLCHAIN_GCC_ARM/m451_retarget.c | 7 +++++-- .../device/TOOLCHAIN_GCC_ARM/nuc472_retarget.c | 7 +++++-- targets/TARGET_NUVOTON/nu_miscutil.h | 2 ++ 3 files changed, 12 insertions(+), 4 deletions(-) diff --git a/targets/TARGET_NUVOTON/TARGET_M451/device/TOOLCHAIN_GCC_ARM/m451_retarget.c b/targets/TARGET_NUVOTON/TARGET_M451/device/TOOLCHAIN_GCC_ARM/m451_retarget.c index 470af432b5..c45bd8207e 100644 --- a/targets/TARGET_NUVOTON/TARGET_M451/device/TOOLCHAIN_GCC_ARM/m451_retarget.c +++ b/targets/TARGET_NUVOTON/TARGET_M451/device/TOOLCHAIN_GCC_ARM/m451_retarget.c @@ -11,10 +11,13 @@ #include "M451Series.h" #include +#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; diff --git a/targets/TARGET_NUVOTON/TARGET_NUC472/device/TOOLCHAIN_GCC_ARM/nuc472_retarget.c b/targets/TARGET_NUVOTON/TARGET_NUC472/device/TOOLCHAIN_GCC_ARM/nuc472_retarget.c index d5c3d874e8..273b3df841 100644 --- a/targets/TARGET_NUVOTON/TARGET_NUC472/device/TOOLCHAIN_GCC_ARM/nuc472_retarget.c +++ b/targets/TARGET_NUVOTON/TARGET_NUC472/device/TOOLCHAIN_GCC_ARM/nuc472_retarget.c @@ -11,10 +11,13 @@ #include "NUC472_442.h" #include +#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; diff --git a/targets/TARGET_NUVOTON/nu_miscutil.h b/targets/TARGET_NUVOTON/nu_miscutil.h index 5d0672445c..fd1cc9e997 100644 --- a/targets/TARGET_NUVOTON/nu_miscutil.h +++ b/targets/TARGET_NUVOTON/nu_miscutil.h @@ -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); From 6538fd6fb7c1c1f54ba51adb12118f1aa9de2af9 Mon Sep 17 00:00:00 2001 From: ccli8 Date: Mon, 16 Jan 2017 10:35:34 +0800 Subject: [PATCH 04/16] Support exporting IAR project --- tools/export/iar/iar_definitions.json | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tools/export/iar/iar_definitions.json b/tools/export/iar/iar_definitions.json index b37eba1ce8..f3b34ad8ec 100644 --- a/tools/export/iar/iar_definitions.json +++ b/tools/export/iar/iar_definitions.json @@ -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)" } } From 251545215e17509b61943fd2ca85fc484e8c70ca Mon Sep 17 00:00:00 2001 From: jeromecoutant Date: Fri, 10 Feb 2017 16:26:10 +0100 Subject: [PATCH 05/16] STM32L4 HAL update for RTC Wake Up Timer --- .../TARGET_STM/TARGET_STM32L4/device/stm32l4xx_hal_rtc_ex.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/targets/TARGET_STM/TARGET_STM32L4/device/stm32l4xx_hal_rtc_ex.c b/targets/TARGET_STM/TARGET_STM32L4/device/stm32l4xx_hal_rtc_ex.c index 1a1b67c8d0..b543ee91ff 100644 --- a/targets/TARGET_STM/TARGET_STM32L4/device/stm32l4xx_hal_rtc_ex.c +++ b/targets/TARGET_STM/TARGET_STM32L4/device/stm32l4xx_hal_rtc_ex.c @@ -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 */ From 182c9bfaffad9bd36558261e81109ebf9fe6a7d0 Mon Sep 17 00:00:00 2001 From: jeromecoutant Date: Fri, 10 Feb 2017 13:06:41 +0100 Subject: [PATCH 06/16] STM32F7 : remove multiple HSE_VALUE define value --- .../TARGET_DISCO_F746NG/system_stm32f7xx.c | 4 +++- .../TARGET_DISCO_F769NI/system_stm32f7xx.c | 4 +++- .../TARGET_STM32F7/device/stm32f7xx_hal_conf.h | 9 ++++++--- 3 files changed, 12 insertions(+), 5 deletions(-) diff --git a/targets/TARGET_STM/TARGET_STM32F7/TARGET_STM32F746xG/TARGET_DISCO_F746NG/system_stm32f7xx.c b/targets/TARGET_STM/TARGET_STM32F7/TARGET_STM32F746xG/TARGET_DISCO_F746NG/system_stm32f7xx.c index fab899fb25..d3e86e4039 100644 --- a/targets/TARGET_STM/TARGET_STM32F7/TARGET_STM32F746xG/TARGET_DISCO_F746NG/system_stm32f7xx.c +++ b/targets/TARGET_STM/TARGET_STM32F7/TARGET_STM32F746xG/TARGET_DISCO_F746NG/system_stm32f7xx.c @@ -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*/ diff --git a/targets/TARGET_STM/TARGET_STM32F7/TARGET_STM32F769xI/TARGET_DISCO_F769NI/system_stm32f7xx.c b/targets/TARGET_STM/TARGET_STM32F7/TARGET_STM32F769xI/TARGET_DISCO_F769NI/system_stm32f7xx.c index c5d91fdaec..00e63dd9d5 100644 --- a/targets/TARGET_STM/TARGET_STM32F7/TARGET_STM32F769xI/TARGET_DISCO_F769NI/system_stm32f7xx.c +++ b/targets/TARGET_STM/TARGET_STM32F7/TARGET_STM32F769xI/TARGET_DISCO_F769NI/system_stm32f7xx.c @@ -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*/ diff --git a/targets/TARGET_STM/TARGET_STM32F7/device/stm32f7xx_hal_conf.h b/targets/TARGET_STM/TARGET_STM32F7/device/stm32f7xx_hal_conf.h index 9260ccee56..dd26352919 100644 --- a/targets/TARGET_STM/TARGET_STM32F7/device/stm32f7xx_hal_conf.h +++ b/targets/TARGET_STM/TARGET_STM32F7/device/stm32f7xx_hal_conf.h @@ -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 */ From 9b89b0632a182871be57c8bb059c932adeabef37 Mon Sep 17 00:00:00 2001 From: Laurent MEUNIER Date: Mon, 13 Feb 2017 16:15:10 +0100 Subject: [PATCH 07/16] STM32: spi_frequency table index fix In case of prescaler_rank was 0, a -1 index was being used, which resulted in initialization of the Init.BaudRatePrescaler with random values. Now let's better check index and avoid -1 operation, so that prescaler_rank can be only from 0 to "last_index". --- targets/TARGET_STM/stm_spi_api.c | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/targets/TARGET_STM/stm_spi_api.c b/targets/TARGET_STM/stm_spi_api.c index 65ce41dc5a..1928253bb6 100644 --- a/targets/TARGET_STM/stm_spi_api.c +++ b/targets/TARGET_STM/stm_spi_api.c @@ -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); } From 12c498ad9b134ed290c3d9d8a6b50eb908f5c630 Mon Sep 17 00:00:00 2001 From: adustm Date: Mon, 13 Feb 2017 17:10:19 +0100 Subject: [PATCH 08/16] Bug fix to fullfill 64bytes transfer in HID --- .../USBDevice/USBDevice/TARGET_STM/USBHAL_STM32F769NI.h | 2 +- .../USBDevice/USBDevice/TARGET_STM/USBHAL_STM32L476VG.h | 2 +- .../USBDevice/USBDevice/TARGET_STM/USBHAL_STM_144_64pins.h | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/features/unsupported/USBDevice/USBDevice/TARGET_STM/USBHAL_STM32F769NI.h b/features/unsupported/USBDevice/USBDevice/TARGET_STM/USBHAL_STM32F769NI.h index 4ef5c58c00..f2bfa7a102 100644 --- a/features/unsupported/USBDevice/USBDevice/TARGET_STM/USBHAL_STM32F769NI.h +++ b/features/unsupported/USBDevice/USBDevice/TARGET_STM/USBHAL_STM32F769NI.h @@ -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)); diff --git a/features/unsupported/USBDevice/USBDevice/TARGET_STM/USBHAL_STM32L476VG.h b/features/unsupported/USBDevice/USBDevice/TARGET_STM/USBHAL_STM32L476VG.h index e313b2529b..b08bce8b40 100644 --- a/features/unsupported/USBDevice/USBDevice/TARGET_STM/USBHAL_STM32L476VG.h +++ b/features/unsupported/USBDevice/USBDevice/TARGET_STM/USBHAL_STM32L476VG.h @@ -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)); diff --git a/features/unsupported/USBDevice/USBDevice/TARGET_STM/USBHAL_STM_144_64pins.h b/features/unsupported/USBDevice/USBDevice/TARGET_STM/USBHAL_STM_144_64pins.h index 15fad1af0a..a9d3760448 100644 --- a/features/unsupported/USBDevice/USBDevice/TARGET_STM/USBHAL_STM_144_64pins.h +++ b/features/unsupported/USBDevice/USBDevice/TARGET_STM/USBHAL_STM_144_64pins.h @@ -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)); From 668e91f2cb7026a7c92dbe423e94d567e607f426 Mon Sep 17 00:00:00 2001 From: Christopher Haster Date: Fri, 9 Dec 2016 17:28:03 -0600 Subject: [PATCH 09/16] events: Added equeue platform timing tests Tests the timer/semaphores at a lower level than the event queue, which removes a layer of concerns from issues in the rtos timing. --- TESTS/events/timing/main.cpp | 122 +++++++++++++++++++++++++++++++++++ 1 file changed, 122 insertions(+) create mode 100644 TESTS/events/timing/main.cpp diff --git a/TESTS/events/timing/main.cpp b/TESTS/events/timing/main.cpp new file mode 100644 index 0000000000..79554e6e15 --- /dev/null +++ b/TESTS/events/timing/main.cpp @@ -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 +#include + +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(2000, 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); +} + From e0ae5e57d839d67b1420acf92780090627a2239f Mon Sep 17 00:00:00 2001 From: Christopher Haster Date: Wed, 15 Feb 2017 09:45:52 -0600 Subject: [PATCH 10/16] NCS36510: Fixed drift in ticker interrupt The NCS36510 is limited to 16bit timers. Construction of larger intervals is performed in software by counting the number of 16bit intervals that pass. Either this counting takes a bit of time, or there is a math error somewhere (maybe a long critical section?), because there is a roughly ~1us delay between when the interrupt occurs and the ticker progresses onto the next 16bit interval. This is normally a completely reasonable error, except that the error accumulates. After a while, the equeue tests find themselves with tens of milliseconds of error. To make matters worse, this error is random because of other interrupts occuring in the system, making the exact issue quite a bit difficult to track down. This fix drops the software counter in favor of just recalculating the next delay interval from the target time and value of the running timer. The running timer used to calculate the current tick is left to overflow in hardware and doesn't have this drift. --- .../TARGET_NCS36510/ncs36510_us_ticker_api.c | 27 +++++++++++-------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/targets/TARGET_ONSEMI/TARGET_NCS36510/ncs36510_us_ticker_api.c b/targets/TARGET_ONSEMI/TARGET_NCS36510/ncs36510_us_ticker_api.c index 8ba3759775..abed10ef06 100644 --- a/targets/TARGET_ONSEMI/TARGET_NCS36510/ncs36510_us_ticker_api.c +++ b/targets/TARGET_ONSEMI/TARGET_NCS36510/ncs36510_us_ticker_api.c @@ -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); } From 1b0fad4bd081a871dc5401fba2c4fbf319e8b97b Mon Sep 17 00:00:00 2001 From: Christopher Haster Date: Wed, 15 Feb 2017 10:04:11 -0600 Subject: [PATCH 11/16] events: Added better handling of desynchronized timers in platform layer An odd bug (c0951c9) in the NCS36510 ticker code caused the timer/ticker classes to become desynchronized. Updated the handling to not assume the timers are perfectly in synch. This will increase the event's tolerance of less robust platforms. --- events/equeue/equeue_mbed.cpp | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/events/equeue/equeue_mbed.cpp b/events/equeue/equeue_mbed.cpp index 9f1ce484de..5c72b38dea 100644 --- a/events/equeue/equeue_mbed.cpp +++ b/events/equeue/equeue_mbed.cpp @@ -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(equeue_timer)->read_ms(); reinterpret_cast(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(equeue_timer)->start(); reinterpret_cast(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(equeue_timer)->read_ms(); - return (equeue_minutes << 16) + equeue_ms; + unsigned minutes; + unsigned ms; + + do { + minutes = equeue_minutes; + ms = reinterpret_cast(equeue_timer)->read_ms(); + } while (minutes != equeue_minutes); + + return minutes + ms; } From 243d47f9fcd8e1f0da156e1caa9cf5a40af6fd98 Mon Sep 17 00:00:00 2001 From: Christopher Haster Date: Thu, 16 Feb 2017 11:43:27 -0600 Subject: [PATCH 12/16] events: Increased test tolerance to +-5ms --- TESTS/events/queue/main.cpp | 2 +- TESTS/events/timing/main.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/TESTS/events/queue/main.cpp b/TESTS/events/queue/main.cpp index bdb58b6eda..f0d1c186f3 100644 --- a/TESTS/events/queue/main.cpp +++ b/TESTS/events/queue/main.cpp @@ -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(); } diff --git a/TESTS/events/timing/main.cpp b/TESTS/events/timing/main.cpp index 79554e6e15..aa361d8dd2 100644 --- a/TESTS/events/timing/main.cpp +++ b/TESTS/events/timing/main.cpp @@ -93,7 +93,7 @@ void semaphore_timing_test() { int taken = timer.read_us() - start; printf("delay %dms => error %dus\r\n", delay, abs(1000*delay - taken)); - TEST_ASSERT_INT_WITHIN(2000, taken, delay * 1000); + TEST_ASSERT_INT_WITHIN(5000, taken, delay * 1000); led = !led; } From 6e4d261df8d52cf5be5a3402a91e535654aa0b3a Mon Sep 17 00:00:00 2001 From: 0xc0170 Date: Mon, 20 Feb 2017 10:32:34 +0000 Subject: [PATCH 13/16] NXP KL43Z/KL27Z: fix spi format bits check Fixes #2989. It was always true for valid values (if its not 8 neither 16 bits, fail). --- .../TARGET_MCUXpresso_MCUS/TARGET_KL27Z/spi_api.c | 2 +- .../TARGET_MCUXpresso_MCUS/TARGET_KL43Z/spi_api.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL27Z/spi_api.c b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL27Z/spi_api.c index 34affdc05e..c478db2485 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL27Z/spi_api.c +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL27Z/spi_api.c @@ -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; } diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL43Z/spi_api.c b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL43Z/spi_api.c index 34affdc05e..c478db2485 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL43Z/spi_api.c +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL43Z/spi_api.c @@ -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; } From e5e32ac3484de6a61bb01a2d438d0f6225a42e3c Mon Sep 17 00:00:00 2001 From: pradeep-gr Date: Wed, 8 Feb 2017 17:13:13 +0530 Subject: [PATCH 14/16] NCS36510: I2C idle delay of 1us It is added between I2C commands as I2C_COMMAND_FIFO is too fast to push commands out. --- targets/TARGET_ONSEMI/TARGET_NCS36510/i2c.h | 14 +++-- .../TARGET_ONSEMI/TARGET_NCS36510/i2c_api.c | 9 ++-- .../TARGET_NCS36510/ncs36510_i2c.c | 53 +++++++++++-------- 3 files changed, 45 insertions(+), 31 deletions(-) diff --git a/targets/TARGET_ONSEMI/TARGET_NCS36510/i2c.h b/targets/TARGET_ONSEMI/TARGET_NCS36510/i2c.h index 15abc34edd..bcbafbe000 100644 --- a/targets/TARGET_ONSEMI/TARGET_NCS36510/i2c.h +++ b/targets/TARGET_ONSEMI/TARGET_NCS36510/i2c.h @@ -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_ */ \ No newline at end of file diff --git a/targets/TARGET_ONSEMI/TARGET_NCS36510/i2c_api.c b/targets/TARGET_ONSEMI/TARGET_NCS36510/i2c_api.c index 8b254c8c90..1e134581a3 100644 --- a/targets/TARGET_ONSEMI/TARGET_NCS36510/i2c_api.c +++ b/targets/TARGET_ONSEMI/TARGET_NCS36510/i2c_api.c @@ -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 */ \ No newline at end of file diff --git a/targets/TARGET_ONSEMI/TARGET_NCS36510/ncs36510_i2c.c b/targets/TARGET_ONSEMI/TARGET_NCS36510/ncs36510_i2c.c index 784ea31bc1..f4cae19428 100644 --- a/targets/TARGET_ONSEMI/TARGET_NCS36510/ncs36510_i2c.c +++ b/targets/TARGET_ONSEMI/TARGET_NCS36510/ncs36510_i2c.c @@ -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 */ \ No newline at end of file From e46ff4d907a855196040a546492a99cdc131741b Mon Sep 17 00:00:00 2001 From: TomoYamanaka Date: Mon, 20 Feb 2017 16:41:59 +0900 Subject: [PATCH 15/16] Bug fix of initial value of interrupt edge in "gpio_irq_init" again I modified the bug in PR #3289. But It seems not enough the changes. For the reason, It occured the following issue. https://github.com/ARMmbed/mbed-os/issues/3694 So I reviewed and re-modified about the setting of initial value of interrupt edge in "gpio_irq_init". --- targets/TARGET_RENESAS/TARGET_RZ_A1H/gpio_irq_api.c | 1 - 1 file changed, 1 deletion(-) diff --git a/targets/TARGET_RENESAS/TARGET_RZ_A1H/gpio_irq_api.c b/targets/TARGET_RENESAS/TARGET_RZ_A1H/gpio_irq_api.c index 71a9fe1cdb..a4d780bff2 100644 --- a/targets/TARGET_RENESAS/TARGET_RZ_A1H/gpio_irq_api.c +++ b/targets/TARGET_RENESAS/TARGET_RZ_A1H/gpio_irq_api.c @@ -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(); From e0b27cc28e4ed3e8aa068fcbb880a2965216c868 Mon Sep 17 00:00:00 2001 From: Anna Bridge Date: Fri, 24 Feb 2017 13:25:03 +0000 Subject: [PATCH 16/16] Update MBED_LIBRARY_VERSION to v137 --- mbed.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mbed.h b/mbed.h index 73c77539b5..76aa8d309b 100644 --- a/mbed.h +++ b/mbed.h @@ -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