mbed library sources. Supersedes mbed-src.
Dependents: Nucleo_Hello_Encoder BLE_iBeaconScan AM1805_DEMO DISCO-F429ZI_ExportTemplate1 ... more
targets/TARGET_Cypress/TARGET_PSOC6/lp_ticker.c
- Committer:
- AnnaBridge
- Date:
- 2019-02-20
- Revision:
- 189:f392fc9709a3
- Parent:
- 188:bcfe06ba3d64
File content as of revision 189:f392fc9709a3:
/* * mbed Microcontroller Library * Copyright (c) 2017-2018 Future Electronics * Copyright (c) 2018-2019 Cypress Semiconductor Corporation * SPDX-License-Identifier: Apache-2.0 * * 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 "cy_mcwdt.h" #include "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. #if !defined (CY_CFG_SYSCLK_CLKLF_FREQ_HZ) #define CY_CFG_SYSCLK_CLKLF_FREQ_HZ 32768UL /* Default to 32K ILO */ #endif /* CY_CFG_SYSCLK_CLKLF_FREQ_HZ */ static const ticker_info_t lp_ticker_info = { .frequency = CY_CFG_SYSCLK_CLKLF_FREQ_HZ, .bits = 16UL, }; 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