mbed library sources. Supersedes mbed-src.

Dependents:   Nucleo_Hello_Encoder BLE_iBeaconScan AM1805_DEMO DISCO-F429ZI_ExportTemplate1 ... more

Revision:
188:bcfe06ba3d64
Child:
189:f392fc9709a3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/targets/TARGET_Cypress/TARGET_PSOC6/us_ticker.c	Thu Nov 08 11:46:34 2018 +0000
@@ -0,0 +1,215 @@
+/*
+ * mbed Microcontroller Library
+ * Copyright (c) 2017-2018 Future Electronics
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stddef.h>
+#include <limits.h>
+#include "device.h"
+#include "PeripheralNames.h"
+#include "us_ticker_api.h"
+#include "mbed_error.h"
+#include "psoc6_utils.h"
+
+#include "drivers/peripheral/sysint/cy_sysint.h"
+#include "drivers/peripheral/sysclk/cy_sysclk.h"
+#include "drivers/peripheral/tcpwm/cy_tcpwm_counter.h"
+#include "drivers/peripheral/syspm/cy_syspm.h"
+
+/** Each CPU core in PSoC6 needs its own usec timer.
+ ** Although each of TCPWM timers have two compare registers,
+ ** it has only one interrupt line, so we need to allocate
+ ** two TCPWM counters for the purpose of us_ticker
+ **/
+
+
+#if defined(TARGET_MCU_PSOC6_M0)
+
+#define TICKER_COUNTER_UNIT                 TCPWM0
+#define TICKER_COUNTER_NUM                  0
+#define TICKER_COUNTER_INTERRUPT_SOURCE     tcpwm_0_interrupts_0_IRQn
+#define TICKER_COUNTER_NVIC_IRQN            CY_M0_CORE_IRQ_CHANNEL_US_TICKER
+#define TICKER_COUNTER_INTERRUPT_PRIORITY   3
+#define TICKER_CLOCK_DIVIDER_NUM            0
+
+#elif defined(TARGET_MCU_PSOC6_M4)
+
+#define TICKER_COUNTER_UNIT                 TCPWM0
+#define TICKER_COUNTER_NUM                  1
+#define TICKER_COUNTER_INTERRUPT_SOURCE     tcpwm_0_interrupts_1_IRQn
+#define TICKER_COUNTER_NVIC_IRQN            TICKER_COUNTER_INTERRUPT_SOURCE
+#define TICKER_COUNTER_INTERRUPT_PRIORITY   6
+#define TICKER_CLOCK_DIVIDER_NUM            1
+
+#else
+#error "Unknown MCU type."
+#endif
+
+
+static const ticker_info_t us_ticker_info = {
+    .frequency = 1000000UL,
+    .bits = 32,
+};
+
+static const cy_stc_sysint_t us_ticker_sysint_cfg = {
+    .intrSrc = TICKER_COUNTER_NVIC_IRQN,
+#if defined(TARGET_MCU_PSOC6_M0)
+    .cm0pSrc = TICKER_COUNTER_INTERRUPT_SOURCE,
+#endif
+    .intrPriority = TICKER_COUNTER_INTERRUPT_PRIORITY
+};
+
+static int      us_ticker_inited = 0;
+
+static const cy_stc_tcpwm_counter_config_t cy_counter_config = {
+    .period = 0xFFFFFFFFUL,
+    .clockPrescaler = CY_TCPWM_COUNTER_PRESCALER_DIVBY_1,
+    .runMode = CY_TCPWM_COUNTER_CONTINUOUS,
+    .countDirection = CY_TCPWM_COUNTER_COUNT_UP,
+    .compareOrCapture = CY_TCPWM_COUNTER_MODE_COMPARE,
+    .enableCompareSwap = false,
+    .interruptSources = CY_TCPWM_INT_ON_CC,
+    .countInputMode = CY_TCPWM_INPUT_LEVEL,
+    .countInput = CY_TCPWM_INPUT_1
+};
+
+// PM callback to be executed when exiting deep sleep.
+static cy_en_syspm_status_t ticker_pm_callback(cy_stc_syspm_callback_params_t *callbackParams);
+
+static cy_stc_syspm_callback_params_t ticker_pm_callback_params = {
+    .base = TICKER_COUNTER_UNIT
+};
+
+static cy_stc_syspm_callback_t ticker_pm_callback_handler = {
+    .callback = ticker_pm_callback,
+    .type = CY_SYSPM_DEEPSLEEP,
+    .skipMode = CY_SYSPM_SKIP_CHECK_READY | CY_SYSPM_SKIP_CHECK_FAIL | CY_SYSPM_SKIP_BEFORE_TRANSITION,
+    .callbackParams = &ticker_pm_callback_params
+};
+
+
+/*
+ * Callback handler to restart the timer after deep sleep.
+ */
+static cy_en_syspm_status_t ticker_pm_callback(cy_stc_syspm_callback_params_t *params)
+{
+    if (params->mode == CY_SYSPM_AFTER_TRANSITION) {
+        Cy_TCPWM_Counter_Enable(TICKER_COUNTER_UNIT, TICKER_COUNTER_NUM);
+        Cy_TCPWM_TriggerStart(TICKER_COUNTER_UNIT, 1UL << TICKER_COUNTER_NUM);
+    }
+    return CY_SYSPM_SUCCESS;
+}
+
+/*
+ * Interrupt handler.
+ */
+static void local_irq_handler(void)
+{
+    us_ticker_clear_interrupt();
+    us_ticker_disable_interrupt();
+    us_ticker_irq_handler();
+}
+
+
+void us_ticker_init(void)
+{
+    us_ticker_disable_interrupt();
+    us_ticker_clear_interrupt();
+
+    if (us_ticker_inited)
+        return;
+
+    us_ticker_inited = 1;
+
+    // Configure the clock, us_ticker 1 MHz from PCLK 50 MHz
+    Cy_SysClk_PeriphAssignDivider(PCLK_TCPWM0_CLOCKS0 + TICKER_COUNTER_NUM, CY_SYSCLK_DIV_8_BIT, TICKER_CLOCK_DIVIDER_NUM);
+    Cy_SysClk_PeriphSetDivider(CY_SYSCLK_DIV_8_BIT, TICKER_CLOCK_DIVIDER_NUM, (CY_CLK_PERICLK_FREQ_HZ / 1000000UL) - 1);
+    Cy_SysClk_PeriphEnableDivider(CY_SYSCLK_DIV_8_BIT, TICKER_CLOCK_DIVIDER_NUM);
+
+    /*
+        Configure the counter
+    */
+
+    Cy_TCPWM_Counter_Init(TICKER_COUNTER_UNIT, TICKER_COUNTER_NUM, &cy_counter_config);
+    Cy_TCPWM_Counter_Enable(TICKER_COUNTER_UNIT, TICKER_COUNTER_NUM);
+    if (!Cy_SysPm_RegisterCallback(&ticker_pm_callback_handler)) {
+        error("PM callback registration failed!");
+    }
+    Cy_TCPWM_TriggerStart(TICKER_COUNTER_UNIT, 1UL << TICKER_COUNTER_NUM);
+
+#if defined (TARGET_MCU_PSOC6_M0)
+    if (cy_m0_nvic_reserve_channel(TICKER_COUNTER_NVIC_IRQN, CY_US_TICKER_IRQN_ID) == (IRQn_Type)(-1)) {
+        error("Microsecond ticker NVIC channel reservation conflict.");
+    }
+#endif //
+
+    Cy_SysInt_Init(&us_ticker_sysint_cfg, local_irq_handler);
+}
+
+void us_ticker_free(void)
+{
+    us_ticker_disable_interrupt();
+    Cy_TCPWM_Counter_Disable(TICKER_COUNTER_UNIT, TICKER_COUNTER_NUM);
+    Cy_SysPm_UnregisterCallback(&ticker_pm_callback_handler);
+#if defined (TARGET_MCU_PSOC6_M0)
+    cy_m0_nvic_release_channel(TICKER_COUNTER_NVIC_IRQN, CY_US_TICKER_IRQN_ID);
+#endif //
+    us_ticker_inited = 0;
+}
+
+uint32_t us_ticker_read(void)
+{
+    if (!us_ticker_inited)
+        us_ticker_init();
+    return Cy_TCPWM_Counter_GetCounter(TICKER_COUNTER_UNIT, TICKER_COUNTER_NUM);
+}
+
+void us_ticker_set_interrupt(timestamp_t timestamp)
+{
+    uint32_t current_ts = Cy_TCPWM_Counter_GetCounter(TICKER_COUNTER_UNIT, TICKER_COUNTER_NUM);
+    uint32_t delta = timestamp - current_ts;
+
+    if (!us_ticker_inited)
+        us_ticker_init();
+
+    // Set new output compare value
+    if ((delta < 2) || (delta  > (uint32_t)(-3))) {
+        timestamp = current_ts + 2;
+    }
+    Cy_TCPWM_Counter_SetCompare0(TICKER_COUNTER_UNIT, TICKER_COUNTER_NUM, timestamp);
+    // Enable int
+    NVIC_EnableIRQ(TICKER_COUNTER_NVIC_IRQN);
+}
+
+void us_ticker_disable_interrupt(void)
+{
+    NVIC_DisableIRQ(TICKER_COUNTER_NVIC_IRQN);
+}
+
+void us_ticker_clear_interrupt(void)
+{
+    Cy_TCPWM_ClearInterrupt(TICKER_COUNTER_UNIT, TICKER_COUNTER_NUM, CY_TCPWM_INT_ON_CC);
+}
+
+void us_ticker_fire_interrupt(void)
+{
+    NVIC_EnableIRQ(TICKER_COUNTER_NVIC_IRQN);
+    NVIC_SetPendingIRQ(TICKER_COUNTER_NVIC_IRQN);
+}
+
+const ticker_info_t* us_ticker_get_info(void)
+{
+    return &us_ticker_info;
+}