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/lp_ticker.c	Thu Nov 08 11:46:34 2018 +0000
@@ -0,0 +1,162 @@
+/*
+ * 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 "device.h"
+#include "mbed_error.h"
+#include "lp_ticker_api.h"
+#include "device/drivers/peripheral/mcwdt/cy_mcwdt.h"
+#include "device/drivers/peripheral/sysint/cy_sysint.h"
+#include "psoc6_utils.h"
+
+#if DEVICE_LPTICKER
+
+/*
+ * Low Power Timer API on PSoC6 uses MCWD0 timer0 to implement functionality.
+ */
+
+#if defined(TARGET_MCU_PSOC6_M0)
+#define LPT_MCWDT_UNIT          MCWDT_STRUCT0
+#define LPT_INTERRUPT_PRIORITY  3
+#define LPT_INTERRUPT_SOURCE    srss_interrupt_mcwdt_0_IRQn
+#else
+#define LPT_MCWDT_UNIT          MCWDT_STRUCT1
+#define LPT_INTERRUPT_PRIORITY  6
+#define LPT_INTERRUPT_SOURCE    srss_interrupt_mcwdt_1_IRQn
+#endif
+#define LPT_MCWDT_DELAY_WAIT    0                // Recommended value is 93, but then we fail function execution time test.
+
+static const ticker_info_t lp_ticker_info = {
+    .frequency = CY_CLK_WCO_FREQ_HZ,
+    .bits = 16,
+};
+
+static bool lpt_init_done = false;
+// Timer h/w configuration.
+static cy_stc_mcwdt_config_t config = {
+    .c0Match = 0,
+    .c1Match = 0,
+    .c0Mode = CY_MCWDT_MODE_INT,
+    .c1Mode = CY_MCWDT_MODE_NONE,
+    .c2ToggleBit = 0,
+    .c2Mode = CY_MCWDT_MODE_NONE,
+    .c0ClearOnMatch = false,
+    .c1ClearOnMatch = false,
+    .c0c1Cascade = false,
+    .c1c2Cascade = false
+};
+
+// Interrupt configuration.
+static cy_stc_sysint_t lpt_sysint_config = {
+#if defined(TARGET_MCU_PSOC6_M0)
+    .intrSrc = (IRQn_Type)(-1),
+    .cm0pSrc = LPT_INTERRUPT_SOURCE,
+#else
+    .intrSrc = LPT_INTERRUPT_SOURCE,
+#endif
+    .intrPriority = LPT_INTERRUPT_PRIORITY
+};
+
+
+void lp_ticker_init(void)
+{
+    lp_ticker_disable_interrupt();
+    lp_ticker_clear_interrupt();
+
+    if (lpt_init_done) {
+        return;
+    }
+
+#ifdef TARGET_MCU_PSOC6_M0
+    // Allocate NVIC channel.
+    lpt_sysint_config.intrSrc = cy_m0_nvic_allocate_channel(CY_LP_TICKER_IRQN_ID);
+    if (lpt_sysint_config.intrSrc == (IRQn_Type)(-1)) {
+        // No free NVIC channel.
+        error("LP_TICKER NVIC channel allocation failed.");
+        return;
+    }
+#endif
+
+    Cy_MCWDT_Init(LPT_MCWDT_UNIT, &config);
+    Cy_SysInt_Init(&lpt_sysint_config, lp_ticker_irq_handler);
+    NVIC_EnableIRQ(lpt_sysint_config.intrSrc);
+    Cy_MCWDT_Enable(LPT_MCWDT_UNIT, CY_MCWDT_CTR0, LPT_MCWDT_DELAY_WAIT);
+    lpt_init_done = true;
+}
+
+void lp_ticker_free(void)
+{
+    NVIC_DisableIRQ(lpt_sysint_config.intrSrc);
+    Cy_MCWDT_Disable(LPT_MCWDT_UNIT, CY_MCWDT_CTR0, LPT_MCWDT_DELAY_WAIT);
+#ifdef TARGET_MCU_PSOC6_M0
+    cy_m0_nvic_release_channel(CY_LP_TICKER_IRQN_ID, lpt_sysint_config.intrSrc);
+    lpt_sysint_config.intrSrc = (IRQn_Type)(-1);
+#endif
+    lpt_init_done = 0;
+}
+
+uint32_t lp_ticker_read(void)
+{
+    return Cy_MCWDT_GetCount(LPT_MCWDT_UNIT, CY_MCWDT_COUNTER0);
+}
+
+void lp_ticker_set_interrupt(timestamp_t timestamp)
+{
+    uint16_t delay;
+    uint16_t current = Cy_MCWDT_GetCount(LPT_MCWDT_UNIT, CY_MCWDT_COUNTER0);
+    uint16_t new_ts = (uint16_t)timestamp;
+    delay = new_ts - current;
+    // Make sure the event is set for the future. Mbed internally will not schedule
+    // delays longer than 0x7000, so too large delay means it should occur already.
+    // MCWDT has internal delay of about 1.5 LF clock ticks, so this is the minimum
+    // that we can schedule.
+    if ((delay < 3) || (delay > (uint16_t)(-3))) {
+        // Cheating a bit here.
+        new_ts = current + 3;
+    }
+
+    // Cypress PDL manual says that valid match range is 1..65535.
+    if (new_ts == 0) {
+        new_ts = 1;
+    }
+
+    // Set up and enable match interrupt.
+    Cy_MCWDT_SetMatch(LPT_MCWDT_UNIT, CY_MCWDT_COUNTER0, new_ts, LPT_MCWDT_DELAY_WAIT);
+    Cy_MCWDT_SetInterruptMask(LPT_MCWDT_UNIT, CY_MCWDT_CTR0);
+}
+
+void lp_ticker_disable_interrupt(void)
+{
+    Cy_MCWDT_SetInterruptMask(LPT_MCWDT_UNIT, 0);
+}
+
+void lp_ticker_clear_interrupt(void)
+{
+    Cy_MCWDT_ClearInterrupt(LPT_MCWDT_UNIT, CY_MCWDT_CTR0);
+}
+
+void lp_ticker_fire_interrupt(void)
+{
+    NVIC_SetPendingIRQ(lpt_sysint_config.intrSrc);
+}
+
+const ticker_info_t* lp_ticker_get_info(void)
+{
+    return &lp_ticker_info;
+}
+
+#endif // DEVICE_LPTICKER