From ba863f4e3da5d82c182528983749f3c171fe80f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C5=82=C4=85bek=2C=20Andrzej?= Date: Fri, 24 Jun 2016 09:02:29 +0200 Subject: [PATCH 1/2] Enabled I2C_ASYNCH. --- hal/targets.json | 4 ++-- hal/targets/hal/TARGET_NORDIC/TARGET_NRF5/i2c_api.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/hal/targets.json b/hal/targets.json index dafc4788fc..5d6e036bdf 100644 --- a/hal/targets.json +++ b/hal/targets.json @@ -1375,7 +1375,7 @@ "supported_form_factors": ["ARDUINO"], "inherits": ["MCU_NRF51_32K"], "progen": {"target": "nrf51-dk"}, - "device_has": ["ERROR_PATTERN", "I2C", "INTERRUPTIN", "PORTIN", "PORTINOUT", "PORTOUT", "RTC", "SERIAL", "SERIAL_ASYNCH", "SLEEP", "SPI", "SPI_ASYNCH"] + "device_has": ["ERROR_PATTERN", "I2C", "I2C_ASYNCH", "INTERRUPTIN", "PORTIN", "PORTINOUT", "PORTOUT", "RTC", "SERIAL", "SERIAL_ASYNCH", "SLEEP", "SPI", "SPI_ASYNCH"] }, "NRF51_DK_BOOT": { "supported_form_factors": ["ARDUINO"], @@ -1773,6 +1773,6 @@ "NRF52_PAN_62", "NRF52_PAN_63" ], - "device_has": ["ERROR_PATTERN", "I2C", "INTERRUPTIN", "PORTIN", "PORTINOUT", "PORTOUT", "RTC", "SERIAL", "SERIAL_ASYNCH", "SLEEP", "SPI", "SPI_ASYNCH"] + "device_has": ["ERROR_PATTERN", "I2C", "I2C_ASYNCH", "INTERRUPTIN", "PORTIN", "PORTINOUT", "PORTOUT", "RTC", "SERIAL", "SERIAL_ASYNCH", "SLEEP", "SPI", "SPI_ASYNCH"] } } diff --git a/hal/targets/hal/TARGET_NORDIC/TARGET_NRF5/i2c_api.c b/hal/targets/hal/TARGET_NORDIC/TARGET_NRF5/i2c_api.c index 7d611490b0..ce2e475f74 100644 --- a/hal/targets/hal/TARGET_NORDIC/TARGET_NRF5/i2c_api.c +++ b/hal/targets/hal/TARGET_NORDIC/TARGET_NRF5/i2c_api.c @@ -122,7 +122,7 @@ void i2c_init(i2c_t *obj, PinName sda, PinName scl) } // No available peripheral - error("No available I2C"); + error("No available I2C peripheral\r\n"); } void i2c_reset(i2c_t *obj) @@ -215,7 +215,7 @@ int i2c_byte_write(i2c_t *obj, int data) #if DEVICE_I2C_ASYNCH -void i2c_transfer_asynch(i2c_t *obj, void *tx, size_t tx_length, +void i2c_transfer_asynch(i2c_t *obj, const void *tx, size_t tx_length, void *rx, size_t rx_length, uint32_t address, uint32_t stop, uint32_t handler, uint32_t event, DMAUsage hint) From 1357fb0ffcda17ceb1202b9563d3cabf7213f20f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C5=82=C4=85bek=2C=20Andrzej?= Date: Thu, 23 Jun 2016 12:27:18 +0200 Subject: [PATCH 2/2] Polished ticker related code. --- .../TARGET_NORDIC/TARGET_NRF5/common_rtc.h | 17 +++++- .../hal/TARGET_NORDIC/TARGET_NRF5/lp_ticker.c | 3 +- .../hal/TARGET_NORDIC/TARGET_NRF5/os_tick.c | 43 +++++++------- .../hal/TARGET_NORDIC/TARGET_NRF5/us_ticker.c | 58 +++++++++++++------ 4 files changed, 78 insertions(+), 43 deletions(-) diff --git a/hal/targets/hal/TARGET_NORDIC/TARGET_NRF5/common_rtc.h b/hal/targets/hal/TARGET_NORDIC/TARGET_NRF5/common_rtc.h index 789427c692..390faf53d3 100644 --- a/hal/targets/hal/TARGET_NORDIC/TARGET_NRF5/common_rtc.h +++ b/hal/targets/hal/TARGET_NORDIC/TARGET_NRF5/common_rtc.h @@ -24,12 +24,27 @@ // Instance 0 is reserved for SoftDevice. // Instance 1 is used as a common one for us_ticker, lp_ticker and (in case // of NRF51) as an alternative tick source for RTOS. +// ["os_tick.c" uses hard coded addresses of the 'NRF_RTC1->EVENT_COMPARE[1]' +// register in inline assembly implementations of COMMON_RTC_IRQ_HANDLER, +// please remember to update those in case of doing changes here] #define COMMON_RTC_INSTANCE NRF_RTC1 - +#define COMMON_RTC_IRQ_HANDLER RTC1_IRQHandler #define US_TICKER_CC_CHANNEL 0 #define OS_TICK_CC_CHANNEL 1 #define LP_TICKER_CC_CHANNEL 2 +#define COMMON_RTC_EVENT_COMPARE(channel) \ + CONCAT_2(NRF_RTC_EVENT_COMPARE_, channel) +#define COMMON_RTC_INT_COMPARE_MASK(channel) \ + CONCAT_3(NRF_RTC_INT_COMPARE, channel, _MASK) + +#define US_TICKER_EVENT COMMON_RTC_EVENT_COMPARE(US_TICKER_CC_CHANNEL) +#define US_TICKER_INT_MASK COMMON_RTC_INT_COMPARE_MASK(US_TICKER_CC_CHANNEL) +#define OS_TICK_EVENT COMMON_RTC_EVENT_COMPARE(OS_TICK_CC_CHANNEL) +#define OS_TICK_INT_MASK COMMON_RTC_INT_COMPARE_MASK(OS_TICK_CC_CHANNEL) +#define LP_TICKER_EVENT COMMON_RTC_EVENT_COMPARE(LP_TICKER_CC_CHANNEL) +#define LP_TICKER_INT_MASK COMMON_RTC_INT_COMPARE_MASK(LP_TICKER_CC_CHANNEL) + extern bool m_common_rtc_enabled; extern uint32_t volatile m_common_rtc_overflows; diff --git a/hal/targets/hal/TARGET_NORDIC/TARGET_NRF5/lp_ticker.c b/hal/targets/hal/TARGET_NORDIC/TARGET_NRF5/lp_ticker.c index 4a928b79f4..404c18c259 100644 --- a/hal/targets/hal/TARGET_NORDIC/TARGET_NRF5/lp_ticker.c +++ b/hal/targets/hal/TARGET_NORDIC/TARGET_NRF5/lp_ticker.c @@ -34,8 +34,7 @@ void lp_ticker_set_interrupt(uint32_t now, uint32_t time) { (void)now; nrf_rtc_cc_set(COMMON_RTC_INSTANCE, LP_TICKER_CC_CHANNEL, RTC_WRAP(time)); - nrf_rtc_event_clear(COMMON_RTC_INSTANCE, NRF_RTC_EVENT_COMPARE_2); - nrf_rtc_event_enable(COMMON_RTC_INSTANCE, NRF_RTC_INT_COMPARE2_MASK); + nrf_rtc_event_enable(COMMON_RTC_INSTANCE, LP_TICKER_INT_MASK); } uint32_t lp_ticker_get_overflows_counter(void) diff --git a/hal/targets/hal/TARGET_NORDIC/TARGET_NRF5/os_tick.c b/hal/targets/hal/TARGET_NORDIC/TARGET_NRF5/os_tick.c index 3b4a51f25c..5655d302e3 100644 --- a/hal/targets/hal/TARGET_NORDIC/TARGET_NRF5/os_tick.c +++ b/hal/targets/hal/TARGET_NORDIC/TARGET_NRF5/os_tick.c @@ -17,7 +17,7 @@ #include "common_rtc.h" #include "toolchain.h" -#include "nrf_delay.h" +#include "nrf_drv_common.h" #define MAX_RTC_COUNTER_VAL ((1uL << RTC_COUNTER_BITS) - 1) @@ -44,7 +44,7 @@ MBED_WEAK void OS_Tick_Handler() { } #if defined (__CC_ARM) /* ARMCC Compiler */ -__asm void RTC1_IRQHandler(void) +__asm void COMMON_RTC_IRQ_HANDLER(void) { IMPORT OS_Tick_Handler IMPORT common_rtc_irq_handler @@ -59,7 +59,7 @@ __asm void RTC1_IRQHandler(void) * would never been dequeued. * * \code - * void RTC1_IRQHandler(void) { + * void COMMON_RTC_IRQ_HANDLER(void) { if(NRF_RTC1->EVENTS_COMPARE[1]) { // never return... OS_Tick_Handler(); @@ -83,7 +83,7 @@ US_TICKER_HANDLER #elif defined (__GNUC__) /* GNU Compiler */ -__attribute__((naked)) void RTC1_IRQHandler(void) +__attribute__((naked)) void COMMON_RTC_IRQ_HANDLER(void) { /** * Chanel 1 of RTC1 is used by RTX as a systick. @@ -95,7 +95,7 @@ __attribute__((naked)) void RTC1_IRQHandler(void) * would never been dequeued. * * \code - * void RTC1_IRQHandler(void) { + * void COMMON_RTC_IRQ_HANDLER(void) { if(NRF_RTC1->EVENTS_COMPARE[1]) { // never return... OS_Tick_Handler(); @@ -122,7 +122,7 @@ __attribute__((naked)) void RTC1_IRQHandler(void) #else #error Compiler not supported. -#error Provide a definition of RTC1_IRQHandler. +#error Provide a definition of COMMON_RTC_IRQ_HANDLER. /* * Chanel 1 of RTC1 is used by RTX as a systick. @@ -134,7 +134,7 @@ __attribute__((naked)) void RTC1_IRQHandler(void) * will never been dequeued. After a certain time a stack overflow will happen. * * \code - * void RTC1_IRQHandler(void) { + * void COMMON_RTC_IRQ_HANDLER(void) { if(NRF_RTC1->EVENTS_COMPARE[1]) { // never return... OS_Tick_Handler(); @@ -188,8 +188,8 @@ static uint32_t get_next_tick_cc_delta() { } static inline void clear_tick_interrupt() { - NRF_RTC1->EVENTS_COMPARE[1] = 0; - NRF_RTC1->EVTENCLR = (1 << 17); + nrf_rtc_event_clear(COMMON_RTC_INSTANCE, OS_TICK_EVENT); + nrf_rtc_event_disable(COMMON_RTC_INSTANCE, OS_TICK_INT_MASK); } /** @@ -224,7 +224,7 @@ static inline bool is_in_wrapped_range(uint32_t begin, uint32_t end, uint32_t va * Register the next tick. */ static void register_next_tick() { - previous_tick_cc_value = NRF_RTC1->CC[1]; + previous_tick_cc_value = nrf_rtc_cc_get(COMMON_RTC_INSTANCE, OS_TICK_CC_CHANNEL); uint32_t delta = get_next_tick_cc_delta(); uint32_t new_compare_value = (previous_tick_cc_value + delta) & MAX_RTC_COUNTER_VAL; @@ -236,16 +236,16 @@ static void register_next_tick() { // This code is very short 20-38 cycles in the worst case, it shouldn't // disturb softdevice. __disable_irq(); - uint32_t current_counter = NRF_RTC1->COUNTER; + uint32_t current_counter = nrf_rtc_counter_get(COMMON_RTC_INSTANCE); // If an overflow occur, set the next tick in COUNTER + delta clock cycles if (is_in_wrapped_range(previous_tick_cc_value, new_compare_value, current_counter) == false) { new_compare_value = current_counter + delta; } - NRF_RTC1->CC[1] = new_compare_value; - - // set the interrupt of CC channel 1 and reenable IRQs - NRF_RTC1->INTENSET = RTC_INTENSET_COMPARE1_Msk; + nrf_rtc_cc_set(COMMON_RTC_INSTANCE, OS_TICK_CC_CHANNEL, new_compare_value); + // Enable generation of the compare event for the value set above (this + // event will trigger the interrupt). + nrf_rtc_event_enable(COMMON_RTC_INSTANCE, OS_TICK_INT_MASK); __enable_irq(); } @@ -259,11 +259,10 @@ int os_tick_init (void) { common_rtc_init(); - NRF_RTC1->CC[1] = 0; - clear_tick_interrupt(); + nrf_rtc_cc_set(COMMON_RTC_INSTANCE, OS_TICK_CC_CHANNEL, 0); register_next_tick(); - return RTC1_IRQn; + return nrf_drv_get_IRQn(COMMON_RTC_INSTANCE); } /** @@ -283,8 +282,8 @@ void os_tick_irqack(void) * @return 1 if the timer has overflowed and 0 otherwise. */ uint32_t os_tick_ovf(void) { - uint32_t current_counter = NRF_RTC1->COUNTER; - uint32_t next_tick_cc_value = NRF_RTC1->CC[1]; + uint32_t current_counter = nrf_rtc_counter_get(COMMON_RTC_INSTANCE); + uint32_t next_tick_cc_value = nrf_rtc_cc_get(COMMON_RTC_INSTANCE, OS_TICK_CC_CHANNEL); return is_in_wrapped_range(previous_tick_cc_value, next_tick_cc_value, current_counter) ? 0 : 1; } @@ -299,8 +298,8 @@ uint32_t os_tick_ovf(void) { * @return the value of the alternative hardware timer. */ uint32_t os_tick_val(void) { - uint32_t current_counter = NRF_RTC1->COUNTER; - uint32_t next_tick_cc_value = NRF_RTC1->CC[1]; + uint32_t current_counter = nrf_rtc_counter_get(COMMON_RTC_INSTANCE); + uint32_t next_tick_cc_value = nrf_rtc_cc_get(COMMON_RTC_INSTANCE, OS_TICK_CC_CHANNEL); // do not use os_tick_ovf because its counter value can be different if(is_in_wrapped_range(previous_tick_cc_value, next_tick_cc_value, current_counter)) { diff --git a/hal/targets/hal/TARGET_NORDIC/TARGET_NRF5/us_ticker.c b/hal/targets/hal/TARGET_NORDIC/TARGET_NRF5/us_ticker.c index 5b9050bb71..463feeaf9e 100644 --- a/hal/targets/hal/TARGET_NORDIC/TARGET_NRF5/us_ticker.c +++ b/hal/targets/hal/TARGET_NORDIC/TARGET_NRF5/us_ticker.c @@ -30,35 +30,35 @@ uint32_t volatile m_common_rtc_overflows = 0; #if defined(TARGET_MCU_NRF51822) void common_rtc_irq_handler(void) #else -void RTC1_IRQHandler(void) +void COMMON_RTC_IRQ_HANDLER(void) #endif { nrf_rtc_event_t event; uint32_t int_mask; - event = NRF_RTC_EVENT_COMPARE_0; - int_mask = NRF_RTC_INT_COMPARE0_MASK; - if (nrf_rtc_event_pending(COMMON_RTC_INSTANCE, event)) - { + event = US_TICKER_EVENT; + int_mask = US_TICKER_INT_MASK; + if (nrf_rtc_event_pending(COMMON_RTC_INSTANCE, event)) { nrf_rtc_event_clear(COMMON_RTC_INSTANCE, event); nrf_rtc_event_disable(COMMON_RTC_INSTANCE, int_mask); + us_ticker_irq_handler(); } #if DEVICE_LOWPOWERTIMER - event = NRF_RTC_EVENT_COMPARE_2; - int_mask = NRF_RTC_INT_COMPARE2_MASK; - if (nrf_rtc_event_pending(COMMON_RTC_INSTANCE, event)) - { + event = LP_TICKER_EVENT; + int_mask = LP_TICKER_INT_MASK; + if (nrf_rtc_event_pending(COMMON_RTC_INSTANCE, event)) { nrf_rtc_event_clear(COMMON_RTC_INSTANCE, event); nrf_rtc_event_disable(COMMON_RTC_INSTANCE, int_mask); } #endif event = NRF_RTC_EVENT_OVERFLOW; - if (nrf_rtc_event_pending(COMMON_RTC_INSTANCE, event)) - { + if (nrf_rtc_event_pending(COMMON_RTC_INSTANCE, event)) { nrf_rtc_event_clear(COMMON_RTC_INSTANCE, event); + // Don't disable this event. It shall occur periodically. + ++m_common_rtc_overflows; } } @@ -76,18 +76,41 @@ void common_rtc_init(void) nrf_rtc_prescaler_set(COMMON_RTC_INSTANCE, 0); + nrf_rtc_event_clear(COMMON_RTC_INSTANCE, US_TICKER_EVENT); +#if defined(TARGET_MCU_NRF51822) + nrf_rtc_event_clear(COMMON_RTC_INSTANCE, OS_TICK_EVENT); +#endif +#if DEVICE_LOWPOWERTIMER + nrf_rtc_event_clear(COMMON_RTC_INSTANCE, LP_TICKER_EVENT); +#endif nrf_rtc_event_clear(COMMON_RTC_INSTANCE, NRF_RTC_EVENT_OVERFLOW); - nrf_rtc_event_enable(COMMON_RTC_INSTANCE, NRF_RTC_INT_OVERFLOW_MASK); + + // Interrupts on all related events are enabled permanently. Particular + // events will be enabled or disabled as needed (such approach is more + // energy efficient). nrf_rtc_int_enable(COMMON_RTC_INSTANCE, - NRF_RTC_INT_COMPARE0_MASK | #if defined(TARGET_MCU_NRF51822) - NRF_RTC_INT_COMPARE1_MASK | + OS_TICK_INT_MASK | #endif #if DEVICE_LOWPOWERTIMER - NRF_RTC_INT_COMPARE2_MASK | + LP_TICKER_INT_MASK | #endif + US_TICKER_INT_MASK | NRF_RTC_INT_OVERFLOW_MASK); + // This event is enabled permanently, since overflow indications are needed + // continuously. + nrf_rtc_event_enable(COMMON_RTC_INSTANCE, NRF_RTC_INT_OVERFLOW_MASK); + // All other relevant events are initially disabled. + nrf_rtc_event_disable(COMMON_RTC_INSTANCE, + #if defined(TARGET_MCU_NRF51822) + OS_TICK_INT_MASK | + #endif + #if DEVICE_LOWPOWERTIMER + LP_TICKER_INT_MASK | + #endif + US_TICKER_INT_MASK); + nrf_drv_common_irq_enable(nrf_drv_get_IRQn(COMMON_RTC_INSTANCE), APP_IRQ_PRIORITY_LOW); @@ -161,13 +184,12 @@ void us_ticker_set_interrupt(timestamp_t timestamp) nrf_rtc_cc_set(COMMON_RTC_INSTANCE, US_TICKER_CC_CHANNEL, RTC_WRAP(compare_value)); - nrf_rtc_event_clear(COMMON_RTC_INSTANCE, NRF_RTC_EVENT_COMPARE_0); - nrf_rtc_event_enable(COMMON_RTC_INSTANCE, NRF_RTC_INT_COMPARE0_MASK); + nrf_rtc_event_enable(COMMON_RTC_INSTANCE, US_TICKER_INT_MASK); } void us_ticker_disable_interrupt(void) { - nrf_rtc_event_disable(COMMON_RTC_INSTANCE, NRF_RTC_INT_COMPARE0_MASK); + nrf_rtc_event_disable(COMMON_RTC_INSTANCE, US_TICKER_INT_MASK); } void us_ticker_clear_interrupt(void)