/**************************************************************************//** * * @copyright (C) 2020 Nuvoton Technology Corp. All rights reserved. * * SPDX-License-Identifier: Apache-2.0 * * Change Logs: * Date Author Notes * 2020-8-20 Philo First version * ******************************************************************************/ #include #if defined(BSP_USING_EPWM_CAPTURE) #if ((BSP_USING_EPWM0_CAPTURE_CHMSK+BSP_USING_EPWM1_CAPTURE_CHMSK)!=0) #include #include "NuMicro.h" #define EPWM_CH0CH1_POS (0) #define EPWM_CH2CH3_POS (2) #define EPWM_CH4CH5_POS (4) /* Private typedef --------------------------------------------------------------*/ typedef struct nu_capture { struct rt_inputcapture_device parent; EPWM_T *epwm; uint8_t u8Channel; IRQn_Type irq; uint32_t u32CurrentRisingCnt; uint32_t u32CurrentFallingCnt; rt_bool_t input_data_level; } nu_capture_t; /* Private functions ------------------------------------------------------------*/ static rt_err_t nu_capture_init(struct rt_inputcapture_device *inputcapture); static rt_err_t nu_capture_open(struct rt_inputcapture_device *inputcapture); static rt_err_t nu_capture_close(struct rt_inputcapture_device *inputcapture); static rt_err_t nu_capture_get_pulsewidth(struct rt_inputcapture_device *inputcapture, rt_uint32_t *pulsewidth_us); /* Public functions -------------------------------------------------------------*/ /* Private variables ------------------------------------------------------------*/ #if (BSP_USING_EPWM0_CAPTURE_CHMSK!=0) static const char *nu_epwm0_device_name[EPWM_CHANNEL_NUM] = { "epwm0i0", "epwm0i1", "epwm0i2", "epwm0i3", "epwm0i4", "epwm0i5"}; static const IRQn_Type nu_epwm0_irq[EPWM_CHANNEL_NUM / 2] = { EPWM0_P0_IRQn, EPWM0_P1_IRQn, EPWM0_P2_IRQn}; static nu_capture_t nu_epwm0_capture[EPWM_CHANNEL_NUM] = {0}; #endif #if (BSP_USING_EPWM1_CAPTURE_CHMSK!=0) static const char *nu_epwm1_device_name[EPWM_CHANNEL_NUM] = {"epwm1i0", "epwm1i1", "epwm1i2", "epwm1i3", "epwm1i4", "epwm1i5", }; static const IRQn_Type nu_epwm1_irq[EPWM_CHANNEL_NUM / 2] = {EPWM1_P0_IRQn, EPWM1_P1_IRQn, EPWM1_P2_IRQn }; static nu_capture_t nu_epwm1_capture[EPWM_CHANNEL_NUM] = {0}; #endif static struct rt_inputcapture_ops nu_capture_ops = { .init = nu_capture_init, .open = nu_capture_open, .close = nu_capture_close, .get_pulsewidth = nu_capture_get_pulsewidth, }; /* Functions define ------------------------------------------------------------*/ static rt_err_t CalPulseWidth(nu_capture_t *nu_capture) { rt_bool_t bWrapAroundFlag = RT_FALSE; /* Check rising/falling capture counter is overflow or not */ if (EPWM_GetWrapAroundFlag(nu_capture->epwm, nu_capture->u8Channel)) { EPWM_ClearWrapAroundFlag(nu_capture->epwm, nu_capture->u8Channel); bWrapAroundFlag = RT_TRUE; } /* Read the capture counter value if falling/rising edge */ if (EPWM_GetCaptureIntFlag(nu_capture->epwm, nu_capture->u8Channel) == 1)//Rising edge { EPWM_ClearCaptureIntFlag(nu_capture->epwm, nu_capture->u8Channel, EPWM_CAPTURE_INT_RISING_LATCH); if (bWrapAroundFlag) { nu_capture->u32CurrentRisingCnt = 0x10000; } nu_capture->u32CurrentRisingCnt += EPWM_GET_CAPTURE_RISING_DATA(nu_capture->epwm, nu_capture->u8Channel); } else if (EPWM_GetCaptureIntFlag(nu_capture->epwm, nu_capture->u8Channel) == 2)//Falling edge { EPWM_ClearCaptureIntFlag(nu_capture->epwm, nu_capture->u8Channel, EPWM_CAPTURE_INT_FALLING_LATCH); if (bWrapAroundFlag) { nu_capture->u32CurrentFallingCnt = 0x10000; } nu_capture->u32CurrentFallingCnt += EPWM_GET_CAPTURE_FALLING_DATA(nu_capture->epwm, nu_capture->u8Channel); } else { EPWM_ClearCaptureIntFlag(nu_capture->epwm, nu_capture->u8Channel, EPWM_CAPTURE_INT_RISING_LATCH); EPWM_ClearCaptureIntFlag(nu_capture->epwm, nu_capture->u8Channel, EPWM_CAPTURE_INT_FALLING_LATCH); return -(RT_ERROR); } return RT_EOK; } #if (BSP_USING_EPWM0_CAPTURE_CHMSK&(0x3<u32CurrentFallingCnt) { *pulsewidth_us = nu_capture->u32CurrentFallingCnt; nu_capture->input_data_level = RT_FALSE; nu_capture->u32CurrentFallingCnt = 0; } else if (nu_capture->u32CurrentRisingCnt) { *pulsewidth_us = nu_capture->u32CurrentRisingCnt; nu_capture->input_data_level = RT_TRUE; nu_capture->u32CurrentRisingCnt = 0; } else { ret = RT_ERROR; } return -(ret); } static rt_err_t nu_epwm_init(nu_capture_t *nu_capture) { rt_err_t ret = RT_ERROR; static rt_bool_t bEPWM0Inited = RT_FALSE; static rt_bool_t bEPWM1Inited = RT_FALSE; if (nu_capture->epwm == EPWM0) { if (bEPWM0Inited == RT_FALSE) { /* Enable EPWM0 clock */ SYS_UnlockReg(); CLK_EnableModuleClock(EPWM0_MODULE); CLK_SetModuleClock(EPWM0_MODULE, CLK_CLKSEL2_EPWM0SEL_PCLK0, 0); SYS_LockReg(); bEPWM0Inited = RT_TRUE; } ret = RT_EOK; } else if (nu_capture->epwm == EPWM1) { if (bEPWM1Inited == RT_FALSE) { /* Enable EPWM1 clock */ SYS_UnlockReg(); CLK_EnableModuleClock(EPWM1_MODULE); CLK_SetModuleClock(EPWM1_MODULE, CLK_CLKSEL2_EPWM1SEL_PCLK1, 0); SYS_LockReg(); bEPWM1Inited = RT_TRUE; } ret = RT_EOK; } return -(ret); } static rt_err_t nu_capture_init(struct rt_inputcapture_device *inputcapture) { rt_err_t ret = RT_EOK; nu_capture_t *nu_capture; RT_ASSERT(inputcapture != RT_NULL); nu_capture = (nu_capture_t *) inputcapture; if (nu_epwm_init(nu_capture) != RT_EOK) { rt_kprintf("Failed to initialize EPWM%d.\n", nu_capture->epwm); ret = RT_ERROR; } return -(ret); } static rt_err_t nu_capture_open(struct rt_inputcapture_device *inputcapture) { rt_err_t ret = RT_EOK; nu_capture_t *nu_capture; RT_ASSERT(inputcapture != RT_NULL); nu_capture = (nu_capture_t *) inputcapture; /* Set capture time as 1000 nanosecond */ EPWM_ConfigCaptureChannel(nu_capture->epwm, nu_capture->u8Channel, 1000, 0); /* Enable capture rising/falling edge interrupt */ EPWM_EnableCaptureInt(nu_capture->epwm, nu_capture->u8Channel, EPWM_CAPTURE_INT_FALLING_LATCH | EPWM_CAPTURE_INT_RISING_LATCH); /* Enable EPWM NVIC interrupt */ NVIC_EnableIRQ(nu_capture->irq); /* Enable Capture Function for EPWM */ EPWM_EnableCapture(nu_capture->epwm, 0x1 << nu_capture->u8Channel); /* Enable rising/falling capture reload */ nu_capture->epwm->CAPCTL |= (0x1 << (EPWM_CAPCTL_RCRLDEN0_Pos + nu_capture->u8Channel)) | (0x1 << (EPWM_CAPCTL_FCRLDEN0_Pos + nu_capture->u8Channel)); /* Set counter type as down count */ EPWM_SET_ALIGNED_TYPE(nu_capture->epwm, 0x1 << nu_capture->u8Channel, EPWM_UP_COUNTER); /* Enable EPWM Timer */ EPWM_Start(nu_capture->epwm, 0x1 << nu_capture->u8Channel); return ret; } static rt_err_t nu_capture_close(struct rt_inputcapture_device *inputcapture) { rt_err_t ret = RT_EOK; nu_capture_t *nu_capture; RT_ASSERT(inputcapture != RT_NULL); nu_capture = (nu_capture_t *) inputcapture; /* Disable capture rising/falling edge interrupt */ EPWM_DisableCaptureInt(nu_capture->epwm, nu_capture->u8Channel, EPWM_CAPTURE_INT_FALLING_LATCH | EPWM_CAPTURE_INT_RISING_LATCH); /* Disable EPWM NVIC interrupt */ NVIC_DisableIRQ(nu_capture->irq); /* Enable EPWM Timer */ EPWM_Stop(nu_capture->epwm, 0x1 << nu_capture->u8Channel); return ret; } /* Init and register epwm capture */ int nu_epwm_capture_device_init(void) { /* Init EPWM0 6 channel and EPWM1 6 channel */ #if (BSP_USING_EPWM0_CAPTURE_CHMSK!=0) for (int i = 0; i < EPWM_CHANNEL_NUM; i++) { if (BSP_USING_EPWM0_CAPTURE_CHMSK & (0x1 << i)) { nu_epwm0_capture[i].epwm = EPWM0; nu_epwm0_capture[i].u8Channel = i; nu_epwm0_capture[i].irq = nu_epwm0_irq[i / 2]; nu_epwm0_capture[i].u32CurrentRisingCnt = 0; nu_epwm0_capture[i].u32CurrentFallingCnt = 0; nu_epwm0_capture[i].parent.ops = &nu_capture_ops; /* register inputcapture device */ rt_device_inputcapture_register(&nu_epwm0_capture[i].parent, nu_epwm0_device_name[i], &nu_epwm0_capture[i]); } } #endif //#if (BSP_USING_EPWM0_CAPTURE_CHMSK!=0) #if (BSP_USING_EPWM1_CAPTURE_CHMSK!=0) for (int i = 0; i < EPWM_CHANNEL_NUM; i++) { if (BSP_USING_EPWM1_CAPTURE_CHMSK & (0x1 << i)) { nu_epwm1_capture[i].epwm = EPWM1; nu_epwm1_capture[i].u8Channel = i; nu_epwm1_capture[i].irq = nu_epwm1_irq[i / 2]; nu_epwm1_capture[i].u32CurrentRisingCnt = 0; nu_epwm1_capture[i].u32CurrentFallingCnt = 0; nu_epwm1_capture[i].parent.ops = &nu_capture_ops; /* register inputcapture device */ rt_device_inputcapture_register(&nu_epwm1_capture[i].parent, nu_epwm1_device_name[i], &nu_epwm1_capture[i]); } } #endif //#if (BSP_USING_EPWM1_CAPTURE_CHMSK!=0) return 0; } INIT_DEVICE_EXPORT(nu_epwm_capture_device_init); #endif //#if ((BSP_USING_EPWM0_CAPTURE_CHMSK+BSP_USING_EPWM1_CAPTURE_CHMSK)!=0) #endif //#if defined(BSP_USING_EPWM_CAPTURE)