[BSP] Import RV32M1 SDK

This commit is contained in:
Bernard Xiong 2018-12-08 10:47:28 +08:00
parent c9576c3e53
commit 4b0f9e76eb
115 changed files with 122583 additions and 0 deletions

View File

@ -0,0 +1,123 @@
/*
* Copyright 2017 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
/* Copyright (c) 2009 - 2015 ARM LIMITED
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
- Neither the name of ARM nor the names of its contributors may be used
to endorse or promote products derived from this software without
specific prior written permission.
*
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
---------------------------------------------------------------------------*/
#ifndef __CORE_RISCV32_H__
#define __CORE_RISCV32_H__
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
#define RISCV32
#if defined ( __GNUC__ )
#define __ASM __asm /*!< asm keyword for GNU Compiler */
#define __INLINE inline /*!< inline keyword for GNU Compiler */
#define __STATIC_INLINE static inline
#else
#error Unknown compiler
#endif
#if defined ( __GNUC__ )
#define __BKPT(x) __ASM("ebreak")
__attribute__((always_inline)) __STATIC_INLINE void __NOP(void)
{
__ASM volatile ("nop");
}
__attribute__((always_inline)) __STATIC_INLINE void __DSB(void)
{
__ASM volatile ("nop");
}
__attribute__((always_inline)) __STATIC_INLINE void __ISB(void)
{
__ASM volatile ("nop");
}
__attribute__((always_inline)) __STATIC_INLINE void __WFI(void)
{
__ASM volatile ("wfi");
}
__attribute__((always_inline)) __STATIC_INLINE void __WFE(void)
{
}
__attribute__( ( always_inline ) ) __STATIC_INLINE void __enable_irq(void)
{
__ASM volatile ("csrsi mstatus, 8");
}
__attribute__( ( always_inline ) ) __STATIC_INLINE void __disable_irq(void)
{
__ASM volatile ("csrci mstatus, 8");
}
__attribute__((always_inline)) __STATIC_INLINE uint32_t __REV(uint32_t value)
{
return __builtin_bswap32(value);
}
__attribute__((always_inline)) __STATIC_INLINE uint32_t __REV16(uint32_t value)
{
return __builtin_bswap16(value);
}
#else
#error Unknown compiler
#endif
#ifdef __cplusplus
#define __I volatile /*!< Defines 'read only' permissions */
#else
#define __I volatile const /*!< Defines 'read only' permissions */
#endif
#define __O volatile /*!< Defines 'write only' permissions */
#define __IO volatile /*!< Defines 'read / write' permissions */
/* following defines should be used for structure members */
#define __IM volatile const /*! Defines 'read only' structure member permissions */
#define __OM volatile /*! Defines 'write only' structure member permissions */
#define __IOM volatile /*! Defines 'read / write' structure member permissions */
#ifdef __cplusplus
}
#endif
#endif /* __CORE_RISCV32_H__ */

View File

@ -0,0 +1,14 @@
# for module compiling
import os
from building import *
cwd = GetCurrentDir()
objs = []
list = os.listdir(cwd)
for d in list:
path = os.path.join(cwd, d)
if os.path.isfile(os.path.join(path, 'SConscript')):
objs = objs + SConscript(os.path.join(d, 'SConscript'))
Return('objs')

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,22 @@
# RT-Thread building script for component
from building import *
cwd = GetCurrentDir()
src = Split('''
system_RV32M1_ri5cy.c
drivers/fsl_clock.c
drivers/fsl_common.c
drivers/fsl_lpuart.c
drivers/fsl_gpio.c
drivers/fsl_msmc.c
drivers/fsl_usdhc.c
drivers/fsl_intmux.c
gcc/startup_RV32M1_ri5cy.S
''')
CPPPATH = [cwd, cwd + '/../../RISCV', cwd + '/drivers', cwd + '/utilities']
CPPDEFINES = ['CPU_RV32M1_ri5cy', 'SDK_DEBUGCONSOLE=0']
group = DefineGroup('Libraries', src, depend = [''], CPPPATH = CPPPATH, CPPDEFINES = CPPDEFINES)
Return('group')

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,794 @@
/*
* Copyright (c) 2015, Freescale Semiconductor, Inc.
* Copyright (c) 2016 - 2017 , NXP
* All rights reserved.
*
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include "fsl_clock.h"
/*******************************************************************************
* Definitions
******************************************************************************/
#define SCG_SIRC_LOW_RANGE_FREQ 2000000U /* Slow IRC low range clock frequency. */
#define SCG_SIRC_HIGH_RANGE_FREQ 8000000U /* Slow IRC high range clock frequency. */
#define SCG_FIRC_FREQ0 48000000U /* Fast IRC trimed clock frequency(48MHz). */
#define SCG_FIRC_FREQ1 52000000U /* Fast IRC trimed clock frequency(52MHz). */
#define SCG_FIRC_FREQ2 56000000U /* Fast IRC trimed clock frequency(56MHz). */
#define SCG_FIRC_FREQ3 60000000U /* Fast IRC trimed clock frequency(60MHz). */
#define SCG_LPFLL_FREQ0 48000000U /* LPFLL trimed clock frequency(48MHz). */
#define SCG_LPFLL_FREQ1 72000000U /* LPFLL trimed clock frequency(72MHz). */
#define SCG_LPFLL_FREQ2 96000000U /* LPFLL trimed clock frequency(96MHz). */
#define SCG_LPFLL_FREQ3 120000000U /* LPFLL trimed clock frequency(120MHz). */
#define SCG_CSR_SCS_VAL ((SCG->CSR & SCG_CSR_SCS_MASK) >> SCG_CSR_SCS_SHIFT)
#define SCG_SOSCDIV_SOSCDIV1_VAL ((SCG->SOSCDIV & SCG_SOSCDIV_SOSCDIV1_MASK) >> SCG_SOSCDIV_SOSCDIV1_SHIFT)
#define SCG_SOSCDIV_SOSCDIV2_VAL ((SCG->SOSCDIV & SCG_SOSCDIV_SOSCDIV2_MASK) >> SCG_SOSCDIV_SOSCDIV2_SHIFT)
#define SCG_SOSCDIV_SOSCDIV3_VAL ((SCG->SOSCDIV & SCG_SOSCDIV_SOSCDIV3_MASK) >> SCG_SOSCDIV_SOSCDIV3_SHIFT)
#define SCG_SIRCDIV_SIRCDIV1_VAL ((SCG->SIRCDIV & SCG_SIRCDIV_SIRCDIV1_MASK) >> SCG_SIRCDIV_SIRCDIV1_SHIFT)
#define SCG_SIRCDIV_SIRCDIV2_VAL ((SCG->SIRCDIV & SCG_SIRCDIV_SIRCDIV2_MASK) >> SCG_SIRCDIV_SIRCDIV2_SHIFT)
#define SCG_SIRCDIV_SIRCDIV3_VAL ((SCG->SIRCDIV & SCG_SIRCDIV_SIRCDIV3_MASK) >> SCG_SIRCDIV_SIRCDIV3_SHIFT)
#define SCG_FIRCDIV_FIRCDIV1_VAL ((SCG->FIRCDIV & SCG_FIRCDIV_FIRCDIV1_MASK) >> SCG_FIRCDIV_FIRCDIV1_SHIFT)
#define SCG_FIRCDIV_FIRCDIV2_VAL ((SCG->FIRCDIV & SCG_FIRCDIV_FIRCDIV2_MASK) >> SCG_FIRCDIV_FIRCDIV2_SHIFT)
#define SCG_FIRCDIV_FIRCDIV3_VAL ((SCG->FIRCDIV & SCG_FIRCDIV_FIRCDIV3_MASK) >> SCG_FIRCDIV_FIRCDIV3_SHIFT)
#define SCG_LPFLLDIV_LPFLLDIV1_VAL ((SCG->LPFLLDIV & SCG_LPFLLDIV_LPFLLDIV1_MASK) >> SCG_LPFLLDIV_LPFLLDIV1_SHIFT)
#define SCG_LPFLLDIV_LPFLLDIV2_VAL ((SCG->LPFLLDIV & SCG_LPFLLDIV_LPFLLDIV2_MASK) >> SCG_LPFLLDIV_LPFLLDIV2_SHIFT)
#define SCG_LPFLLDIV_LPFLLDIV3_VAL ((SCG->LPFLLDIV & SCG_LPFLLDIV_LPFLLDIV3_MASK) >> SCG_LPFLLDIV_LPFLLDIV3_SHIFT)
#define SCG_SIRCCFG_RANGE_VAL ((SCG->SIRCCFG & SCG_SIRCCFG_RANGE_MASK) >> SCG_SIRCCFG_RANGE_SHIFT)
#define SCG_FIRCCFG_RANGE_VAL ((SCG->FIRCCFG & SCG_FIRCCFG_RANGE_MASK) >> SCG_FIRCCFG_RANGE_SHIFT)
#define SCG_LPFLLCFG_FSEL_VAL ((SCG->LPFLLCFG & SCG_LPFLLCFG_FSEL_MASK) >> SCG_LPFLLCFG_FSEL_SHIFT)
/* Get the value of each field in PCC register. */
#define PCC_PCS_VAL(reg) ((reg & PCC_CLKCFG_PCS_MASK) >> PCC_CLKCFG_PCS_SHIFT)
#define PCC_FRAC_VAL(reg) ((reg & PCC_CLKCFG_FRAC_MASK) >> PCC_CLKCFG_FRAC_SHIFT)
#define PCC_PCD_VAL(reg) ((reg & PCC_CLKCFG_PCD_MASK) >> PCC_CLKCFG_PCD_SHIFT)
/*******************************************************************************
* Variables
******************************************************************************/
/* External XTAL0 (OSC0) clock frequency. */
uint32_t g_xtal0Freq;
/* External XTAL32K clock frequency. */
uint32_t g_xtal32Freq;
/*******************************************************************************
* Prototypes
******************************************************************************/
/*******************************************************************************
* Code
******************************************************************************/
uint32_t CLOCK_GetOsc32kClkFreq(void)
{
assert(g_xtal32Freq);
return g_xtal32Freq;
}
uint32_t CLOCK_GetFlashClkFreq(void)
{
return CLOCK_GetSysClkFreq(kSCG_SysClkSlow);
}
uint32_t CLOCK_GetBusClkFreq(void)
{
return CLOCK_GetSysClkFreq(kSCG_SysClkSlow);
}
uint32_t CLOCK_GetPlatClkFreq(void)
{
return CLOCK_GetSysClkFreq(kSCG_SysClkCore);
}
uint32_t CLOCK_GetCoreSysClkFreq(void)
{
return CLOCK_GetSysClkFreq(kSCG_SysClkCore);
}
uint32_t CLOCK_GetExtClkFreq(void)
{
return CLOCK_GetSysClkFreq(kSCG_SysClkExt);
}
uint32_t CLOCK_GetFreq(clock_name_t clockName)
{
uint32_t freq;
switch (clockName)
{
/* System layer clock. */
case kCLOCK_CoreSysClk:
case kCLOCK_PlatClk:
freq = CLOCK_GetSysClkFreq(kSCG_SysClkCore);
break;
case kCLOCK_BusClk:
freq = CLOCK_GetSysClkFreq(kSCG_SysClkBus);
break;
case kCLOCK_FlashClk:
freq = CLOCK_GetSysClkFreq(kSCG_SysClkSlow);
break;
case kCLOCK_ExtClk:
freq = CLOCK_GetSysClkFreq(kSCG_SysClkExt);
break;
/* Original clock source. */
case kCLOCK_ScgSysOscClk:
freq = CLOCK_GetSysOscFreq();
break;
case kCLOCK_ScgSircClk:
freq = CLOCK_GetSircFreq();
break;
case kCLOCK_ScgFircClk:
freq = CLOCK_GetFircFreq();
break;
case kCLOCK_ScgLpFllClk:
freq = CLOCK_GetLpFllFreq();
break;
/* SOSC div clock. */
case kCLOCK_ScgSysOscAsyncDiv1Clk:
freq = CLOCK_GetSysOscAsyncFreq(kSCG_AsyncDiv1Clk);
break;
case kCLOCK_ScgSysOscAsyncDiv2Clk:
freq = CLOCK_GetSysOscAsyncFreq(kSCG_AsyncDiv2Clk);
break;
case kCLOCK_ScgSysOscAsyncDiv3Clk:
freq = CLOCK_GetSysOscAsyncFreq(kSCG_AsyncDiv3Clk);
break;
/* SIRC div clock. */
case kCLOCK_ScgSircAsyncDiv1Clk:
freq = CLOCK_GetSircAsyncFreq(kSCG_AsyncDiv1Clk);
break;
case kCLOCK_ScgSircAsyncDiv2Clk:
freq = CLOCK_GetSircAsyncFreq(kSCG_AsyncDiv2Clk);
break;
case kCLOCK_ScgSircAsyncDiv3Clk:
freq = CLOCK_GetSircAsyncFreq(kSCG_AsyncDiv3Clk);
break;
/* FIRC div clock. */
case kCLOCK_ScgFircAsyncDiv1Clk:
freq = CLOCK_GetFircAsyncFreq(kSCG_AsyncDiv1Clk);
break;
case kCLOCK_ScgFircAsyncDiv2Clk:
freq = CLOCK_GetFircAsyncFreq(kSCG_AsyncDiv2Clk);
break;
case kCLOCK_ScgFircAsyncDiv3Clk:
freq = CLOCK_GetFircAsyncFreq(kSCG_AsyncDiv3Clk);
break;
/* LPFLL div clock. */
case kCLOCK_ScgSysLpFllAsyncDiv1Clk:
freq = CLOCK_GetLpFllAsyncFreq(kSCG_AsyncDiv1Clk);
break;
case kCLOCK_ScgSysLpFllAsyncDiv2Clk:
freq = CLOCK_GetLpFllAsyncFreq(kSCG_AsyncDiv2Clk);
break;
case kCLOCK_ScgSysLpFllAsyncDiv3Clk:
freq = CLOCK_GetLpFllAsyncFreq(kSCG_AsyncDiv3Clk);
break;
/* Other clocks. */
case kCLOCK_LpoClk:
freq = CLOCK_GetLpoClkFreq();
break;
case kCLOCK_Osc32kClk:
freq = CLOCK_GetOsc32kClkFreq();
break;
default:
freq = 0U;
break;
}
return freq;
}
uint32_t CLOCK_GetIpFreq(clock_ip_name_t name)
{
uint32_t reg = (*(volatile uint32_t *)name);
scg_async_clk_t asycClk;
uint32_t freq;
assert(reg & PCC_CLKCFG_PR_MASK);
switch (name)
{
case kCLOCK_Lpit0:
case kCLOCK_Lpit1:
asycClk = kSCG_AsyncDiv3Clk;
break;
case kCLOCK_Sdhc0:
case kCLOCK_Usb0:
asycClk = kSCG_AsyncDiv1Clk;
break;
default:
asycClk = kSCG_AsyncDiv2Clk;
break;
}
switch (PCC_PCS_VAL(reg))
{
case kCLOCK_IpSrcSysOscAsync:
freq = CLOCK_GetSysOscAsyncFreq(asycClk);
break;
case kCLOCK_IpSrcSircAsync:
freq = CLOCK_GetSircAsyncFreq(asycClk);
break;
case kCLOCK_IpSrcFircAsync:
freq = CLOCK_GetFircAsyncFreq(asycClk);
break;
case kCLOCK_IpSrcLpFllAsync:
freq = CLOCK_GetLpFllAsyncFreq(asycClk);
break;
default: /* kCLOCK_IpSrcNoneOrExt. */
freq = 0U;
break;
}
if (0U != (reg & (PCC_CLKCFG_PCD_MASK | PCC_CLKCFG_FRAC_MASK)))
{
return freq * (PCC_FRAC_VAL(reg) + 1U) / (PCC_PCD_VAL(reg) + 1U);
}
else
{
return freq;
}
}
bool CLOCK_EnableUsbfs0Clock(clock_usb_src_t src, uint32_t freq)
{
bool ret = true;
CLOCK_SetIpSrc(kCLOCK_Usb0, kCLOCK_IpSrcFircAsync);
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
/* Enable clock gate. */
CLOCK_EnableClock(kCLOCK_Usb0);
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
USBVREG->CTRL |= USBVREG_CTRL_EN_MASK;
USB0->CONTROL &= ~USB_CONTROL_DPPULLUPNONOTG_MASK;
if (kCLOCK_UsbSrcIrc48M == src)
{
USB0->CLK_RECOVER_IRC_EN = 0x03U;
USB0->CLK_RECOVER_CTRL |= USB_CLK_RECOVER_CTRL_CLOCK_RECOVER_EN_MASK;
USB0->CLK_RECOVER_INT_EN = 0x00U;
}
return ret;
}
uint32_t CLOCK_GetSysClkFreq(scg_sys_clk_t type)
{
uint32_t freq;
scg_sys_clk_config_t sysClkConfig;
CLOCK_GetCurSysClkConfig(&sysClkConfig); /* Get the main clock for SoC platform. */
switch (sysClkConfig.src)
{
case kSCG_SysClkSrcSysOsc:
freq = CLOCK_GetSysOscFreq();
break;
case kSCG_SysClkSrcSirc:
freq = CLOCK_GetSircFreq();
break;
case kSCG_SysClkSrcFirc:
freq = CLOCK_GetFircFreq();
break;
case kSCG_SysClkSrcRosc:
freq = CLOCK_GetRtcOscFreq();
break;
case kSCG_SysClkSrcLpFll:
freq = CLOCK_GetLpFllFreq();
break;
default:
freq = 0U;
break;
}
freq /= (sysClkConfig.divCore + 1U); /* divided by the DIVCORE firstly. */
if (kSCG_SysClkSlow == type)
{
freq /= (sysClkConfig.divSlow + 1U);
}
else if (kSCG_SysClkBus == type)
{
freq /= (sysClkConfig.divBus + 1U);
}
else if (kSCG_SysClkExt == type)
{
freq /= (sysClkConfig.divExt + 1U);
}
else
{
}
return freq;
}
status_t CLOCK_InitSysOsc(const scg_sosc_config_t *config)
{
assert(config);
status_t status;
uint8_t tmp8;
/* De-init the SOSC first. */
status = CLOCK_DeinitSysOsc();
if (kStatus_Success != status)
{
return status;
}
/* Now start to set up OSC clock. */
/* Step 1. Setup dividers. */
SCG->SOSCDIV =
SCG_SOSCDIV_SOSCDIV1(config->div1) | SCG_SOSCDIV_SOSCDIV2(config->div2) | SCG_SOSCDIV_SOSCDIV3(config->div3);
/* Step 2. Set OSC configuration. */
/* Step 3. Enable clock. */
/* SCG->SOSCCSR = SCG_SOSCCSR_SOSCEN_MASK | (config->enableMode); */
tmp8 = config->enableMode;
tmp8 |= SCG_SOSCCSR_SOSCEN_MASK;
SCG->SOSCCSR = tmp8;
/* Step 4. Wait for OSC clock to be valid. */
while (!(SCG->SOSCCSR & SCG_SOSCCSR_SOSCVLD_MASK))
{
}
/* Step 5. Enabe monitor. */
SCG->SOSCCSR |= (uint32_t)config->monitorMode;
return kStatus_Success;
}
status_t CLOCK_DeinitSysOsc(void)
{
uint32_t reg = SCG->SOSCCSR;
/* If clock is used by system, return error. */
if (reg & SCG_SOSCCSR_SOSCSEL_MASK)
{
return kStatus_SCG_Busy;
}
/* If configure register is locked, return error. */
if (reg & SCG_SOSCCSR_LK_MASK)
{
return kStatus_ReadOnly;
}
SCG->SOSCCSR = SCG_SOSCCSR_SOSCERR_MASK;
return kStatus_Success;
}
uint32_t CLOCK_GetSysOscFreq(void)
{
if (SCG->SOSCCSR & SCG_SOSCCSR_SOSCVLD_MASK) /* System OSC clock is valid. */
{
/* Please call CLOCK_SetXtal0Freq base on board setting before using OSC0 clock. */
assert(g_xtal0Freq);
return g_xtal0Freq;
}
else
{
return 0U;
}
}
uint32_t CLOCK_GetSysOscAsyncFreq(scg_async_clk_t type)
{
uint32_t oscFreq = CLOCK_GetSysOscFreq();
uint32_t divider = 0U;
/* Get divider. */
if (oscFreq)
{
switch (type)
{
case kSCG_AsyncDiv3Clk: /* SOSCDIV3_CLK. */
divider = SCG_SOSCDIV_SOSCDIV3_VAL;
break;
case kSCG_AsyncDiv2Clk: /* SOSCDIV2_CLK. */
divider = SCG_SOSCDIV_SOSCDIV2_VAL;
break;
case kSCG_AsyncDiv1Clk: /* SOSCDIV1_CLK. */
divider = SCG_SOSCDIV_SOSCDIV1_VAL;
break;
default:
break;
}
}
if (divider)
{
return oscFreq >> (divider - 1U);
}
else /* Output disabled. */
{
return 0U;
}
}
status_t CLOCK_InitSirc(const scg_sirc_config_t *config)
{
assert(config);
status_t status;
/* De-init the SIRC first. */
status = CLOCK_DeinitSirc();
if (kStatus_Success != status)
{
return status;
}
/* Now start to set up SIRC clock. */
/* Step 1. Setup dividers. */
SCG->SIRCDIV =
SCG_SIRCDIV_SIRCDIV1(config->div1) | SCG_SIRCDIV_SIRCDIV2(config->div2) | SCG_SIRCDIV_SIRCDIV3(config->div3);
/* Step 2. Set SIRC configuration. */
SCG->SIRCCFG = SCG_SIRCCFG_RANGE(config->range);
/* Step 3. Enable clock. */
SCG->SIRCCSR = SCG_SIRCCSR_SIRCEN_MASK | config->enableMode;
/* Step 4. Wait for SIRC clock to be valid. */
while (!(SCG->SIRCCSR & SCG_SIRCCSR_SIRCVLD_MASK))
{
}
return kStatus_Success;
}
status_t CLOCK_DeinitSirc(void)
{
uint32_t reg = SCG->SIRCCSR;
/* If clock is used by system, return error. */
if (reg & SCG_SIRCCSR_SIRCSEL_MASK)
{
return kStatus_SCG_Busy;
}
/* If configure register is locked, return error. */
if (reg & SCG_SIRCCSR_LK_MASK)
{
return kStatus_ReadOnly;
}
SCG->SIRCCSR = 0U;
return kStatus_Success;
}
uint32_t CLOCK_GetSircFreq(void)
{
static const uint32_t sircFreq[] = {SCG_SIRC_LOW_RANGE_FREQ, SCG_SIRC_HIGH_RANGE_FREQ};
if (SCG->SIRCCSR & SCG_SIRCCSR_SIRCVLD_MASK) /* SIRC is valid. */
{
return sircFreq[SCG_SIRCCFG_RANGE_VAL];
}
else
{
return 0U;
}
}
uint32_t CLOCK_GetSircAsyncFreq(scg_async_clk_t type)
{
uint32_t sircFreq = CLOCK_GetSircFreq();
uint32_t divider = 0U;
/* Get divider. */
if (sircFreq)
{
switch (type)
{
case kSCG_AsyncDiv3Clk: /* SIRCDIV3_CLK. */
divider = SCG_SIRCDIV_SIRCDIV3_VAL;
break;
case kSCG_AsyncDiv2Clk: /* SIRCDIV2_CLK. */
divider = SCG_SIRCDIV_SIRCDIV2_VAL;
break;
case kSCG_AsyncDiv1Clk: /* SIRCDIV2_CLK. */
divider = SCG_SIRCDIV_SIRCDIV1_VAL;
break;
default:
break;
}
}
if (divider)
{
return sircFreq >> (divider - 1U);
}
else /* Output disabled. */
{
return 0U;
}
}
status_t CLOCK_InitFirc(const scg_firc_config_t *config)
{
assert(config);
status_t status;
/* De-init the FIRC first. */
status = CLOCK_DeinitFirc();
if (kStatus_Success != status)
{
return status;
}
/* Now start to set up FIRC clock. */
/* Step 1. Setup dividers. */
SCG->FIRCDIV =
SCG_FIRCDIV_FIRCDIV1(config->div1) | SCG_FIRCDIV_FIRCDIV2(config->div2) | SCG_FIRCDIV_FIRCDIV3(config->div3);
/* Step 2. Set FIRC configuration. */
SCG->FIRCCFG = SCG_FIRCCFG_RANGE(config->range);
/* Step 3. Set trimming configuration. */
if (config->trimConfig)
{
SCG->FIRCTCFG =
SCG_FIRCTCFG_TRIMDIV(config->trimConfig->trimDiv) | SCG_FIRCTCFG_TRIMSRC(config->trimConfig->trimSrc);
/* TODO: Write FIRCSTAT cause bus error: TKT266932. */
if (kSCG_FircTrimNonUpdate == config->trimConfig->trimMode)
{
SCG->FIRCSTAT = SCG_FIRCSTAT_TRIMCOAR(config->trimConfig->trimCoar) |
SCG_FIRCSTAT_TRIMFINE(config->trimConfig->trimFine);
}
/* trim mode. */
SCG->FIRCCSR = config->trimConfig->trimMode;
if (SCG->FIRCCSR & SCG_FIRCCSR_FIRCERR_MASK)
{
return kStatus_Fail;
}
}
/* Step 4. Enable clock. */
SCG->FIRCCSR |= (SCG_FIRCCSR_FIRCEN_MASK | SCG_FIRCCSR_FIRCTREN_MASK | config->enableMode);
/* Step 5. Wait for FIRC clock to be valid. */
while (!(SCG->FIRCCSR & SCG_FIRCCSR_FIRCVLD_MASK))
{
}
return kStatus_Success;
}
status_t CLOCK_DeinitFirc(void)
{
uint32_t reg = SCG->FIRCCSR;
/* If clock is used by system, return error. */
if (reg & SCG_FIRCCSR_FIRCSEL_MASK)
{
return kStatus_SCG_Busy;
}
/* If configure register is locked, return error. */
if (reg & SCG_FIRCCSR_LK_MASK)
{
return kStatus_ReadOnly;
}
SCG->FIRCCSR = SCG_FIRCCSR_FIRCERR_MASK;
return kStatus_Success;
}
uint32_t CLOCK_GetFircFreq(void)
{
static const uint32_t fircFreq[] = {
SCG_FIRC_FREQ0, SCG_FIRC_FREQ1, SCG_FIRC_FREQ2, SCG_FIRC_FREQ3,
};
if (SCG->FIRCCSR & SCG_FIRCCSR_FIRCVLD_MASK) /* FIRC is valid. */
{
return fircFreq[SCG_FIRCCFG_RANGE_VAL];
}
else
{
return 0U;
}
}
uint32_t CLOCK_GetFircAsyncFreq(scg_async_clk_t type)
{
uint32_t fircFreq = CLOCK_GetFircFreq();
uint32_t divider = 0U;
/* Get divider. */
if (fircFreq)
{
switch (type)
{
case kSCG_AsyncDiv3Clk: /* FIRCDIV3_CLK. */
divider = SCG_FIRCDIV_FIRCDIV3_VAL;
break;
case kSCG_AsyncDiv2Clk: /* FIRCDIV2_CLK. */
divider = SCG_FIRCDIV_FIRCDIV2_VAL;
break;
case kSCG_AsyncDiv1Clk: /* FIRCDIV1_CLK. */
divider = SCG_FIRCDIV_FIRCDIV1_VAL;
break;
default:
break;
}
}
if (divider)
{
return fircFreq >> (divider - 1U);
}
else /* Output disabled. */
{
return 0U;
}
}
uint32_t CLOCK_GetRtcOscFreq(void)
{
if (SCG->ROSCCSR & SCG_ROSCCSR_ROSCVLD_MASK) /* RTC OSC clock is valid. */
{
/* Please call CLOCK_SetXtal32Freq base on board setting before using RTC OSC clock. */
assert(g_xtal32Freq);
return g_xtal32Freq;
}
else
{
return 0U;
}
}
status_t CLOCK_InitLpFll(const scg_lpfll_config_t *config)
{
assert(config);
status_t status;
/* De-init the LPFLL first. */
status = CLOCK_DeinitLpFll();
if (kStatus_Success != status)
{
return status;
}
/* Now start to set up LPFLL clock. */
/* Step 1. Setup dividers. */
SCG->LPFLLDIV = SCG_LPFLLDIV_LPFLLDIV1(config->div1) | SCG_LPFLLDIV_LPFLLDIV2(config->div2) |
SCG_LPFLLDIV_LPFLLDIV3(config->div3);
/* Step 2. Set LPFLL configuration. */
SCG->LPFLLCFG = SCG_LPFLLCFG_FSEL(config->range);
/* Step 3. Set trimming configuration. */
if (config->trimConfig)
{
SCG->LPFLLTCFG = SCG_LPFLLTCFG_TRIMDIV(config->trimConfig->trimDiv) |
SCG_LPFLLTCFG_TRIMSRC(config->trimConfig->trimSrc) |
SCG_LPFLLTCFG_LOCKW2LSB(config->trimConfig->lockMode);
if (kSCG_LpFllTrimNonUpdate == config->trimConfig->trimMode)
{
SCG->LPFLLSTAT = config->trimConfig->trimValue;
}
/* Trim mode. */
SCG->LPFLLCSR = config->trimConfig->trimMode;
if (SCG->LPFLLCSR & SCG_LPFLLCSR_LPFLLERR_MASK)
{
return kStatus_Fail;
}
}
/* Step 4. Enable clock. */
SCG->LPFLLCSR |= (SCG_LPFLLCSR_LPFLLEN_MASK | config->enableMode);
/* Step 5. Wait for LPFLL clock to be valid. */
while (!(SCG->LPFLLCSR & SCG_LPFLLCSR_LPFLLVLD_MASK))
{
}
/* Step 6. Wait for LPFLL trim lock. */
if ((config->trimConfig) && (kSCG_LpFllTrimUpdate == config->trimConfig->trimMode))
{
while (!(SCG->LPFLLCSR & SCG_LPFLLCSR_LPFLLTRMLOCK_MASK))
{
}
}
return kStatus_Success;
}
status_t CLOCK_DeinitLpFll(void)
{
uint32_t reg = SCG->LPFLLCSR;
/* If clock is used by system, return error. */
if (reg & SCG_LPFLLCSR_LPFLLSEL_MASK)
{
return kStatus_SCG_Busy;
}
/* If configure register is locked, return error. */
if (reg & SCG_LPFLLCSR_LK_MASK)
{
return kStatus_ReadOnly;
}
SCG->LPFLLCSR = SCG_LPFLLCSR_LPFLLERR_MASK;
return kStatus_Success;
}
uint32_t CLOCK_GetLpFllFreq(void)
{
static const uint32_t lpfllFreq[] = {
SCG_LPFLL_FREQ0, SCG_LPFLL_FREQ1, SCG_LPFLL_FREQ2, SCG_LPFLL_FREQ3,
};
if (SCG->LPFLLCSR & SCG_LPFLLCSR_LPFLLVLD_MASK) /* LPFLL is valid. */
{
return lpfllFreq[SCG_LPFLLCFG_FSEL_VAL];
}
else
{
return 0U;
}
}
uint32_t CLOCK_GetLpFllAsyncFreq(scg_async_clk_t type)
{
uint32_t lpfllFreq = CLOCK_GetLpFllFreq();
uint32_t divider = 0U;
/* Get divider. */
if (lpfllFreq)
{
switch (type)
{
case kSCG_AsyncDiv2Clk: /* LPFLLDIV2_CLK. */
divider = SCG_LPFLLDIV_LPFLLDIV2_VAL;
break;
case kSCG_AsyncDiv1Clk: /* LPFLLDIV1_CLK. */
divider = SCG_LPFLLDIV_LPFLLDIV1_VAL;
break;
default:
break;
}
}
if (divider)
{
return lpfllFreq >> (divider - 1U);
}
else /* Output disabled. */
{
return 0U;
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,117 @@
/*
* Copyright (c) 2015-2016, Freescale Semiconductor, Inc.
* Copyright 2016 NXP
* All rights reserved.
*
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include "fsl_common.h"
#include "fsl_debug_console.h"
#ifndef NDEBUG
#if (defined(__CC_ARM)) || (defined(__ICCARM__))
void __aeabi_assert(const char *failedExpr, const char *file, int line)
{
PRINTF("ASSERT ERROR \" %s \": file \"%s\" Line \"%d\" \n", failedExpr, file, line);
for (;;)
{
__BKPT(0);
}
}
#elif(defined(__GNUC__))
void __assert_func(const char *file, int line, const char *func, const char *failedExpr)
{
PRINTF("ASSERT ERROR \" %s \": file \"%s\" Line \"%d\" function name \"%s\" \n", failedExpr, file, line, func);
for (;;)
{
__BKPT(0);
}
}
#endif /* (defined(__CC_ARM)) || (defined (__ICCARM__)) */
#endif /* NDEBUG */
#ifndef __GIC_PRIO_BITS
#ifndef __riscv
uint32_t InstallIRQHandler(IRQn_Type irq, uint32_t irqHandler)
{
/* Addresses for VECTOR_TABLE and VECTOR_RAM come from the linker file */
#if defined(__CC_ARM)
extern uint32_t Image$$VECTOR_ROM$$Base[];
extern uint32_t Image$$VECTOR_RAM$$Base[];
extern uint32_t Image$$RW_m_data$$Base[];
#define __VECTOR_TABLE Image$$VECTOR_ROM$$Base
#define __VECTOR_RAM Image$$VECTOR_RAM$$Base
#define __RAM_VECTOR_TABLE_SIZE (((uint32_t)Image$$RW_m_data$$Base - (uint32_t)Image$$VECTOR_RAM$$Base))
#elif defined(__ICCARM__)
extern uint32_t __RAM_VECTOR_TABLE_SIZE[];
extern uint32_t __VECTOR_TABLE[];
extern uint32_t __VECTOR_RAM[];
#elif defined(__GNUC__)
extern uint32_t __VECTOR_TABLE[];
extern uint32_t __VECTOR_RAM[];
extern uint32_t __RAM_VECTOR_TABLE_SIZE_BYTES[];
uint32_t __RAM_VECTOR_TABLE_SIZE = (uint32_t)(__RAM_VECTOR_TABLE_SIZE_BYTES);
#endif /* defined(__CC_ARM) */
uint32_t n;
uint32_t ret;
uint32_t irqMaskValue;
irqMaskValue = DisableGlobalIRQ();
if (SCB->VTOR != (uint32_t)__VECTOR_RAM)
{
/* Copy the vector table from ROM to RAM */
for (n = 0; n < ((uint32_t)__RAM_VECTOR_TABLE_SIZE) / sizeof(uint32_t); n++)
{
__VECTOR_RAM[n] = __VECTOR_TABLE[n];
}
/* Point the VTOR to the position of vector table */
SCB->VTOR = (uint32_t)__VECTOR_RAM;
}
ret = __VECTOR_RAM[irq + 16];
/* make sure the __VECTOR_RAM is noncachable */
__VECTOR_RAM[irq + 16] = irqHandler;
EnableGlobalIRQ(irqMaskValue);
return ret;
}
#endif
#endif
#ifndef QN908XC_SERIES
#if (defined(FSL_FEATURE_SOC_SYSCON_COUNT) && (FSL_FEATURE_SOC_SYSCON_COUNT > 0))
void EnableDeepSleepIRQ(IRQn_Type interrupt)
{
uint32_t index = 0;
uint32_t intNumber = (uint32_t)interrupt;
while (intNumber >= 32u)
{
index++;
intNumber -= 32u;
}
SYSCON->STARTERSET[index] = 1u << intNumber;
EnableIRQ(interrupt); /* also enable interrupt at NVIC */
}
void DisableDeepSleepIRQ(IRQn_Type interrupt)
{
uint32_t index = 0;
uint32_t intNumber = (uint32_t)interrupt;
while (intNumber >= 32u)
{
index++;
intNumber -= 32u;
}
DisableIRQ(interrupt); /* also disable interrupt at NVIC */
SYSCON->STARTERCLR[index] = 1u << intNumber;
}
#endif /* FSL_FEATURE_SOC_SYSCON_COUNT */
#endif /* QN908XC_SERIES */

View File

@ -0,0 +1,485 @@
/*
* Copyright (c) 2015-2016, Freescale Semiconductor, Inc.
* Copyright 2016-2017 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef _FSL_COMMON_H_
#define _FSL_COMMON_H_
#include <assert.h>
#include <stdbool.h>
#include <stdint.h>
#include <string.h>
#if defined(__ICCARM__)
#include <stddef.h>
#endif
#include "fsl_device_registers.h"
/*!
* @addtogroup ksdk_common
* @{
*/
/*******************************************************************************
* Definitions
******************************************************************************/
/*! @brief Construct a status code value from a group and code number. */
#define MAKE_STATUS(group, code) ((((group)*100) + (code)))
/*! @brief Construct the version number for drivers. */
#define MAKE_VERSION(major, minor, bugfix) (((major) << 16) | ((minor) << 8) | (bugfix))
/*! @name Driver version */
/*@{*/
/*! @brief common driver version 2.0.0. */
#define FSL_COMMON_DRIVER_VERSION (MAKE_VERSION(2, 0, 0))
/*@}*/
/* Debug console type definition. */
#define DEBUG_CONSOLE_DEVICE_TYPE_NONE 0U /*!< No debug console. */
#define DEBUG_CONSOLE_DEVICE_TYPE_UART 1U /*!< Debug console base on UART. */
#define DEBUG_CONSOLE_DEVICE_TYPE_LPUART 2U /*!< Debug console base on LPUART. */
#define DEBUG_CONSOLE_DEVICE_TYPE_LPSCI 3U /*!< Debug console base on LPSCI. */
#define DEBUG_CONSOLE_DEVICE_TYPE_USBCDC 4U /*!< Debug console base on USBCDC. */
#define DEBUG_CONSOLE_DEVICE_TYPE_FLEXCOMM 5U /*!< Debug console base on USBCDC. */
#define DEBUG_CONSOLE_DEVICE_TYPE_IUART 6U /*!< Debug console base on i.MX UART. */
#define DEBUG_CONSOLE_DEVICE_TYPE_VUSART 7U /*!< Debug console base on LPC_USART. */
/*! @brief Status group numbers. */
enum _status_groups
{
kStatusGroup_Generic = 0, /*!< Group number for generic status codes. */
kStatusGroup_FLASH = 1, /*!< Group number for FLASH status codes. */
kStatusGroup_LPSPI = 4, /*!< Group number for LPSPI status codes. */
kStatusGroup_FLEXIO_SPI = 5, /*!< Group number for FLEXIO SPI status codes. */
kStatusGroup_DSPI = 6, /*!< Group number for DSPI status codes. */
kStatusGroup_FLEXIO_UART = 7, /*!< Group number for FLEXIO UART status codes. */
kStatusGroup_FLEXIO_I2C = 8, /*!< Group number for FLEXIO I2C status codes. */
kStatusGroup_LPI2C = 9, /*!< Group number for LPI2C status codes. */
kStatusGroup_UART = 10, /*!< Group number for UART status codes. */
kStatusGroup_I2C = 11, /*!< Group number for UART status codes. */
kStatusGroup_LPSCI = 12, /*!< Group number for LPSCI status codes. */
kStatusGroup_LPUART = 13, /*!< Group number for LPUART status codes. */
kStatusGroup_SPI = 14, /*!< Group number for SPI status code.*/
kStatusGroup_XRDC = 15, /*!< Group number for XRDC status code.*/
kStatusGroup_SEMA42 = 16, /*!< Group number for SEMA42 status code.*/
kStatusGroup_SDHC = 17, /*!< Group number for SDHC status code */
kStatusGroup_SDMMC = 18, /*!< Group number for SDMMC status code */
kStatusGroup_SAI = 19, /*!< Group number for SAI status code */
kStatusGroup_MCG = 20, /*!< Group number for MCG status codes. */
kStatusGroup_SCG = 21, /*!< Group number for SCG status codes. */
kStatusGroup_SDSPI = 22, /*!< Group number for SDSPI status codes. */
kStatusGroup_FLEXIO_I2S = 23, /*!< Group number for FLEXIO I2S status codes */
kStatusGroup_FLEXIO_MCULCD = 24, /*!< Group number for FLEXIO LCD status codes */
kStatusGroup_FLASHIAP = 25, /*!< Group number for FLASHIAP status codes */
kStatusGroup_FLEXCOMM_I2C = 26, /*!< Group number for FLEXCOMM I2C status codes */
kStatusGroup_I2S = 27, /*!< Group number for I2S status codes */
kStatusGroup_IUART = 28, /*!< Group number for IUART status codes */
kStatusGroup_CSI = 29, /*!< Group number for CSI status codes */
kStatusGroup_SDRAMC = 35, /*!< Group number for SDRAMC status codes. */
kStatusGroup_POWER = 39, /*!< Group number for POWER status codes. */
kStatusGroup_ENET = 40, /*!< Group number for ENET status codes. */
kStatusGroup_PHY = 41, /*!< Group number for PHY status codes. */
kStatusGroup_TRGMUX = 42, /*!< Group number for TRGMUX status codes. */
kStatusGroup_SMARTCARD = 43, /*!< Group number for SMARTCARD status codes. */
kStatusGroup_LMEM = 44, /*!< Group number for LMEM status codes. */
kStatusGroup_QSPI = 45, /*!< Group number for QSPI status codes. */
kStatusGroup_DMA = 50, /*!< Group number for DMA status codes. */
kStatusGroup_EDMA = 51, /*!< Group number for EDMA status codes. */
kStatusGroup_DMAMGR = 52, /*!< Group number for DMAMGR status codes. */
kStatusGroup_FLEXCAN = 53, /*!< Group number for FlexCAN status codes. */
kStatusGroup_LTC = 54, /*!< Group number for LTC status codes. */
kStatusGroup_FLEXIO_CAMERA = 55, /*!< Group number for FLEXIO CAMERA status codes. */
kStatusGroup_LPC_SPI = 56, /*!< Group number for LPC_SPI status codes. */
kStatusGroup_LPC_USART = 57, /*!< Group number for LPC_USART status codes. */
kStatusGroup_DMIC = 58, /*!< Group number for DMIC status codes. */
kStatusGroup_SDIF = 59, /*!< Group number for SDIF status codes.*/
kStatusGroup_SPIFI = 60, /*!< Group number for SPIFI status codes. */
kStatusGroup_OTP = 61, /*!< Group number for OTP status codes. */
kStatusGroup_MCAN = 62, /*!< Group number for MCAN status codes. */
kStatusGroup_CAAM = 63, /*!< Group number for CAAM status codes. */
kStatusGroup_ECSPI = 64, /*!< Group number for ECSPI status codes. */
kStatusGroup_USDHC = 65, /*!< Group number for USDHC status codes.*/
kStatusGroup_LPC_I2C = 66, /*!< Group number for LPC_I2C status codes.*/
kStatusGroup_ESAI = 69, /*!< Group number for ESAI status codes. */
kStatusGroup_FLEXSPI = 70, /*!< Group number for FLEXSPI status codes. */
kStatusGroup_MMDC = 71, /*!< Group number for MMDC status codes. */
kStatusGroup_MICFIL = 72, /*!< Group number for MIC status codes. */
kStatusGroup_SDMA = 73, /*!< Group number for SDMA status codes. */
kStatusGroup_ICS = 74, /*!< Group number for ICS status codes. */
kStatusGroup_NOTIFIER = 98, /*!< Group number for NOTIFIER status codes. */
kStatusGroup_DebugConsole = 99, /*!< Group number for debug console status codes. */
kStatusGroup_ApplicationRangeStart = 100, /*!< Starting number for application groups. */
};
/*! @brief Generic status return codes. */
enum _generic_status
{
kStatus_Success = MAKE_STATUS(kStatusGroup_Generic, 0),
kStatus_Fail = MAKE_STATUS(kStatusGroup_Generic, 1),
kStatus_ReadOnly = MAKE_STATUS(kStatusGroup_Generic, 2),
kStatus_OutOfRange = MAKE_STATUS(kStatusGroup_Generic, 3),
kStatus_InvalidArgument = MAKE_STATUS(kStatusGroup_Generic, 4),
kStatus_Timeout = MAKE_STATUS(kStatusGroup_Generic, 5),
kStatus_NoTransferInProgress = MAKE_STATUS(kStatusGroup_Generic, 6),
};
/*! @brief Type used for all status and error return values. */
typedef int32_t status_t;
/*
* The fsl_clock.h is included here because it needs MAKE_VERSION/MAKE_STATUS/status_t
* defined in previous of this file.
*/
#include "fsl_clock.h"
/*
* Chip level peripheral reset API, for MCUs that implement peripheral reset control external to a peripheral
*/
#if ((defined(FSL_FEATURE_SOC_SYSCON_COUNT) && (FSL_FEATURE_SOC_SYSCON_COUNT > 0)) || \
(defined(FSL_FEATURE_SOC_ASYNC_SYSCON_COUNT) && (FSL_FEATURE_SOC_ASYNC_SYSCON_COUNT > 0)))
#include "fsl_reset.h"
#endif
/*! @name Min/max macros */
/* @{ */
#if !defined(MIN)
#define MIN(a, b) ((a) < (b) ? (a) : (b))
#endif
#if !defined(MAX)
#define MAX(a, b) ((a) > (b) ? (a) : (b))
#endif
/* @} */
/*! @brief Computes the number of elements in an array. */
#if !defined(ARRAY_SIZE)
#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
#endif
/*! @name UINT16_MAX/UINT32_MAX value */
/* @{ */
#if !defined(UINT16_MAX)
#define UINT16_MAX ((uint16_t)-1)
#endif
#if !defined(UINT32_MAX)
#define UINT32_MAX ((uint32_t)-1)
#endif
/* @} */
/*! @name Timer utilities */
/* @{ */
/*! Macro to convert a microsecond period to raw count value */
#define USEC_TO_COUNT(us, clockFreqInHz) (uint64_t)((uint64_t)us * clockFreqInHz / 1000000U)
/*! Macro to convert a raw count value to microsecond */
#define COUNT_TO_USEC(count, clockFreqInHz) (uint64_t)((uint64_t)count * 1000000U / clockFreqInHz)
/*! Macro to convert a millisecond period to raw count value */
#define MSEC_TO_COUNT(ms, clockFreqInHz) (uint64_t)((uint64_t)ms * clockFreqInHz / 1000U)
/*! Macro to convert a raw count value to millisecond */
#define COUNT_TO_MSEC(count, clockFreqInHz) (uint64_t)((uint64_t)count * 1000U / clockFreqInHz)
/* @} */
/*! @name Alignment variable definition macros */
/* @{ */
#if (defined(__ICCARM__))
/**
* Workaround to disable MISRA C message suppress warnings for IAR compiler.
* http://supp.iar.com/Support/?note=24725
*/
_Pragma("diag_suppress=Pm120")
#define SDK_PRAGMA(x) _Pragma(#x)
_Pragma("diag_error=Pm120")
/*! Macro to define a variable with alignbytes alignment */
#define SDK_ALIGN(var, alignbytes) SDK_PRAGMA(data_alignment = alignbytes) var
/*! Macro to define a variable with L1 d-cache line size alignment */
#if defined(FSL_FEATURE_L1DCACHE_LINESIZE_BYTE)
#define SDK_L1DCACHE_ALIGN(var) SDK_PRAGMA(data_alignment = FSL_FEATURE_L1DCACHE_LINESIZE_BYTE) var
#endif
/*! Macro to define a variable with L2 cache line size alignment */
#if defined(FSL_FEATURE_L2CACHE_LINESIZE_BYTE)
#define SDK_L2CACHE_ALIGN(var) SDK_PRAGMA(data_alignment = FSL_FEATURE_L2CACHE_LINESIZE_BYTE) var
#endif
#elif defined(__CC_ARM)
/*! Macro to define a variable with alignbytes alignment */
#define SDK_ALIGN(var, alignbytes) __align(alignbytes) var
/*! Macro to define a variable with L1 d-cache line size alignment */
#if defined(FSL_FEATURE_L1DCACHE_LINESIZE_BYTE)
#define SDK_L1DCACHE_ALIGN(var) __align(FSL_FEATURE_L1DCACHE_LINESIZE_BYTE) var
#endif
/*! Macro to define a variable with L2 cache line size alignment */
#if defined(FSL_FEATURE_L2CACHE_LINESIZE_BYTE)
#define SDK_L2CACHE_ALIGN(var) __align(FSL_FEATURE_L2CACHE_LINESIZE_BYTE) var
#endif
#elif defined(__GNUC__)
/*! Macro to define a variable with alignbytes alignment */
#define SDK_ALIGN(var, alignbytes) var __attribute__((aligned(alignbytes)))
/*! Macro to define a variable with L1 d-cache line size alignment */
#if defined(FSL_FEATURE_L1DCACHE_LINESIZE_BYTE)
#define SDK_L1DCACHE_ALIGN(var) var __attribute__((aligned(FSL_FEATURE_L1DCACHE_LINESIZE_BYTE)))
#endif
/*! Macro to define a variable with L2 cache line size alignment */
#if defined(FSL_FEATURE_L2CACHE_LINESIZE_BYTE)
#define SDK_L2CACHE_ALIGN(var) var __attribute__((aligned(FSL_FEATURE_L2CACHE_LINESIZE_BYTE)))
#endif
#else
#error Toolchain not supported
#define SDK_ALIGN(var, alignbytes) var
#if defined(FSL_FEATURE_L1DCACHE_LINESIZE_BYTE)
#define SDK_L1DCACHE_ALIGN(var) var
#endif
#if defined(FSL_FEATURE_L2CACHE_LINESIZE_BYTE)
#define SDK_L2CACHE_ALIGN(var) var
#endif
#endif
/*! Macro to change a value to a given size aligned value */
#define SDK_SIZEALIGN(var, alignbytes) \
((unsigned int)((var) + ((alignbytes)-1)) & (unsigned int)(~(unsigned int)((alignbytes)-1)))
/* @} */
/*! @name Non-cacheable region definition macros */
/* @{ */
#if (defined(__ICCARM__))
#if defined(FSL_FEATURE_L1ICACHE_LINESIZE_BYTE)
#define AT_NONCACHEABLE_SECTION(var) var @"NonCacheable"
#define AT_NONCACHEABLE_SECTION_ALIGN(var, alignbytes) SDK_PRAGMA(data_alignment = alignbytes) var @"NonCacheable"
#else
#define AT_NONCACHEABLE_SECTION(var) var
#define AT_NONCACHEABLE_SECTION_ALIGN(var, alignbytes) SDK_PRAGMA(data_alignment = alignbytes) var
#endif
#elif(defined(__CC_ARM))
#if defined(FSL_FEATURE_L1ICACHE_LINESIZE_BYTE)
#define AT_NONCACHEABLE_SECTION(var) __attribute__((section("NonCacheable"))) var
#define AT_NONCACHEABLE_SECTION_ALIGN(var, alignbytes) \
__attribute__((section("NonCacheable"), zero_init)) __align(alignbytes) var
#else
#define AT_NONCACHEABLE_SECTION(var) var
#define AT_NONCACHEABLE_SECTION_ALIGN(var, alignbytes) __align(alignbytes) var
#endif
#elif(defined(__GNUC__))
/* For GCC, when the non-cacheable section is required, please define "__STARTUP_INITIALIZE_NONCACHEDATA"
* in your projects to make sure the non-cacheable section variables will be initialized in system startup.
*/
#if defined(FSL_FEATURE_L1ICACHE_LINESIZE_BYTE)
#define AT_NONCACHEABLE_SECTION(var) __attribute__((section("NonCacheable"))) var
#define AT_NONCACHEABLE_SECTION_ALIGN(var, alignbytes) \
__attribute__((section("NonCacheable"))) var __attribute__((aligned(alignbytes)))
#else
#define AT_NONCACHEABLE_SECTION(var) var
#define AT_NONCACHEABLE_SECTION_ALIGN(var, alignbytes) var __attribute__((aligned(alignbytes)))
#endif
#else
#error Toolchain not supported.
#define AT_NONCACHEABLE_SECTION(var) var
#define AT_NONCACHEABLE_SECTION_ALIGN(var, alignbytes) var
#endif
/* @} */
/*******************************************************************************
* API
******************************************************************************/
#if defined(__cplusplus)
extern "C" {
#endif
/*!
* @brief Enable specific interrupt.
*
* Enable LEVEL1 interrupt. For some devices, there might be multiple interrupt
* levels. For example, there are NVIC and intmux. Here the interrupts connected
* to NVIC are the LEVEL1 interrupts, because they are routed to the core directly.
* The interrupts connected to intmux are the LEVEL2 interrupts, they are routed
* to NVIC first then routed to core.
*
* This function only enables the LEVEL1 interrupts. The number of LEVEL1 interrupts
* is indicated by the feature macro FSL_FEATURE_NUMBER_OF_LEVEL1_INT_VECTORS.
*
* @param interrupt The IRQ number.
* @retval kStatus_Success Interrupt enabled successfully
* @retval kStatus_Fail Failed to enable the interrupt
*/
static inline status_t EnableIRQ(IRQn_Type interrupt)
{
if (NotAvail_IRQn == interrupt)
{
return kStatus_Fail;
}
#if defined(FSL_FEATURE_NUMBER_OF_LEVEL1_INT_VECTORS) && (FSL_FEATURE_NUMBER_OF_LEVEL1_INT_VECTORS > 0)
if (interrupt >= FSL_FEATURE_NUMBER_OF_LEVEL1_INT_VECTORS)
{
return kStatus_Fail;
}
#endif
#if defined(FSL_FEATURE_SOC_EVENT_COUNT) && (FSL_FEATURE_SOC_EVENT_COUNT > 0)
EVENT_UNIT->INTPTEN |= (uint32_t)(1 << interrupt);
/* Read back to make sure write finished. */
(void)EVENT_UNIT->INTPTEN;
#else
#if defined(__GIC_PRIO_BITS)
GIC_EnableIRQ(interrupt);
#else
NVIC_EnableIRQ(interrupt);
#endif
#endif
return kStatus_Success;
}
/*!
* @brief Disable specific interrupt.
*
* Disable LEVEL1 interrupt. For some devices, there might be multiple interrupt
* levels. For example, there are NVIC and intmux. Here the interrupts connected
* to NVIC are the LEVEL1 interrupts, because they are routed to the core directly.
* The interrupts connected to intmux are the LEVEL2 interrupts, they are routed
* to NVIC first then routed to core.
*
* This function only disables the LEVEL1 interrupts. The number of LEVEL1 interrupts
* is indicated by the feature macro FSL_FEATURE_NUMBER_OF_LEVEL1_INT_VECTORS.
*
* @param interrupt The IRQ number.
* @retval kStatus_Success Interrupt disabled successfully
* @retval kStatus_Fail Failed to disable the interrupt
*/
static inline status_t DisableIRQ(IRQn_Type interrupt)
{
if (NotAvail_IRQn == interrupt)
{
return kStatus_Fail;
}
#if defined(FSL_FEATURE_NUMBER_OF_LEVEL1_INT_VECTORS) && (FSL_FEATURE_NUMBER_OF_LEVEL1_INT_VECTORS > 0)
if (interrupt >= FSL_FEATURE_NUMBER_OF_LEVEL1_INT_VECTORS)
{
return kStatus_Fail;
}
#endif
#if defined(FSL_FEATURE_SOC_EVENT_COUNT) && (FSL_FEATURE_SOC_EVENT_COUNT > 0)
EVENT_UNIT->INTPTEN &= ~(uint32_t)(1 << interrupt);
/* Read back to make sure write finished. */
(void)EVENT_UNIT->INTPTEN;
#else
#if defined(__GIC_PRIO_BITS)
GIC_DisableIRQ(interrupt);
#else
NVIC_DisableIRQ(interrupt);
#endif
#endif
return kStatus_Success;
}
/*!
* @brief Disable the global IRQ
*
* Disable the global interrupt and return the current primask register. User is required to provided the primask
* register for the EnableGlobalIRQ().
*
* @return Current primask value.
*/
static inline uint32_t DisableGlobalIRQ(void)
{
#ifndef __riscv
#if defined(CPSR_I_Msk)
uint32_t cpsr = __get_CPSR() & CPSR_I_Msk;
__disable_irq();
return cpsr;
#else
uint32_t regPrimask = __get_PRIMASK();
__disable_irq();
return regPrimask;
#endif
#else
uint32_t mstatus;
__ASM volatile ("csrrci %0, mstatus, 8" : "=r"(mstatus));
return mstatus;
#endif
}
/*!
* @brief Enaable the global IRQ
*
* Set the primask register with the provided primask value but not just enable the primask. The idea is for the
* convinience of integration of RTOS. some RTOS get its own management mechanism of primask. User is required to
* use the EnableGlobalIRQ() and DisableGlobalIRQ() in pair.
*
* @param primask value of primask register to be restored. The primask value is supposed to be provided by the
* DisableGlobalIRQ().
*/
static inline void EnableGlobalIRQ(uint32_t primask)
{
#ifndef __riscv
#if defined(CPSR_I_Msk)
__set_CPSR((__get_CPSR() & ~CPSR_I_Msk) | primask);
#else
__set_PRIMASK(primask);
#endif
#else
__ASM volatile ("csrw mstatus, %0" : : "r"(primask));
#endif
}
/*!
* @brief install IRQ handler
*
* @param irq IRQ number
* @param irqHandler IRQ handler address
* @return The old IRQ handler address
*/
uint32_t InstallIRQHandler(IRQn_Type irq, uint32_t irqHandler);
#if (defined(FSL_FEATURE_SOC_SYSCON_COUNT) && (FSL_FEATURE_SOC_SYSCON_COUNT > 0))
/*!
* @brief Enable specific interrupt for wake-up from deep-sleep mode.
*
* Enable the interrupt for wake-up from deep sleep mode.
* Some interrupts are typically used in sleep mode only and will not occur during
* deep-sleep mode because relevant clocks are stopped. However, it is possible to enable
* those clocks (significantly increasing power consumption in the reduced power mode),
* making these wake-ups possible.
*
* @note This function also enables the interrupt in the NVIC (EnableIRQ() is called internally).
*
* @param interrupt The IRQ number.
*/
void EnableDeepSleepIRQ(IRQn_Type interrupt);
/*!
* @brief Disable specific interrupt for wake-up from deep-sleep mode.
*
* Disable the interrupt for wake-up from deep sleep mode.
* Some interrupts are typically used in sleep mode only and will not occur during
* deep-sleep mode because relevant clocks are stopped. However, it is possible to enable
* those clocks (significantly increasing power consumption in the reduced power mode),
* making these wake-ups possible.
*
* @note This function also disables the interrupt in the NVIC (DisableIRQ() is called internally).
*
* @param interrupt The IRQ number.
*/
void DisableDeepSleepIRQ(IRQn_Type interrupt);
#endif /* FSL_FEATURE_SOC_SYSCON_COUNT */
#if defined(__cplusplus)
}
#endif
/*! @} */
#endif /* _FSL_COMMON_H_ */

View File

@ -0,0 +1,260 @@
/*
* Copyright (c) 2015-2016, Freescale Semiconductor, Inc.
* Copyright 2016-2017 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include "fsl_crc.h"
/*******************************************************************************
* Definitions
******************************************************************************/
/*! @internal @brief Has data register with name CRC. */
#if defined(FSL_FEATURE_CRC_HAS_CRC_REG) && FSL_FEATURE_CRC_HAS_CRC_REG
#define DATA CRC
#define DATALL CRCLL
#endif
#if defined(CRC_DRIVER_USE_CRC16_CCIT_FALSE_AS_DEFAULT) && CRC_DRIVER_USE_CRC16_CCIT_FALSE_AS_DEFAULT
/* @brief Default user configuration structure for CRC-16-CCITT */
#define CRC_DRIVER_DEFAULT_POLYNOMIAL 0x1021U
/*< CRC-16-CCIT polynomial x**16 + x**12 + x**5 + x**0 */
#define CRC_DRIVER_DEFAULT_SEED 0xFFFFU
/*< Default initial checksum */
#define CRC_DRIVER_DEFAULT_REFLECT_IN false
/*< Default is no transpose */
#define CRC_DRIVER_DEFAULT_REFLECT_OUT false
/*< Default is transpose bytes */
#define CRC_DRIVER_DEFAULT_COMPLEMENT_CHECKSUM false
/*< Default is without complement of CRC data register read data */
#define CRC_DRIVER_DEFAULT_CRC_BITS kCrcBits16
/*< Default is 16-bit CRC protocol */
#define CRC_DRIVER_DEFAULT_CRC_RESULT kCrcFinalChecksum
/*< Default is resutl type is final checksum */
#endif /* CRC_DRIVER_USE_CRC16_CCIT_FALSE_AS_DEFAULT */
/*! @brief CRC type of transpose of read write data */
typedef enum _crc_transpose_type
{
kCrcTransposeNone = 0U, /*! No transpose */
kCrcTransposeBits = 1U, /*! Tranpose bits in bytes */
kCrcTransposeBitsAndBytes = 2U, /*! Transpose bytes and bits in bytes */
kCrcTransposeBytes = 3U, /*! Transpose bytes */
} crc_transpose_type_t;
/*!
* @brief CRC module configuration.
*
* This structure holds the configuration for the CRC module.
*/
typedef struct _crc_module_config
{
uint32_t polynomial; /*!< CRC Polynomial, MSBit first.@n
Example polynomial: 0x1021 = 1_0000_0010_0001 = x^12+x^5+1 */
uint32_t seed; /*!< Starting checksum value */
crc_transpose_type_t readTranspose; /*!< Type of transpose when reading CRC result. */
crc_transpose_type_t writeTranspose; /*!< Type of transpose when writing CRC input data. */
bool complementChecksum; /*!< True if the result shall be complement of the actual checksum. */
crc_bits_t crcBits; /*!< Selects 16- or 32- bit CRC protocol. */
} crc_module_config_t;
/*******************************************************************************
* Code
******************************************************************************/
/*!
* @brief Returns transpose type for CRC protocol reflect in parameter.
*
* This functions helps to set writeTranspose member of crc_config_t structure. Reflect in is CRC protocol parameter.
*
* @param enable True or false for the selected CRC protocol Reflect In (refin) parameter.
*/
static inline crc_transpose_type_t CRC_GetTransposeTypeFromReflectIn(bool enable)
{
return ((enable) ? kCrcTransposeBitsAndBytes : kCrcTransposeBytes);
}
/*!
* @brief Returns transpose type for CRC protocol reflect out parameter.
*
* This functions helps to set readTranspose member of crc_config_t structure. Reflect out is CRC protocol parameter.
*
* @param enable True or false for the selected CRC protocol Reflect Out (refout) parameter.
*/
static inline crc_transpose_type_t CRC_GetTransposeTypeFromReflectOut(bool enable)
{
return ((enable) ? kCrcTransposeBitsAndBytes : kCrcTransposeNone);
}
/*!
* @brief Starts checksum computation.
*
* Configures the CRC module for the specified CRC protocol. @n
* Starts the checksum computation by writing the seed value
*
* @param base CRC peripheral address.
* @param config Pointer to protocol configuration structure.
*/
static void CRC_ConfigureAndStart(CRC_Type *base, const crc_module_config_t *config)
{
uint32_t crcControl;
/* pre-compute value for CRC control registger based on user configuraton without WAS field */
crcControl = 0 | CRC_CTRL_TOT(config->writeTranspose) | CRC_CTRL_TOTR(config->readTranspose) |
CRC_CTRL_FXOR(config->complementChecksum) | CRC_CTRL_TCRC(config->crcBits);
/* make sure the control register is clear - WAS is deasserted, and protocol is set */
base->CTRL = crcControl;
/* write polynomial register */
base->GPOLY = config->polynomial;
/* write pre-computed control register value along with WAS to start checksum computation */
base->CTRL = crcControl | CRC_CTRL_WAS(true);
/* write seed (initial checksum) */
base->DATA = config->seed;
/* deassert WAS by writing pre-computed CRC control register value */
base->CTRL = crcControl;
}
/*!
* @brief Starts final checksum computation.
*
* Configures the CRC module for the specified CRC protocol. @n
* Starts final checksum computation by writing the seed value.
* @note CRC_Get16bitResult() or CRC_Get32bitResult() return final checksum
* (output reflection and xor functions are applied).
*
* @param base CRC peripheral address.
* @param protocolConfig Pointer to protocol configuration structure.
*/
static void CRC_SetProtocolConfig(CRC_Type *base, const crc_config_t *protocolConfig)
{
crc_module_config_t moduleConfig;
/* convert protocol to CRC peripheral module configuration, prepare for final checksum */
moduleConfig.polynomial = protocolConfig->polynomial;
moduleConfig.seed = protocolConfig->seed;
moduleConfig.readTranspose = CRC_GetTransposeTypeFromReflectOut(protocolConfig->reflectOut);
moduleConfig.writeTranspose = CRC_GetTransposeTypeFromReflectIn(protocolConfig->reflectIn);
moduleConfig.complementChecksum = protocolConfig->complementChecksum;
moduleConfig.crcBits = protocolConfig->crcBits;
CRC_ConfigureAndStart(base, &moduleConfig);
}
/*!
* @brief Starts intermediate checksum computation.
*
* Configures the CRC module for the specified CRC protocol. @n
* Starts intermediate checksum computation by writing the seed value.
* @note CRC_Get16bitResult() or CRC_Get32bitResult() return intermediate checksum (raw data register value).
*
* @param base CRC peripheral address.
* @param protocolConfig Pointer to protocol configuration structure.
*/
static void CRC_SetRawProtocolConfig(CRC_Type *base, const crc_config_t *protocolConfig)
{
crc_module_config_t moduleConfig;
/* convert protocol to CRC peripheral module configuration, prepare for intermediate checksum */
moduleConfig.polynomial = protocolConfig->polynomial;
moduleConfig.seed = protocolConfig->seed;
moduleConfig.readTranspose =
kCrcTransposeNone; /* intermediate checksum does no transpose of data register read value */
moduleConfig.writeTranspose = CRC_GetTransposeTypeFromReflectIn(protocolConfig->reflectIn);
moduleConfig.complementChecksum = false; /* intermediate checksum does no xor of data register read value */
moduleConfig.crcBits = protocolConfig->crcBits;
CRC_ConfigureAndStart(base, &moduleConfig);
}
void CRC_Init(CRC_Type *base, const crc_config_t *config)
{
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
/* ungate clock */
CLOCK_EnableClock(kCLOCK_Crc0);
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
/* configure CRC module and write the seed */
if (config->crcResult == kCrcFinalChecksum)
{
CRC_SetProtocolConfig(base, config);
}
else
{
CRC_SetRawProtocolConfig(base, config);
}
}
void CRC_GetDefaultConfig(crc_config_t *config)
{
static const crc_config_t crc16ccit = {
CRC_DRIVER_DEFAULT_POLYNOMIAL, CRC_DRIVER_DEFAULT_SEED,
CRC_DRIVER_DEFAULT_REFLECT_IN, CRC_DRIVER_DEFAULT_REFLECT_OUT,
CRC_DRIVER_DEFAULT_COMPLEMENT_CHECKSUM, CRC_DRIVER_DEFAULT_CRC_BITS,
CRC_DRIVER_DEFAULT_CRC_RESULT,
};
*config = crc16ccit;
}
void CRC_WriteData(CRC_Type *base, const uint8_t *data, size_t dataSize)
{
const uint32_t *data32;
/* 8-bit reads and writes till source address is aligned 4 bytes */
while ((dataSize) && ((uint32_t)data & 3U))
{
base->ACCESS8BIT.DATALL = *data;
data++;
dataSize--;
}
/* use 32-bit reads and writes as long as possible */
data32 = (const uint32_t *)data;
while (dataSize >= sizeof(uint32_t))
{
base->DATA = *data32;
data32++;
dataSize -= sizeof(uint32_t);
}
data = (const uint8_t *)data32;
/* 8-bit reads and writes till end of data buffer */
while (dataSize)
{
base->ACCESS8BIT.DATALL = *data;
data++;
dataSize--;
}
}
uint32_t CRC_Get32bitResult(CRC_Type *base)
{
return base->DATA;
}
uint16_t CRC_Get16bitResult(CRC_Type *base)
{
uint32_t retval;
uint32_t totr; /* type of transpose read bitfield */
retval = base->DATA;
totr = (base->CTRL & CRC_CTRL_TOTR_MASK) >> CRC_CTRL_TOTR_SHIFT;
/* check transpose type to get 16-bit out of 32-bit register */
if (totr >= 2U)
{
/* transpose of bytes for read is set, the result CRC is in CRC_DATA[HU:HL] */
retval &= 0xFFFF0000U;
retval = retval >> 16U;
}
else
{
/* no transpose of bytes for read, the result CRC is in CRC_DATA[LU:LL] */
retval &= 0x0000FFFFU;
}
return (uint16_t)retval;
}

View File

@ -0,0 +1,171 @@
/*
* Copyright (c) 2015-2016, Freescale Semiconductor, Inc.
* Copyright 2016-2017 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef _FSL_CRC_H_
#define _FSL_CRC_H_
#include "fsl_common.h"
/*!
* @addtogroup crc
* @{
*/
/*******************************************************************************
* Definitions
******************************************************************************/
/*! @name Driver version */
/*@{*/
/*! @brief CRC driver version. Version 2.0.1.
*
* Current version: 2.0.1
*
* Change log:
* - Version 2.0.1
* - move DATA and DATALL macro definition from header file to source file
*/
#define FSL_CRC_DRIVER_VERSION (MAKE_VERSION(2, 0, 1))
/*@}*/
#ifndef CRC_DRIVER_CUSTOM_DEFAULTS
/*! @brief Default configuration structure filled by CRC_GetDefaultConfig(). Use CRC16-CCIT-FALSE as defeault. */
#define CRC_DRIVER_USE_CRC16_CCIT_FALSE_AS_DEFAULT 1
#endif
/*! @brief CRC bit width */
typedef enum _crc_bits
{
kCrcBits16 = 0U, /*!< Generate 16-bit CRC code */
kCrcBits32 = 1U /*!< Generate 32-bit CRC code */
} crc_bits_t;
/*! @brief CRC result type */
typedef enum _crc_result
{
kCrcFinalChecksum = 0U, /*!< CRC data register read value is the final checksum.
Reflect out and final xor protocol features are applied. */
kCrcIntermediateChecksum = 1U /*!< CRC data register read value is intermediate checksum (raw value).
Reflect out and final xor protocol feature are not applied.
Intermediate checksum can be used as a seed for CRC_Init()
to continue adding data to this checksum. */
} crc_result_t;
/*!
* @brief CRC protocol configuration.
*
* This structure holds the configuration for the CRC protocol.
*
*/
typedef struct _crc_config
{
uint32_t polynomial; /*!< CRC Polynomial, MSBit first.
Example polynomial: 0x1021 = 1_0000_0010_0001 = x^12+x^5+1 */
uint32_t seed; /*!< Starting checksum value */
bool reflectIn; /*!< Reflect bits on input. */
bool reflectOut; /*!< Reflect bits on output. */
bool complementChecksum; /*!< True if the result shall be complement of the actual checksum. */
crc_bits_t crcBits; /*!< Selects 16- or 32- bit CRC protocol. */
crc_result_t crcResult; /*!< Selects final or intermediate checksum return from CRC_Get16bitResult() or
CRC_Get32bitResult() */
} crc_config_t;
/*******************************************************************************
* API
******************************************************************************/
#if defined(__cplusplus)
extern "C" {
#endif
/*!
* @brief Enables and configures the CRC peripheral module.
*
* This function enables the clock gate in the SIM module for the CRC peripheral.
* It also configures the CRC module and starts a checksum computation by writing the seed.
*
* @param base CRC peripheral address.
* @param config CRC module configuration structure.
*/
void CRC_Init(CRC_Type *base, const crc_config_t *config);
/*!
* @brief Disables the CRC peripheral module.
*
* This function disables the clock gate in the SIM module for the CRC peripheral.
*
* @param base CRC peripheral address.
*/
static inline void CRC_Deinit(CRC_Type *base)
{
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
/* gate clock */
CLOCK_DisableClock(kCLOCK_Crc0);
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
}
/*!
* @brief Loads default values to the CRC protocol configuration structure.
*
* Loads default values to the CRC protocol configuration structure. The default values are as follows.
* @code
* config->polynomial = 0x1021;
* config->seed = 0xFFFF;
* config->reflectIn = false;
* config->reflectOut = false;
* config->complementChecksum = false;
* config->crcBits = kCrcBits16;
* config->crcResult = kCrcFinalChecksum;
* @endcode
*
* @param config CRC protocol configuration structure.
*/
void CRC_GetDefaultConfig(crc_config_t *config);
/*!
* @brief Writes data to the CRC module.
*
* Writes input data buffer bytes to the CRC data register.
* The configured type of transpose is applied.
*
* @param base CRC peripheral address.
* @param data Input data stream, MSByte in data[0].
* @param dataSize Size in bytes of the input data buffer.
*/
void CRC_WriteData(CRC_Type *base, const uint8_t *data, size_t dataSize);
/*!
* @brief Reads the 32-bit checksum from the CRC module.
*
* Reads the CRC data register (either an intermediate or the final checksum).
* The configured type of transpose and complement is applied.
*
* @param base CRC peripheral address.
* @return An intermediate or the final 32-bit checksum, after configured transpose and complement operations.
*/
uint32_t CRC_Get32bitResult(CRC_Type *base);
/*!
* @brief Reads a 16-bit checksum from the CRC module.
*
* Reads the CRC data register (either an intermediate or the final checksum).
* The configured type of transpose and complement is applied.
*
* @param base CRC peripheral address.
* @return An intermediate or the final 16-bit checksum, after configured transpose and complement operations.
*/
uint16_t CRC_Get16bitResult(CRC_Type *base);
#if defined(__cplusplus)
}
#endif
/*!
*@}
*/
#endif /* _FSL_CRC_H_ */

View File

@ -0,0 +1,116 @@
/*
* Copyright (c) 2016, Freescale Semiconductor, Inc.
* Copyright 2016-2017 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include "fsl_dac.h"
/*******************************************************************************
* Prototypes
******************************************************************************/
/*!
* @brief Get instance number for DAC module.
*
* @param base DAC peripheral base address
*/
static uint32_t DAC_GetInstance(LPDAC_Type *base);
/*******************************************************************************
* Variables
******************************************************************************/
/*! @brief Pointers to DAC bases for each instance. */
static LPDAC_Type *const s_dacBases[] = LPDAC_BASE_PTRS;
/*! @brief Pointers to DAC clocks for each instance. */
static const clock_ip_name_t s_dacClocks[] = LPDAC_CLOCKS;
/*******************************************************************************
* Code
******************************************************************************/
static uint32_t DAC_GetInstance(LPDAC_Type *base)
{
uint32_t instance;
/* Find the instance index from base address mappings. */
for (instance = 0; instance < ARRAY_SIZE(s_dacBases); instance++)
{
if (s_dacBases[instance] == base)
{
break;
}
}
assert(instance < ARRAY_SIZE(s_dacBases));
return instance;
}
void DAC_Init(LPDAC_Type *base, const dac_config_t *config)
{
assert(NULL != config);
uint32_t tmp32 = 0U;
/* Enable the clock. */
CLOCK_EnableClock(s_dacClocks[DAC_GetInstance(base)]);
/* Reset the logic. */
DAC_SetReset(base, kDAC_ResetLogic);
DAC_ClearReset(base, kDAC_ResetLogic);
/* Reset the FIFO. */
DAC_SetReset(base, kDAC_ResetFIFO);
DAC_ClearReset(base, kDAC_ResetFIFO);
/* Configuration. */
if (kDAC_FIFOTriggerBySoftwareMode == config->fifoTriggerMode)
{
tmp32 |= LPDAC_GCR_TRGSEL_MASK; /* Software trigger. */
}
switch (config->fifoWorkMode)
{
case kDAC_FIFOWorkAsNormalMode: /* Normal FIFO. */
tmp32 |= LPDAC_GCR_FIFOEN_MASK;
break;
case kDAC_FIFOWorkAsSwingMode:
tmp32 |= LPDAC_GCR_FIFOEN_MASK | LPDAC_GCR_SWMD_MASK; /* Enable swing mode. */
break;
default: /* kDAC_FIFODisabled. */
break;
}
if (config->enableLowPowerMode)
{
tmp32 |= LPDAC_GCR_LPEN_MASK; /* Enable low power. */
}
if (kDAC_ReferenceVoltageSourceAlt2 == config->referenceVoltageSource)
{
tmp32 |= LPDAC_GCR_DACRFS_MASK;
}
base->GCR = tmp32;
base->FCR = LPDAC_FCR_WML(config->fifoWatermarkLevel);
/* Now, the DAC is disabled. It needs to be enabled in application. */
}
void DAC_GetDefaultConfig(dac_config_t *config)
{
assert(config != NULL);
config->fifoWatermarkLevel = 0U;
config->fifoTriggerMode = kDAC_FIFOTriggerByHardwareMode;
config->fifoWorkMode = kDAC_FIFODisabled;
config->enableLowPowerMode = false;
config->referenceVoltageSource = kDAC_ReferenceVoltageSourceAlt1;
}
void DAC_Deinit(LPDAC_Type *base)
{
/* Disable the module. */
DAC_Enable(base, false);
/* Disable the clock. */
CLOCK_DisableClock(s_dacClocks[DAC_GetInstance(base)]);
}

View File

@ -0,0 +1,381 @@
/*
* Copyright (c) 2016, Freescale Semiconductor, Inc.
* Copyright 2016-2017 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef _FSL_DAC_H_
#define _FSL_DAC_H_
#include "fsl_common.h"
/*!
* @addtogroup dac
* @{
*/
/*! @file */
/*******************************************************************************
* Definitions
******************************************************************************/
/*! @name Driver version */
/*@{*/
/*! @brief DAC driver version 2.0.0. */
#define FSL_DAC_DRIVER_VERSION (MAKE_VERSION(2, 0, 0))
/*@}*/
/*!
* @brief DAC reset control.
*/
enum _dac_reset_control
{
kDAC_ResetFIFO = LPDAC_RCR_FIFORST_MASK, /*!< Resets the FIFO pointers and flags. */
kDAC_ResetLogic = LPDAC_RCR_SWRST_MASK, /*!< Resets all DAC registers and internal logic. */
};
/*!
* @brief DAC interrupts.
*/
enum _dac_interrupt_enable
{
kDAC_FIFOFullInterruptEnable = LPDAC_IER_FULL_IE_MASK, /*!< FIFO full interrupt enable. */
kDAC_FIFOEmptyInterruptEnable = LPDAC_IER_EMPTY_IE_MASK, /*!< FIFO empty interrupt enable. */
kDAC_FIFOWatermarkInterruptEnable = LPDAC_IER_WM_IE_MASK, /*!< FIFO watermark interrupt enable. */
kDAC_SwingBackInterruptEnable = LPDAC_IER_SWBK_IE_MASK, /*!< Swing back one cycle complete interrupt enable. */
kDAC_FIFOOverflowInterruptEnable = LPDAC_IER_OF_IE_MASK, /*!< FIFO overflow interrupt enable. */
kDAC_FIFOUnderflowInterruptEnable = LPDAC_IER_UF_IE_MASK, /*!< FIFO underflow interrupt enable. */
};
/*!
* @brief DAC DMA switchers.
*/
enum _dac_dma_enable
{
kDAC_FIFOEmptyDMAEnable = LPDAC_DER_EMPTY_DMAEN_MASK, /*!< FIFO empty DMA enable. */
kDAC_FIFOWatermarkDMAEnable = LPDAC_DER_WM_DMAEN_MASK, /*!< FIFO watermark DMA enable. */
};
/*!
* @brief DAC status flags.
*/
enum _dac_status_flags
{
kDAC_FIFOUnderflowFlag = LPDAC_FSR_UF_MASK, /*!< This flag means that there is a new trigger after the buffer is
empty. The FIFO read pointer will not
increase in this case and the data sent to DAC analog conversion will not changed. This flag is cleared by writing a 1
to it. */
kDAC_FIFOOverflowFlag = LPDAC_FSR_OF_MASK, /*!< This flag indicates that data is intended to write into FIFO after the
buffer is full. The writer pointer will
not increase in this case. The extra data will not be written into the FIFO. This flag is cleared by writing a 1 to it.
*/
kDAC_FIFOSwingBackFlag = LPDAC_FSR_SWBK_MASK, /*!< This flag indicates that the DAC has completed one period of
conversion in swing back mode. It means
that the read pointer has increased to the top (write pointer) once and then decreased to zero once. For
example, after three data is written to FIFO, the writer pointer is now 3. Then, if continually triggered, the
read pointer will swing like: 0-1-2-1-0-1-2-, and so on. After the fourth trigger, the flag is set. This flag is
cleared by writing a 1 to it. */
kDAC_FIFOWatermarkFlag = LPDAC_FSR_WM_MASK, /*!< This field is set if the remaining data in FIFO is less than or equal
to the setting value of wartermark. By writing data into
FIFO by DMA or CPU, this flag is cleared automatically when the data in FIFO is more than the setting value of
watermark. */
kDAC_FIFOEmptyFlag = LPDAC_FSR_EMPTY_MASK, /*!< FIFO empty flag. */
kDAC_FIFOFullFlag = LPDAC_FSR_FULL_MASK, /*!< FIFO full flag. */
};
/*!
* @brief DAC FIFO trigger mode.
*/
typedef enum _dac_fifo_trigger_mode
{
kDAC_FIFOTriggerByHardwareMode = 0U, /*!< Buffer would be triggered by hardware. */
kDAC_FIFOTriggerBySoftwareMode = 1U, /*!< Buffer would be triggered by software. */
} dac_fifo_trigger_mode_t;
/*!
* @brief DAC FIFO work mode.
*/
typedef enum _dac_fifo_work_mode
{
kDAC_FIFODisabled = 0U, /*!< FIFO mode is disabled and buffer mode is enabled. Any data written to DATA[DATA] goes
to buffer then goes to conversion. */
kDAC_FIFOWorkAsNormalMode = 1U, /*!< FIFO mode is enabled. Data will be first read from FIFO to buffer then goes to
conversion. */
kDAC_FIFOWorkAsSwingMode = 2U, /*!< In swing mode, the read pointer swings between the writer pointer and zero. That
is, the trigger increases the read pointer till reach the writer pointer and
decreases the read pointer till zero, and so on. The FIFO empty/full/watermark
flag will not update during swing back mode. */
} dac_fifo_work_mode_t;
/*!
* @brief DAC reference voltage source.
*/
typedef enum _dac_reference_voltage_source
{
kDAC_ReferenceVoltageSourceAlt1 = 0U, /*!< The DAC selects VREFH_INT as the reference voltage. */
kDAC_ReferenceVoltageSourceAlt2 = 1U, /*!< The DAC selects VREFH_EXT as the reference voltage. */
} dac_reference_voltage_source_t;
/*!
* @brief DAC configuration structure.
*/
typedef struct _dac_config
{
uint32_t fifoWatermarkLevel; /*!< FIFO's watermark, the max value can be the hardware FIFO size. */
dac_fifo_trigger_mode_t fifoTriggerMode; /*!< Select the trigger mode for FIFO. */
dac_fifo_work_mode_t fifoWorkMode; /*!< Select the work mode for FIFO. */
bool enableLowPowerMode; /*!< Enable the low power mode. */
dac_reference_voltage_source_t referenceVoltageSource; /*!< Select the reference voltage source. */
} dac_config_t;
/*******************************************************************************
* API
******************************************************************************/
#if defined(__cplusplus)
extern "C" {
#endif
/*!
* @name Initialization and de-initialization
* @{
*/
/*!
* @brief Initialize the DAC module with common configuartion.
*
* The clock will be enabled in this function.
*
* @param base DAC peripheral base address.
* @param config Pointer to configuration structure.
*/
void DAC_Init(LPDAC_Type *base, const dac_config_t *config);
/*!
* @brief Get the default settings for initialization's configuration.
*
* This function initializes the user configuration structure to a default value. The default values are:
* @code
* config->fifoWatermarkLevel = 0U;
* config->fifoTriggerMode = kDAC_FIFOTriggerByHardwareMode;
* config->fifoWorkMode = kDAC_FIFODisabled;
* config->enableLowPowerMode = false;
* config->referenceVoltageSource = kDAC_ReferenceVoltageSourceAlt1;
* @endcode
*
* @param config Pointer to configuration structure.
* @param
*/
void DAC_GetDefaultConfig(dac_config_t *config);
/*!
* @brief De-initialize the DAC module.
*
* The clock will be disabled in this function.
*
* @param base DAC peripheral base address.
* @param
*/
void DAC_Deinit(LPDAC_Type *base);
/*!
* @brief Assert the reset control to part hardware.
*
* This fucntion is to assert the reset control to part hardware. Responding part hardware would remain reset untill
* cleared by software.
*
* @param base DAC peripheral base address.
* @param mask The reset control mask, see to #_dac_reset_control_t.
*/
static inline void DAC_SetReset(LPDAC_Type *base, uint32_t mask)
{
base->RCR |= mask;
}
/*!
* @brief Clear the reset control to part hardware.
*
* This fucntion is to clear the reset control to part hardware. Responding part hardware would work after the reset
* control is cleared by software.
*
* @param base DAC peripheral base address.
* @param mask The reset control mask, see to #_dac_reset_control_t.
*/
static inline void DAC_ClearReset(LPDAC_Type *base, uint32_t mask)
{
base->RCR &= ~mask;
}
/*!
* @brief Enable the DAC hardware system or not.
*
* This function is to start the Programmable Reference Generator operation or not.
*
* @param base DAC peripheral base address.
* @param enable Assertion of indicated event.
*/
static inline void DAC_Enable(LPDAC_Type *base, bool enable)
{
if (enable)
{
base->GCR |= LPDAC_GCR_DACEN_MASK;
}
else
{
base->GCR &= ~LPDAC_GCR_DACEN_MASK;
}
}
/* @} */
/*!
* @name Interrupts
* @{
*/
/*!
* @brief Enable the interrupts.
*
* @param base DAC peripheral base address.
* @param mask Mask value of indicated interrupt events. See to #_dac_interrupt_enable.
*/
static inline void DAC_EnableInterrupts(LPDAC_Type *base, uint32_t mask)
{
base->IER |= mask;
}
/*!
* @brief Disable the interrupts.
*
* @param base DAC peripheral base address.
* @param mask Mask value of indicated interrupt events. See to #_dac_interrupt_enable.
*/
static inline void DAC_DisableInterrupts(LPDAC_Type *base, uint32_t mask)
{
base->IER &= ~mask;
}
/* @} */
/*!
* @name DMA control
* @{
*/
/*!
* @brief Enable the DMA switchers or not.
*
* @param base DAC peripheral base address.
* @param mask Mask value of indicated DMA requeset. See to #_dac_dma_enable.
* @param enable Enable the DMA or not.
*/
static inline void DAC_EnableDMA(LPDAC_Type *base, uint32_t mask, bool enable)
{
if (enable)
{
base->DER |= mask;
}
else
{
base->DER &= ~mask;
}
}
/* @} */
/*!
* @name Status flags
* @{
*/
/*!
* @brief Get status flags of DAC module.
*
* @param base DAC peripheral base address.
* @return Mask value of status flags. See to #_dac_status_flags.
*/
static inline uint32_t DAC_GetStatusFlags(LPDAC_Type *base)
{
return base->FSR;
}
/*!
* @brief Clear status flags of DAC module.
*
* @param base DAC peripheral base address.
* @param flags Mask value of status flags to be cleared. See to #_dac_status_flags.
*/
static inline void DAC_ClearStatusFlags(LPDAC_Type *base, uint32_t flags)
{
base->FSR = flags;
}
/* @} */
/*!
* @name Functional feature
* @{
*/
/*!
* @brief Set data into the entry of FIFO buffer.
*
* @param base DAC peripheral base address.
* @param value Setting value into FIFO buffer.
*/
static inline void DAC_SetData(LPDAC_Type *base, uint32_t value)
{
base->DATA = LPDAC_DATA_DATA(value);
}
/*!
* @brief Get the value of the FIFO write pointer.
*
* @param base DAC peripheral base address.
* @return Current value of the FIFO write pointer.
*/
static inline uint32_t DAC_GetFIFOWritePointer(LPDAC_Type *base)
{
return (LPDAC_FPR_FIFO_WPT_MASK & base->FPR) >> LPDAC_FPR_FIFO_WPT_SHIFT;
}
/*!
* @brief Get the value of the FIFO read pointer.
*
* @param base DAC peripheral base address.
* @return Current value of the FIFO read pointer.
*/
static inline uint32_t DAC_GetFIFOReadPointer(LPDAC_Type *base)
{
return (LPDAC_FPR_FIFO_RPT_MASK & base->FPR) >> LPDAC_FPR_FIFO_RPT_SHIFT;
}
/*!
* @brief Do software trigger to FIFO when in software mode.
*
* @param base DAC peripheral base address.
*/
static inline void DAC_DoSoftwareTriggerFIFO(LPDAC_Type *base)
{
base->TCR = LPDAC_TCR_SWTRG_MASK;
}
/* @} */
#if defined(__cplusplus)
}
#endif
/*!
* @}
*/
#endif /* _FSL_DAC12_H_ */

View File

@ -0,0 +1,71 @@
/*
* Copyright (c) 2015, Freescale Semiconductor, Inc.
* Copyright 2016-2017 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include "fsl_dmamux.h"
/*******************************************************************************
* Definitions
******************************************************************************/
/*******************************************************************************
* Prototypes
******************************************************************************/
/*!
* @brief Get instance number for DMAMUX.
*
* @param base DMAMUX peripheral base address.
*/
static uint32_t DMAMUX_GetInstance(DMAMUX_Type *base);
/*******************************************************************************
* Variables
******************************************************************************/
/*! @brief Array to map DMAMUX instance number to base pointer. */
static DMAMUX_Type *const s_dmamuxBases[] = DMAMUX_BASE_PTRS;
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
/*! @brief Array to map DMAMUX instance number to clock name. */
static const clock_ip_name_t s_dmamuxClockName[] = DMAMUX_CLOCKS;
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
/*******************************************************************************
* Code
******************************************************************************/
static uint32_t DMAMUX_GetInstance(DMAMUX_Type *base)
{
uint32_t instance;
/* Find the instance index from base address mappings. */
for (instance = 0; instance < ARRAY_SIZE(s_dmamuxBases); instance++)
{
if (s_dmamuxBases[instance] == base)
{
break;
}
}
assert(instance < ARRAY_SIZE(s_dmamuxBases));
return instance;
}
void DMAMUX_Init(DMAMUX_Type *base)
{
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
CLOCK_EnableClock(s_dmamuxClockName[DMAMUX_GetInstance(base)]);
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
}
void DMAMUX_Deinit(DMAMUX_Type *base)
{
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
CLOCK_DisableClock(s_dmamuxClockName[DMAMUX_GetInstance(base)]);
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
}

View File

@ -0,0 +1,178 @@
/*
* Copyright (c) 2015, Freescale Semiconductor, Inc.
* Copyright 2016-2017 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef _FSL_DMAMUX_H_
#define _FSL_DMAMUX_H_
#include "fsl_common.h"
/*!
* @addtogroup dmamux
* @{
*/
/*******************************************************************************
* Definitions
******************************************************************************/
/*! @name Driver version */
/*@{*/
/*! @brief DMAMUX driver version 2.0.2. */
#define FSL_DMAMUX_DRIVER_VERSION (MAKE_VERSION(2, 0, 2))
/*@}*/
/*******************************************************************************
* API
******************************************************************************/
#if defined(__cplusplus)
extern "C" {
#endif /* __cplusplus */
/*!
* @name DMAMUX Initialization and de-initialization
* @{
*/
/*!
* @brief Initializes the DMAMUX peripheral.
*
* This function ungates the DMAMUX clock.
*
* @param base DMAMUX peripheral base address.
*
*/
void DMAMUX_Init(DMAMUX_Type *base);
/*!
* @brief Deinitializes the DMAMUX peripheral.
*
* This function gates the DMAMUX clock.
*
* @param base DMAMUX peripheral base address.
*/
void DMAMUX_Deinit(DMAMUX_Type *base);
/* @} */
/*!
* @name DMAMUX Channel Operation
* @{
*/
/*!
* @brief Enables the DMAMUX channel.
*
* This function enables the DMAMUX channel.
*
* @param base DMAMUX peripheral base address.
* @param channel DMAMUX channel number.
*/
static inline void DMAMUX_EnableChannel(DMAMUX_Type *base, uint32_t channel)
{
assert(channel < FSL_FEATURE_DMAMUX_MODULE_CHANNEL);
base->CHCFG[channel] |= DMAMUX_CHCFG_ENBL_MASK;
}
/*!
* @brief Disables the DMAMUX channel.
*
* This function disables the DMAMUX channel.
*
* @note The user must disable the DMAMUX channel before configuring it.
* @param base DMAMUX peripheral base address.
* @param channel DMAMUX channel number.
*/
static inline void DMAMUX_DisableChannel(DMAMUX_Type *base, uint32_t channel)
{
assert(channel < FSL_FEATURE_DMAMUX_MODULE_CHANNEL);
base->CHCFG[channel] &= ~DMAMUX_CHCFG_ENBL_MASK;
}
/*!
* @brief Configures the DMAMUX channel source.
*
* @param base DMAMUX peripheral base address.
* @param channel DMAMUX channel number.
* @param source Channel source, which is used to trigger the DMA transfer.
*/
static inline void DMAMUX_SetSource(DMAMUX_Type *base, uint32_t channel, uint32_t source)
{
assert(channel < FSL_FEATURE_DMAMUX_MODULE_CHANNEL);
base->CHCFG[channel] = ((base->CHCFG[channel] & ~DMAMUX_CHCFG_SOURCE_MASK) | DMAMUX_CHCFG_SOURCE(source));
}
#if defined(FSL_FEATURE_DMAMUX_HAS_TRIG) && FSL_FEATURE_DMAMUX_HAS_TRIG > 0U
/*!
* @brief Enables the DMAMUX period trigger.
*
* This function enables the DMAMUX period trigger feature.
*
* @param base DMAMUX peripheral base address.
* @param channel DMAMUX channel number.
*/
static inline void DMAMUX_EnablePeriodTrigger(DMAMUX_Type *base, uint32_t channel)
{
assert(channel < FSL_FEATURE_DMAMUX_MODULE_CHANNEL);
base->CHCFG[channel] |= DMAMUX_CHCFG_TRIG_MASK;
}
/*!
* @brief Disables the DMAMUX period trigger.
*
* This function disables the DMAMUX period trigger.
*
* @param base DMAMUX peripheral base address.
* @param channel DMAMUX channel number.
*/
static inline void DMAMUX_DisablePeriodTrigger(DMAMUX_Type *base, uint32_t channel)
{
assert(channel < FSL_FEATURE_DMAMUX_MODULE_CHANNEL);
base->CHCFG[channel] &= ~DMAMUX_CHCFG_TRIG_MASK;
}
#endif /* FSL_FEATURE_DMAMUX_HAS_TRIG */
#if (defined(FSL_FEATURE_DMAMUX_HAS_A_ON) && FSL_FEATURE_DMAMUX_HAS_A_ON)
/*!
* @brief Enables the DMA channel to be always ON.
*
* This function enables the DMAMUX channel always ON feature.
*
* @param base DMAMUX peripheral base address.
* @param channel DMAMUX channel number.
* @param enable Switcher of the always ON feature. "true" means enabled, "false" means disabled.
*/
static inline void DMAMUX_EnableAlwaysOn(DMAMUX_Type *base, uint32_t channel, bool enable)
{
assert(channel < FSL_FEATURE_DMAMUX_MODULE_CHANNEL);
if (enable)
{
base->CHCFG[channel] |= DMAMUX_CHCFG_A_ON_MASK;
}
else
{
base->CHCFG[channel] &= ~DMAMUX_CHCFG_A_ON_MASK;
}
}
#endif /* FSL_FEATURE_DMAMUX_HAS_A_ON */
/* @} */
#if defined(__cplusplus)
}
#endif /* __cplusplus */
/* @} */
#endif /* _FSL_DMAMUX_H_ */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,897 @@
/*
* Copyright (c) 2015, Freescale Semiconductor, Inc.
* Copyright 2016-2017 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef _FSL_EDMA_H_
#define _FSL_EDMA_H_
#include "fsl_common.h"
/*!
* @addtogroup edma
* @{
*/
/*******************************************************************************
* Definitions
******************************************************************************/
/*! @name Driver version */
/*@{*/
/*! @brief eDMA driver version */
#define FSL_EDMA_DRIVER_VERSION (MAKE_VERSION(2, 1, 1)) /*!< Version 2.1.1. */
/*@}*/
/*! @brief Compute the offset unit from DCHPRI3 */
#define DMA_DCHPRI_INDEX(channel) (((channel) & ~0x03U) | (3 - ((channel)&0x03U)))
/*! @brief Get the pointer of DCHPRIn */
#define DMA_DCHPRIn(base, channel) ((volatile uint8_t *)&(base->DCHPRI3))[DMA_DCHPRI_INDEX(channel)]
/*! @brief eDMA transfer configuration */
typedef enum _edma_transfer_size
{
kEDMA_TransferSize1Bytes = 0x0U, /*!< Source/Destination data transfer size is 1 byte every time */
kEDMA_TransferSize2Bytes = 0x1U, /*!< Source/Destination data transfer size is 2 bytes every time */
kEDMA_TransferSize4Bytes = 0x2U, /*!< Source/Destination data transfer size is 4 bytes every time */
kEDMA_TransferSize16Bytes = 0x4U, /*!< Source/Destination data transfer size is 16 bytes every time */
kEDMA_TransferSize32Bytes = 0x5U, /*!< Source/Destination data transfer size is 32 bytes every time */
} edma_transfer_size_t;
/*! @brief eDMA modulo configuration */
typedef enum _edma_modulo
{
kEDMA_ModuloDisable = 0x0U, /*!< Disable modulo */
kEDMA_Modulo2bytes, /*!< Circular buffer size is 2 bytes. */
kEDMA_Modulo4bytes, /*!< Circular buffer size is 4 bytes. */
kEDMA_Modulo8bytes, /*!< Circular buffer size is 8 bytes. */
kEDMA_Modulo16bytes, /*!< Circular buffer size is 16 bytes. */
kEDMA_Modulo32bytes, /*!< Circular buffer size is 32 bytes. */
kEDMA_Modulo64bytes, /*!< Circular buffer size is 64 bytes. */
kEDMA_Modulo128bytes, /*!< Circular buffer size is 128 bytes. */
kEDMA_Modulo256bytes, /*!< Circular buffer size is 256 bytes. */
kEDMA_Modulo512bytes, /*!< Circular buffer size is 512 bytes. */
kEDMA_Modulo1Kbytes, /*!< Circular buffer size is 1 K bytes. */
kEDMA_Modulo2Kbytes, /*!< Circular buffer size is 2 K bytes. */
kEDMA_Modulo4Kbytes, /*!< Circular buffer size is 4 K bytes. */
kEDMA_Modulo8Kbytes, /*!< Circular buffer size is 8 K bytes. */
kEDMA_Modulo16Kbytes, /*!< Circular buffer size is 16 K bytes. */
kEDMA_Modulo32Kbytes, /*!< Circular buffer size is 32 K bytes. */
kEDMA_Modulo64Kbytes, /*!< Circular buffer size is 64 K bytes. */
kEDMA_Modulo128Kbytes, /*!< Circular buffer size is 128 K bytes. */
kEDMA_Modulo256Kbytes, /*!< Circular buffer size is 256 K bytes. */
kEDMA_Modulo512Kbytes, /*!< Circular buffer size is 512 K bytes. */
kEDMA_Modulo1Mbytes, /*!< Circular buffer size is 1 M bytes. */
kEDMA_Modulo2Mbytes, /*!< Circular buffer size is 2 M bytes. */
kEDMA_Modulo4Mbytes, /*!< Circular buffer size is 4 M bytes. */
kEDMA_Modulo8Mbytes, /*!< Circular buffer size is 8 M bytes. */
kEDMA_Modulo16Mbytes, /*!< Circular buffer size is 16 M bytes. */
kEDMA_Modulo32Mbytes, /*!< Circular buffer size is 32 M bytes. */
kEDMA_Modulo64Mbytes, /*!< Circular buffer size is 64 M bytes. */
kEDMA_Modulo128Mbytes, /*!< Circular buffer size is 128 M bytes. */
kEDMA_Modulo256Mbytes, /*!< Circular buffer size is 256 M bytes. */
kEDMA_Modulo512Mbytes, /*!< Circular buffer size is 512 M bytes. */
kEDMA_Modulo1Gbytes, /*!< Circular buffer size is 1 G bytes. */
kEDMA_Modulo2Gbytes, /*!< Circular buffer size is 2 G bytes. */
} edma_modulo_t;
/*! @brief Bandwidth control */
typedef enum _edma_bandwidth
{
kEDMA_BandwidthStallNone = 0x0U, /*!< No eDMA engine stalls. */
kEDMA_BandwidthStall4Cycle = 0x2U, /*!< eDMA engine stalls for 4 cycles after each read/write. */
kEDMA_BandwidthStall8Cycle = 0x3U, /*!< eDMA engine stalls for 8 cycles after each read/write. */
} edma_bandwidth_t;
/*! @brief Channel link type */
typedef enum _edma_channel_link_type
{
kEDMA_LinkNone = 0x0U, /*!< No channel link */
kEDMA_MinorLink, /*!< Channel link after each minor loop */
kEDMA_MajorLink, /*!< Channel link while major loop count exhausted */
} edma_channel_link_type_t;
/*!@brief eDMA channel status flags. */
enum _edma_channel_status_flags
{
kEDMA_DoneFlag = 0x1U, /*!< DONE flag, set while transfer finished, CITER value exhausted*/
kEDMA_ErrorFlag = 0x2U, /*!< eDMA error flag, an error occurred in a transfer */
kEDMA_InterruptFlag = 0x4U, /*!< eDMA interrupt flag, set while an interrupt occurred of this channel */
};
/*! @brief eDMA channel error status flags. */
enum _edma_error_status_flags
{
kEDMA_DestinationBusErrorFlag = DMA_ES_DBE_MASK, /*!< Bus error on destination address */
kEDMA_SourceBusErrorFlag = DMA_ES_SBE_MASK, /*!< Bus error on the source address */
kEDMA_ScatterGatherErrorFlag = DMA_ES_SGE_MASK, /*!< Error on the Scatter/Gather address, not 32byte aligned. */
kEDMA_NbytesErrorFlag = DMA_ES_NCE_MASK, /*!< NBYTES/CITER configuration error */
kEDMA_DestinationOffsetErrorFlag = DMA_ES_DOE_MASK, /*!< Destination offset not aligned with destination size */
kEDMA_DestinationAddressErrorFlag = DMA_ES_DAE_MASK, /*!< Destination address not aligned with destination size */
kEDMA_SourceOffsetErrorFlag = DMA_ES_SOE_MASK, /*!< Source offset not aligned with source size */
kEDMA_SourceAddressErrorFlag = DMA_ES_SAE_MASK, /*!< Source address not aligned with source size*/
kEDMA_ErrorChannelFlag = DMA_ES_ERRCHN_MASK, /*!< Error channel number of the cancelled channel number */
kEDMA_ChannelPriorityErrorFlag = DMA_ES_CPE_MASK, /*!< Channel priority is not unique. */
kEDMA_TransferCanceledFlag = DMA_ES_ECX_MASK, /*!< Transfer cancelled */
#if defined(FSL_FEATURE_EDMA_CHANNEL_GROUP_COUNT) && FSL_FEATURE_EDMA_CHANNEL_GROUP_COUNT > 1
kEDMA_GroupPriorityErrorFlag = DMA_ES_GPE_MASK, /*!< Group priority is not unique. */
#endif
kEDMA_ValidFlag = DMA_ES_VLD_MASK, /*!< No error occurred, this bit is 0. Otherwise, it is 1. */
};
/*! @brief eDMA interrupt source */
typedef enum _edma_interrupt_enable
{
kEDMA_ErrorInterruptEnable = 0x1U, /*!< Enable interrupt while channel error occurs. */
kEDMA_MajorInterruptEnable = DMA_CSR_INTMAJOR_MASK, /*!< Enable interrupt while major count exhausted. */
kEDMA_HalfInterruptEnable = DMA_CSR_INTHALF_MASK, /*!< Enable interrupt while major count to half value. */
} edma_interrupt_enable_t;
/*! @brief eDMA transfer type */
typedef enum _edma_transfer_type
{
kEDMA_MemoryToMemory = 0x0U, /*!< Transfer from memory to memory */
kEDMA_PeripheralToMemory, /*!< Transfer from peripheral to memory */
kEDMA_MemoryToPeripheral, /*!< Transfer from memory to peripheral */
} edma_transfer_type_t;
/*! @brief eDMA transfer status */
enum _edma_transfer_status
{
kStatus_EDMA_QueueFull = MAKE_STATUS(kStatusGroup_EDMA, 0), /*!< TCD queue is full. */
kStatus_EDMA_Busy = MAKE_STATUS(kStatusGroup_EDMA, 1), /*!< Channel is busy and can't handle the
transfer request. */
};
/*! @brief eDMA global configuration structure.*/
typedef struct _edma_config
{
bool enableContinuousLinkMode; /*!< Enable (true) continuous link mode. Upon minor loop completion, the channel
activates again if that channel has a minor loop channel link enabled and
the link channel is itself. */
bool enableHaltOnError; /*!< Enable (true) transfer halt on error. Any error causes the HALT bit to set.
Subsequently, all service requests are ignored until the HALT bit is cleared.*/
bool enableRoundRobinArbitration; /*!< Enable (true) round robin channel arbitration method or fixed priority
arbitration is used for channel selection */
bool enableDebugMode; /*!< Enable(true) eDMA debug mode. When in debug mode, the eDMA stalls the start of
a new channel. Executing channels are allowed to complete. */
} edma_config_t;
/*!
* @brief eDMA transfer configuration
*
* This structure configures the source/destination transfer attribute.
*/
typedef struct _edma_transfer_config
{
uint32_t srcAddr; /*!< Source data address. */
uint32_t destAddr; /*!< Destination data address. */
edma_transfer_size_t srcTransferSize; /*!< Source data transfer size. */
edma_transfer_size_t destTransferSize; /*!< Destination data transfer size. */
int16_t srcOffset; /*!< Sign-extended offset applied to the current source address to
form the next-state value as each source read is completed. */
int16_t destOffset; /*!< Sign-extended offset applied to the current destination address to
form the next-state value as each destination write is completed. */
uint32_t minorLoopBytes; /*!< Bytes to transfer in a minor loop*/
uint32_t majorLoopCounts; /*!< Major loop iteration count. */
} edma_transfer_config_t;
/*! @brief eDMA channel priority configuration */
typedef struct _edma_channel_Preemption_config
{
bool enableChannelPreemption; /*!< If true: a channel can be suspended by other channel with higher priority */
bool enablePreemptAbility; /*!< If true: a channel can suspend other channel with low priority */
uint8_t channelPriority; /*!< Channel priority */
} edma_channel_Preemption_config_t;
/*! @brief eDMA minor offset configuration */
typedef struct _edma_minor_offset_config
{
bool enableSrcMinorOffset; /*!< Enable(true) or Disable(false) source minor loop offset. */
bool enableDestMinorOffset; /*!< Enable(true) or Disable(false) destination minor loop offset. */
uint32_t minorOffset; /*!< Offset for a minor loop mapping. */
} edma_minor_offset_config_t;
/*!
* @brief eDMA TCD.
*
* This structure is same as TCD register which is described in reference manual,
* and is used to configure the scatter/gather feature as a next hardware TCD.
*/
typedef struct _edma_tcd
{
__IO uint32_t SADDR; /*!< SADDR register, used to save source address */
__IO uint16_t SOFF; /*!< SOFF register, save offset bytes every transfer */
__IO uint16_t ATTR; /*!< ATTR register, source/destination transfer size and modulo */
__IO uint32_t NBYTES; /*!< Nbytes register, minor loop length in bytes */
__IO uint32_t SLAST; /*!< SLAST register */
__IO uint32_t DADDR; /*!< DADDR register, used for destination address */
__IO uint16_t DOFF; /*!< DOFF register, used for destination offset */
__IO uint16_t CITER; /*!< CITER register, current minor loop numbers, for unfinished minor loop.*/
__IO uint32_t DLAST_SGA; /*!< DLASTSGA register, next stcd address used in scatter-gather mode */
__IO uint16_t CSR; /*!< CSR register, for TCD control status */
__IO uint16_t BITER; /*!< BITER register, begin minor loop count. */
} edma_tcd_t;
/*! @brief Callback for eDMA */
struct _edma_handle;
/*! @brief Define callback function for eDMA. */
typedef void (*edma_callback)(struct _edma_handle *handle, void *userData, bool transferDone, uint32_t tcds);
/*! @brief eDMA transfer handle structure */
typedef struct _edma_handle
{
edma_callback callback; /*!< Callback function for major count exhausted. */
void *userData; /*!< Callback function parameter. */
DMA_Type *base; /*!< eDMA peripheral base address. */
edma_tcd_t *tcdPool; /*!< Pointer to memory stored TCDs. */
uint8_t channel; /*!< eDMA channel number. */
volatile int8_t header; /*!< The first TCD index. Should point to the next TCD to be loaded into the eDMA engine. */
volatile int8_t tail; /*!< The last TCD index. Should point to the next TCD to be stored into the memory pool. */
volatile int8_t tcdUsed; /*!< The number of used TCD slots. Should reflect the number of TCDs can be used/loaded in
the memory. */
volatile int8_t tcdSize; /*!< The total number of TCD slots in the queue. */
uint8_t flags; /*!< The status of the current channel. */
} edma_handle_t;
/*******************************************************************************
* APIs
******************************************************************************/
#if defined(__cplusplus)
extern "C" {
#endif /* __cplusplus */
/*!
* @name eDMA initialization and de-initialization
* @{
*/
/*!
* @brief Initializes the eDMA peripheral.
*
* This function ungates the eDMA clock and configures the eDMA peripheral according
* to the configuration structure.
*
* @param base eDMA peripheral base address.
* @param config A pointer to the configuration structure, see "edma_config_t".
* @note This function enables the minor loop map feature.
*/
void EDMA_Init(DMA_Type *base, const edma_config_t *config);
/*!
* @brief Deinitializes the eDMA peripheral.
*
* This function gates the eDMA clock.
*
* @param base eDMA peripheral base address.
*/
void EDMA_Deinit(DMA_Type *base);
/*!
* @brief Push content of TCD structure into hardware TCD register.
*
* @param base EDMA peripheral base address.
* @param channel EDMA channel number.
* @param tcd Point to TCD structure.
*/
void EDMA_InstallTCD(DMA_Type *base, uint32_t channel, edma_tcd_t *tcd);
/*!
* @brief Gets the eDMA default configuration structure.
*
* This function sets the configuration structure to default values.
* The default configuration is set to the following values.
* @code
* config.enableContinuousLinkMode = false;
* config.enableHaltOnError = true;
* config.enableRoundRobinArbitration = false;
* config.enableDebugMode = false;
* @endcode
*
* @param config A pointer to the eDMA configuration structure.
*/
void EDMA_GetDefaultConfig(edma_config_t *config);
/* @} */
/*!
* @name eDMA Channel Operation
* @{
*/
/*!
* @brief Sets all TCD registers to default values.
*
* This function sets TCD registers for this channel to default values.
*
* @param base eDMA peripheral base address.
* @param channel eDMA channel number.
* @note This function must not be called while the channel transfer is ongoing
* or it causes unpredictable results.
* @note This function enables the auto stop request feature.
*/
void EDMA_ResetChannel(DMA_Type *base, uint32_t channel);
/*!
* @brief Configures the eDMA transfer attribute.
*
* This function configures the transfer attribute, including source address, destination address,
* transfer size, address offset, and so on. It also configures the scatter gather feature if the
* user supplies the TCD address.
* Example:
* @code
* edma_transfer_t config;
* edma_tcd_t tcd;
* config.srcAddr = ..;
* config.destAddr = ..;
* ...
* EDMA_SetTransferConfig(DMA0, channel, &config, &stcd);
* @endcode
*
* @param base eDMA peripheral base address.
* @param channel eDMA channel number.
* @param config Pointer to eDMA transfer configuration structure.
* @param nextTcd Point to TCD structure. It can be NULL if users
* do not want to enable scatter/gather feature.
* @note If nextTcd is not NULL, it means scatter gather feature is enabled
* and DREQ bit is cleared in the previous transfer configuration, which
* is set in the eDMA_ResetChannel.
*/
void EDMA_SetTransferConfig(DMA_Type *base,
uint32_t channel,
const edma_transfer_config_t *config,
edma_tcd_t *nextTcd);
/*!
* @brief Configures the eDMA minor offset feature.
*
* The minor offset means that the signed-extended value is added to the source address or destination
* address after each minor loop.
*
* @param base eDMA peripheral base address.
* @param channel eDMA channel number.
* @param config A pointer to the minor offset configuration structure.
*/
void EDMA_SetMinorOffsetConfig(DMA_Type *base, uint32_t channel, const edma_minor_offset_config_t *config);
/*!
* @brief Configures the eDMA channel preemption feature.
*
* This function configures the channel preemption attribute and the priority of the channel.
*
* @param base eDMA peripheral base address.
* @param channel eDMA channel number
* @param config A pointer to the channel preemption configuration structure.
*/
static inline void EDMA_SetChannelPreemptionConfig(DMA_Type *base,
uint32_t channel,
const edma_channel_Preemption_config_t *config)
{
assert(channel < FSL_FEATURE_EDMA_MODULE_CHANNEL);
assert(config != NULL);
DMA_DCHPRIn(base, channel) =
(DMA_DCHPRI0_DPA(!config->enablePreemptAbility) | DMA_DCHPRI0_ECP(config->enableChannelPreemption) |
DMA_DCHPRI0_CHPRI(config->channelPriority));
}
/*!
* @brief Sets the channel link for the eDMA transfer.
*
* This function configures either the minor link or the major link mode. The minor link means that the channel link is
* triggered every time CITER decreases by 1. The major link means that the channel link is triggered when the CITER is
* exhausted.
*
* @param base eDMA peripheral base address.
* @param channel eDMA channel number.
* @param type A channel link type, which can be one of the following:
* @arg kEDMA_LinkNone
* @arg kEDMA_MinorLink
* @arg kEDMA_MajorLink
* @param linkedChannel The linked channel number.
* @note Users should ensure that DONE flag is cleared before calling this interface, or the configuration is invalid.
*/
void EDMA_SetChannelLink(DMA_Type *base, uint32_t channel, edma_channel_link_type_t type, uint32_t linkedChannel);
/*!
* @brief Sets the bandwidth for the eDMA transfer.
*
* Because the eDMA processes the minor loop, it continuously generates read/write sequences
* until the minor count is exhausted. The bandwidth forces the eDMA to stall after the completion of
* each read/write access to control the bus request bandwidth seen by the crossbar switch.
*
* @param base eDMA peripheral base address.
* @param channel eDMA channel number.
* @param bandWidth A bandwidth setting, which can be one of the following:
* @arg kEDMABandwidthStallNone
* @arg kEDMABandwidthStall4Cycle
* @arg kEDMABandwidthStall8Cycle
*/
void EDMA_SetBandWidth(DMA_Type *base, uint32_t channel, edma_bandwidth_t bandWidth);
/*!
* @brief Sets the source modulo and the destination modulo for the eDMA transfer.
*
* This function defines a specific address range specified to be the value after (SADDR + SOFF)/(DADDR + DOFF)
* calculation is performed or the original register value. It provides the ability to implement a circular data
* queue easily.
*
* @param base eDMA peripheral base address.
* @param channel eDMA channel number.
* @param srcModulo A source modulo value.
* @param destModulo A destination modulo value.
*/
void EDMA_SetModulo(DMA_Type *base, uint32_t channel, edma_modulo_t srcModulo, edma_modulo_t destModulo);
#if defined(FSL_FEATURE_EDMA_ASYNCHRO_REQUEST_CHANNEL_COUNT) && FSL_FEATURE_EDMA_ASYNCHRO_REQUEST_CHANNEL_COUNT
/*!
* @brief Enables an async request for the eDMA transfer.
*
* @param base eDMA peripheral base address.
* @param channel eDMA channel number.
* @param enable The command to enable (true) or disable (false).
*/
static inline void EDMA_EnableAsyncRequest(DMA_Type *base, uint32_t channel, bool enable)
{
assert(channel < FSL_FEATURE_DMAMUX_MODULE_CHANNEL);
base->EARS = (base->EARS & (~(1U << channel))) | ((uint32_t)enable << channel);
}
#endif /* FSL_FEATURE_EDMA_ASYNCHRO_REQUEST_CHANNEL_COUNT */
/*!
* @brief Enables an auto stop request for the eDMA transfer.
*
* If enabling the auto stop request, the eDMA hardware automatically disables the hardware channel request.
*
* @param base eDMA peripheral base address.
* @param channel eDMA channel number.
* @param enable The command to enable (true) or disable (false).
*/
static inline void EDMA_EnableAutoStopRequest(DMA_Type *base, uint32_t channel, bool enable)
{
assert(channel < FSL_FEATURE_DMAMUX_MODULE_CHANNEL);
base->TCD[channel].CSR = (base->TCD[channel].CSR & (~DMA_CSR_DREQ_MASK)) | DMA_CSR_DREQ(enable);
}
/*!
* @brief Enables the interrupt source for the eDMA transfer.
*
* @param base eDMA peripheral base address.
* @param channel eDMA channel number.
* @param mask The mask of interrupt source to be set. Users need to use
* the defined edma_interrupt_enable_t type.
*/
void EDMA_EnableChannelInterrupts(DMA_Type *base, uint32_t channel, uint32_t mask);
/*!
* @brief Disables the interrupt source for the eDMA transfer.
*
* @param base eDMA peripheral base address.
* @param channel eDMA channel number.
* @param mask The mask of the interrupt source to be set. Use
* the defined edma_interrupt_enable_t type.
*/
void EDMA_DisableChannelInterrupts(DMA_Type *base, uint32_t channel, uint32_t mask);
/* @} */
/*!
* @name eDMA TCD Operation
* @{
*/
/*!
* @brief Sets all fields to default values for the TCD structure.
*
* This function sets all fields for this TCD structure to default value.
*
* @param tcd Pointer to the TCD structure.
* @note This function enables the auto stop request feature.
*/
void EDMA_TcdReset(edma_tcd_t *tcd);
/*!
* @brief Configures the eDMA TCD transfer attribute.
*
* The TCD is a transfer control descriptor. The content of the TCD is the same as the hardware TCD registers.
* The STCD is used in the scatter-gather mode.
* This function configures the TCD transfer attribute, including source address, destination address,
* transfer size, address offset, and so on. It also configures the scatter gather feature if the
* user supplies the next TCD address.
* Example:
* @code
* edma_transfer_t config = {
* ...
* }
* edma_tcd_t tcd __aligned(32);
* edma_tcd_t nextTcd __aligned(32);
* EDMA_TcdSetTransferConfig(&tcd, &config, &nextTcd);
* @endcode
*
* @param tcd Pointer to the TCD structure.
* @param config Pointer to eDMA transfer configuration structure.
* @param nextTcd Pointer to the next TCD structure. It can be NULL if users
* do not want to enable scatter/gather feature.
* @note TCD address should be 32 bytes aligned or it causes an eDMA error.
* @note If the nextTcd is not NULL, the scatter gather feature is enabled
* and DREQ bit is cleared in the previous transfer configuration, which
* is set in the EDMA_TcdReset.
*/
void EDMA_TcdSetTransferConfig(edma_tcd_t *tcd, const edma_transfer_config_t *config, edma_tcd_t *nextTcd);
/*!
* @brief Configures the eDMA TCD minor offset feature.
*
* A minor offset is a signed-extended value added to the source address or a destination
* address after each minor loop.
*
* @param tcd A point to the TCD structure.
* @param config A pointer to the minor offset configuration structure.
*/
void EDMA_TcdSetMinorOffsetConfig(edma_tcd_t *tcd, const edma_minor_offset_config_t *config);
/*!
* @brief Sets the channel link for the eDMA TCD.
*
* This function configures either a minor link or a major link. The minor link means the channel link is
* triggered every time CITER decreases by 1. The major link means that the channel link is triggered when the CITER is
* exhausted.
*
* @note Users should ensure that DONE flag is cleared before calling this interface, or the configuration is invalid.
* @param tcd Point to the TCD structure.
* @param type Channel link type, it can be one of:
* @arg kEDMA_LinkNone
* @arg kEDMA_MinorLink
* @arg kEDMA_MajorLink
* @param linkedChannel The linked channel number.
*/
void EDMA_TcdSetChannelLink(edma_tcd_t *tcd, edma_channel_link_type_t type, uint32_t linkedChannel);
/*!
* @brief Sets the bandwidth for the eDMA TCD.
*
* Because the eDMA processes the minor loop, it continuously generates read/write sequences
* until the minor count is exhausted. The bandwidth forces the eDMA to stall after the completion of
* each read/write access to control the bus request bandwidth seen by the crossbar switch.
* @param tcd A pointer to the TCD structure.
* @param bandWidth A bandwidth setting, which can be one of the following:
* @arg kEDMABandwidthStallNone
* @arg kEDMABandwidthStall4Cycle
* @arg kEDMABandwidthStall8Cycle
*/
static inline void EDMA_TcdSetBandWidth(edma_tcd_t *tcd, edma_bandwidth_t bandWidth)
{
assert(tcd != NULL);
assert(((uint32_t)tcd & 0x1FU) == 0);
tcd->CSR = (tcd->CSR & (~DMA_CSR_BWC_MASK)) | DMA_CSR_BWC(bandWidth);
}
/*!
* @brief Sets the source modulo and the destination modulo for the eDMA TCD.
*
* This function defines a specific address range specified to be the value after (SADDR + SOFF)/(DADDR + DOFF)
* calculation is performed or the original register value. It provides the ability to implement a circular data
* queue easily.
*
* @param tcd A pointer to the TCD structure.
* @param srcModulo A source modulo value.
* @param destModulo A destination modulo value.
*/
void EDMA_TcdSetModulo(edma_tcd_t *tcd, edma_modulo_t srcModulo, edma_modulo_t destModulo);
/*!
* @brief Sets the auto stop request for the eDMA TCD.
*
* If enabling the auto stop request, the eDMA hardware automatically disables the hardware channel request.
*
* @param tcd A pointer to the TCD structure.
* @param enable The command to enable (true) or disable (false).
*/
static inline void EDMA_TcdEnableAutoStopRequest(edma_tcd_t *tcd, bool enable)
{
assert(tcd != NULL);
assert(((uint32_t)tcd & 0x1FU) == 0);
tcd->CSR = (tcd->CSR & (~DMA_CSR_DREQ_MASK)) | DMA_CSR_DREQ(enable);
}
/*!
* @brief Enables the interrupt source for the eDMA TCD.
*
* @param tcd Point to the TCD structure.
* @param mask The mask of interrupt source to be set. Users need to use
* the defined edma_interrupt_enable_t type.
*/
void EDMA_TcdEnableInterrupts(edma_tcd_t *tcd, uint32_t mask);
/*!
* @brief Disables the interrupt source for the eDMA TCD.
*
* @param tcd Point to the TCD structure.
* @param mask The mask of interrupt source to be set. Users need to use
* the defined edma_interrupt_enable_t type.
*/
void EDMA_TcdDisableInterrupts(edma_tcd_t *tcd, uint32_t mask);
/*! @} */
/*!
* @name eDMA Channel Transfer Operation
* @{
*/
/*!
* @brief Enables the eDMA hardware channel request.
*
* This function enables the hardware channel request.
*
* @param base eDMA peripheral base address.
* @param channel eDMA channel number.
*/
static inline void EDMA_EnableChannelRequest(DMA_Type *base, uint32_t channel)
{
assert(channel < FSL_FEATURE_DMAMUX_MODULE_CHANNEL);
base->SERQ = DMA_SERQ_SERQ(channel);
}
/*!
* @brief Disables the eDMA hardware channel request.
*
* This function disables the hardware channel request.
*
* @param base eDMA peripheral base address.
* @param channel eDMA channel number.
*/
static inline void EDMA_DisableChannelRequest(DMA_Type *base, uint32_t channel)
{
assert(channel < FSL_FEATURE_DMAMUX_MODULE_CHANNEL);
base->CERQ = DMA_CERQ_CERQ(channel);
}
/*!
* @brief Starts the eDMA transfer by using the software trigger.
*
* This function starts a minor loop transfer.
*
* @param base eDMA peripheral base address.
* @param channel eDMA channel number.
*/
static inline void EDMA_TriggerChannelStart(DMA_Type *base, uint32_t channel)
{
assert(channel < FSL_FEATURE_DMAMUX_MODULE_CHANNEL);
base->SSRT = DMA_SSRT_SSRT(channel);
}
/*! @} */
/*!
* @name eDMA Channel Status Operation
* @{
*/
/*!
* @brief Gets the remaining major loop count from the eDMA current channel TCD.
*
* This function checks the TCD (Task Control Descriptor) status for a specified
* eDMA channel and returns the the number of major loop count that has not finished.
*
* @param base eDMA peripheral base address.
* @param channel eDMA channel number.
* @return Major loop count which has not been transferred yet for the current TCD.
* @note 1. This function can only be used to get unfinished major loop count of transfer without
* the next TCD, or it might be inaccuracy.
* 2. The unfinished/remaining transfer bytes cannot be obtained directly from registers while
* the channel is running.
* Because to calculate the remaining bytes, the initial NBYTES configured in DMA_TCDn_NBYTES_MLNO
* register is needed while the eDMA IP does not support getting it while a channel is active.
* In another word, the NBYTES value reading is always the actual (decrementing) NBYTES value the dma_engine
* is working with while a channel is running.
* Consequently, to get the remaining transfer bytes, a software-saved initial value of NBYTES (for example
* copied before enabling the channel) is needed. The formula to calculate it is shown below:
* RemainingBytes = RemainingMajorLoopCount * NBYTES(initially configured)
*/
uint32_t EDMA_GetRemainingMajorLoopCount(DMA_Type *base, uint32_t channel);
/*!
* @brief Gets the eDMA channel error status flags.
*
* @param base eDMA peripheral base address.
* @return The mask of error status flags. Users need to use the
* _edma_error_status_flags type to decode the return variables.
*/
static inline uint32_t EDMA_GetErrorStatusFlags(DMA_Type *base)
{
return base->ES;
}
/*!
* @brief Gets the eDMA channel status flags.
*
* @param base eDMA peripheral base address.
* @param channel eDMA channel number.
* @return The mask of channel status flags. Users need to use the
* _edma_channel_status_flags type to decode the return variables.
*/
uint32_t EDMA_GetChannelStatusFlags(DMA_Type *base, uint32_t channel);
/*!
* @brief Clears the eDMA channel status flags.
*
* @param base eDMA peripheral base address.
* @param channel eDMA channel number.
* @param mask The mask of channel status to be cleared. Users need to use
* the defined _edma_channel_status_flags type.
*/
void EDMA_ClearChannelStatusFlags(DMA_Type *base, uint32_t channel, uint32_t mask);
/*! @} */
/*!
* @name eDMA Transactional Operation
*/
/*!
* @brief Creates the eDMA handle.
*
* This function is called if using the transactional API for eDMA. This function
* initializes the internal state of the eDMA handle.
*
* @param handle eDMA handle pointer. The eDMA handle stores callback function and
* parameters.
* @param base eDMA peripheral base address.
* @param channel eDMA channel number.
*/
void EDMA_CreateHandle(edma_handle_t *handle, DMA_Type *base, uint32_t channel);
/*!
* @brief Installs the TCDs memory pool into the eDMA handle.
*
* This function is called after the EDMA_CreateHandle to use scatter/gather feature.
*
* @param handle eDMA handle pointer.
* @param tcdPool A memory pool to store TCDs. It must be 32 bytes aligned.
* @param tcdSize The number of TCD slots.
*/
void EDMA_InstallTCDMemory(edma_handle_t *handle, edma_tcd_t *tcdPool, uint32_t tcdSize);
/*!
* @brief Installs a callback function for the eDMA transfer.
*
* This callback is called in the eDMA IRQ handler. Use the callback to do something after
* the current major loop transfer completes.
*
* @param handle eDMA handle pointer.
* @param callback eDMA callback function pointer.
* @param userData A parameter for the callback function.
*/
void EDMA_SetCallback(edma_handle_t *handle, edma_callback callback, void *userData);
/*!
* @brief Prepares the eDMA transfer structure.
*
* This function prepares the transfer configuration structure according to the user input.
*
* @param config The user configuration structure of type edma_transfer_t.
* @param srcAddr eDMA transfer source address.
* @param srcWidth eDMA transfer source address width(bytes).
* @param destAddr eDMA transfer destination address.
* @param destWidth eDMA transfer destination address width(bytes).
* @param bytesEachRequest eDMA transfer bytes per channel request.
* @param transferBytes eDMA transfer bytes to be transferred.
* @param type eDMA transfer type.
* @note The data address and the data width must be consistent. For example, if the SRC
* is 4 bytes, the source address must be 4 bytes aligned, or it results in
* source address error (SAE).
*/
void EDMA_PrepareTransfer(edma_transfer_config_t *config,
void *srcAddr,
uint32_t srcWidth,
void *destAddr,
uint32_t destWidth,
uint32_t bytesEachRequest,
uint32_t transferBytes,
edma_transfer_type_t type);
/*!
* @brief Submits the eDMA transfer request.
*
* This function submits the eDMA transfer request according to the transfer configuration structure.
* If submitting the transfer request repeatedly, this function packs an unprocessed request as
* a TCD and enables scatter/gather feature to process it in the next time.
*
* @param handle eDMA handle pointer.
* @param config Pointer to eDMA transfer configuration structure.
* @retval kStatus_EDMA_Success It means submit transfer request succeed.
* @retval kStatus_EDMA_QueueFull It means TCD queue is full. Submit transfer request is not allowed.
* @retval kStatus_EDMA_Busy It means the given channel is busy, need to submit request later.
*/
status_t EDMA_SubmitTransfer(edma_handle_t *handle, const edma_transfer_config_t *config);
/*!
* @brief eDMA starts transfer.
*
* This function enables the channel request. Users can call this function after submitting the transfer request
* or before submitting the transfer request.
*
* @param handle eDMA handle pointer.
*/
void EDMA_StartTransfer(edma_handle_t *handle);
/*!
* @brief eDMA stops transfer.
*
* This function disables the channel request to pause the transfer. Users can call EDMA_StartTransfer()
* again to resume the transfer.
*
* @param handle eDMA handle pointer.
*/
void EDMA_StopTransfer(edma_handle_t *handle);
/*!
* @brief eDMA aborts transfer.
*
* This function disables the channel request and clear transfer status bits.
* Users can submit another transfer after calling this API.
*
* @param handle DMA handle pointer.
*/
void EDMA_AbortTransfer(edma_handle_t *handle);
/*!
* @brief Get unused TCD slot number.
*
* This function gets current tcd index which is run. If the TCD pool pointer is NULL, it will return 0.
*
* @param handle DMA handle pointer.
* @return The unused tcd slot number.
*/
static inline uint32_t EDMA_GetUnusedTCDNumber(edma_handle_t *handle)
{
return (handle->tcdSize - handle->tcdUsed);
}
/*!
* @brief eDMA IRQ handler for the current major loop transfer completion.
*
* This function clears the channel major interrupt flag and calls
* the callback function if it is not NULL.
*
* Note:
* For the case using TCD queue, when the major iteration count is exhausted, additional operations are performed.
* These include the final address adjustments and reloading of the BITER field into the CITER.
* Assertion of an optional interrupt request also occurs at this time, as does a possible fetch of a new TCD from
* memory using the scatter/gather address pointer included in the descriptor (if scatter/gather is enabled).
*
* For instance, when the time interrupt of TCD[0] happens, the TCD[1] has already been loaded into the eDMA engine.
* As sga and sga_index are calculated based on the DLAST_SGA bitfield lies in the TCD_CSR register, the sga_index
* in this case should be 2 (DLAST_SGA of TCD[1] stores the address of TCD[2]). Thus, the "tcdUsed" updated should be
* (tcdUsed - 2U) which indicates the number of TCDs can be loaded in the memory pool (because TCD[0] and TCD[1] have
* been loaded into the eDMA engine at this point already.).
*
* For the last two continuous ISRs in a scatter/gather process, they both load the last TCD (The last ISR does not
* load a new TCD) from the memory pool to the eDMA engine when major loop completes.
* Therefore, ensure that the header and tcdUsed updated are identical for them.
* tcdUsed are both 0 in this case as no TCD to be loaded.
*
* See the "eDMA basic data flow" in the eDMA Functional description section of the Reference Manual for
* further details.
*
* @param handle eDMA handle pointer.
*/
void EDMA_HandleIRQ(edma_handle_t *handle);
/* @} */
#if defined(__cplusplus)
}
#endif /* __cplusplus */
/* @} */
#endif /*_FSL_EDMA_H_*/

View File

@ -0,0 +1,80 @@
/*
* Copyright (c) 2015, Freescale Semiconductor, Inc.
* Copyright 2016-2017 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include "fsl_ewm.h"
/*******************************************************************************
* Code
******************************************************************************/
void EWM_Init(EWM_Type *base, const ewm_config_t *config)
{
assert(config);
uint32_t value = 0U;
#if !((defined(FSL_FEATURE_SOC_PCC_COUNT) && FSL_FEATURE_SOC_PCC_COUNT) && \
(defined(FSL_FEATURE_PCC_SUPPORT_EWM_CLOCK_REMOVE) && FSL_FEATURE_PCC_SUPPORT_EWM_CLOCK_REMOVE))
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
CLOCK_EnableClock(kCLOCK_Ewm0);
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
#endif
value = EWM_CTRL_EWMEN(config->enableEwm) | EWM_CTRL_ASSIN(config->setInputAssertLogic) |
EWM_CTRL_INEN(config->enableEwmInput) | EWM_CTRL_INTEN(config->enableInterrupt);
#if defined(FSL_FEATURE_EWM_HAS_PRESCALER) && FSL_FEATURE_EWM_HAS_PRESCALER
base->CLKPRESCALER = config->prescaler;
#endif /* FSL_FEATURE_EWM_HAS_PRESCALER */
#if defined(FSL_FEATURE_EWM_HAS_CLOCK_SELECT) && FSL_FEATURE_EWM_HAS_CLOCK_SELECT
base->CLKCTRL = config->clockSource;
#endif /* FSL_FEATURE_EWM_HAS_CLOCK_SELECT*/
base->CMPL = config->compareLowValue;
base->CMPH = config->compareHighValue;
base->CTRL = value;
}
void EWM_Deinit(EWM_Type *base)
{
EWM_DisableInterrupts(base, kEWM_InterruptEnable);
#if !((defined(FSL_FEATURE_SOC_PCC_COUNT) && FSL_FEATURE_SOC_PCC_COUNT) && \
(defined(FSL_FEATURE_PCC_SUPPORT_EWM_CLOCK_REMOVE) && FSL_FEATURE_PCC_SUPPORT_EWM_CLOCK_REMOVE))
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
CLOCK_DisableClock(kCLOCK_Ewm0);
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
#endif /* FSL_FEATURE_PCC_SUPPORT_EWM_CLOCK_REMOVE */
}
void EWM_GetDefaultConfig(ewm_config_t *config)
{
assert(config);
config->enableEwm = true;
config->enableEwmInput = false;
config->setInputAssertLogic = false;
config->enableInterrupt = false;
#if defined(FSL_FEATURE_EWM_HAS_CLOCK_SELECT) && FSL_FEATURE_EWM_HAS_CLOCK_SELECT
config->clockSource = kEWM_LpoClockSource0;
#endif /* FSL_FEATURE_EWM_HAS_CLOCK_SELECT*/
#if defined(FSL_FEATURE_EWM_HAS_PRESCALER) && FSL_FEATURE_EWM_HAS_PRESCALER
config->prescaler = 0U;
#endif /* FSL_FEATURE_EWM_HAS_PRESCALER */
config->compareLowValue = 0U;
config->compareHighValue = 0xFEU;
}
void EWM_Refresh(EWM_Type *base)
{
uint32_t primaskValue = 0U;
/* Disable the global interrupt to protect refresh sequence */
primaskValue = DisableGlobalIRQ();
base->SERV = (uint8_t)0xB4U;
base->SERV = (uint8_t)0x2CU;
EnableGlobalIRQ(primaskValue);
}

View File

@ -0,0 +1,219 @@
/*
* Copyright (c) 2015, Freescale Semiconductor, Inc.
* Copyright 2016-2017 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef _FSL_EWM_H_
#define _FSL_EWM_H_
#include "fsl_common.h"
/*!
* @addtogroup ewm
* @{
*/
/*******************************************************************************
* Definitions
*******************************************************************************/
/*! @name Driver version */
/*@{*/
/*! @brief EWM driver version 2.0.1. */
#define FSL_EWM_DRIVER_VERSION (MAKE_VERSION(2, 0, 1))
/*@}*/
/*! @brief Describes EWM clock source. */
#if defined(FSL_FEATURE_EWM_HAS_CLOCK_SELECT) && FSL_FEATURE_EWM_HAS_CLOCK_SELECT
typedef enum _ewm_lpo_clock_source
{
kEWM_LpoClockSource0 = 0U, /*!< EWM clock sourced from lpo_clk[0]*/
kEWM_LpoClockSource1 = 1U, /*!< EWM clock sourced from lpo_clk[1]*/
kEWM_LpoClockSource2 = 2U, /*!< EWM clock sourced from lpo_clk[2]*/
kEWM_LpoClockSource3 = 3U, /*!< EWM clock sourced from lpo_clk[3]*/
} ewm_lpo_clock_source_t;
#endif /* FSL_FEATURE_EWM_HAS_CLOCK_SELECT */
/*!
* @brief Data structure for EWM configuration.
*
* This structure is used to configure the EWM.
*/
typedef struct _ewm_config
{
bool enableEwm; /*!< Enable EWM module */
bool enableEwmInput; /*!< Enable EWM_in input */
bool setInputAssertLogic; /*!< EWM_in signal assertion state */
bool enableInterrupt; /*!< Enable EWM interrupt */
#if defined(FSL_FEATURE_EWM_HAS_CLOCK_SELECT) && FSL_FEATURE_EWM_HAS_CLOCK_SELECT
ewm_lpo_clock_source_t clockSource; /*!< Clock source select */
#endif /* FSL_FEATURE_EWM_HAS_CLOCK_SELECT */
#if defined(FSL_FEATURE_EWM_HAS_PRESCALER) && FSL_FEATURE_EWM_HAS_PRESCALER
uint8_t prescaler; /*!< Clock prescaler value */
#endif /* FSL_FEATURE_EWM_HAS_PRESCALER */
uint8_t compareLowValue; /*!< Compare low-register value */
uint8_t compareHighValue; /*!< Compare high-register value */
} ewm_config_t;
/*!
* @brief EWM interrupt configuration structure with default settings all disabled.
*
* This structure contains the settings for all of EWM interrupt configurations.
*/
enum _ewm_interrupt_enable_t
{
kEWM_InterruptEnable = EWM_CTRL_INTEN_MASK, /*!< Enable the EWM to generate an interrupt*/
};
/*!
* @brief EWM status flags.
*
* This structure contains the constants for the EWM status flags for use in the EWM functions.
*/
enum _ewm_status_flags_t
{
kEWM_RunningFlag = EWM_CTRL_EWMEN_MASK, /*!< Running flag, set when EWM is enabled*/
};
/*******************************************************************************
* API
*******************************************************************************/
#if defined(__cplusplus)
extern "C" {
#endif /* __cplusplus */
/*!
* @name EWM initialization and de-initialization
* @{
*/
/*!
* @brief Initializes the EWM peripheral.
*
* This function is used to initialize the EWM. After calling, the EWM
* runs immediately according to the configuration.
* Note that, except for the interrupt enable control bit, other control bits and registers are write once after a
* CPU reset. Modifying them more than once generates a bus transfer error.
*
* This is an example.
* @code
* ewm_config_t config;
* EWM_GetDefaultConfig(&config);
* config.compareHighValue = 0xAAU;
* EWM_Init(ewm_base,&config);
* @endcode
*
* @param base EWM peripheral base address
* @param config The configuration of the EWM
*/
void EWM_Init(EWM_Type *base, const ewm_config_t *config);
/*!
* @brief Deinitializes the EWM peripheral.
*
* This function is used to shut down the EWM.
*
* @param base EWM peripheral base address
*/
void EWM_Deinit(EWM_Type *base);
/*!
* @brief Initializes the EWM configuration structure.
*
* This function initializes the EWM configuration structure to default values. The default
* values are as follows.
* @code
* ewmConfig->enableEwm = true;
* ewmConfig->enableEwmInput = false;
* ewmConfig->setInputAssertLogic = false;
* ewmConfig->enableInterrupt = false;
* ewmConfig->ewm_lpo_clock_source_t = kEWM_LpoClockSource0;
* ewmConfig->prescaler = 0;
* ewmConfig->compareLowValue = 0;
* ewmConfig->compareHighValue = 0xFEU;
* @endcode
*
* @param config Pointer to the EWM configuration structure.
* @see ewm_config_t
*/
void EWM_GetDefaultConfig(ewm_config_t *config);
/* @} */
/*!
* @name EWM functional Operation
* @{
*/
/*!
* @brief Enables the EWM interrupt.
*
* This function enables the EWM interrupt.
*
* @param base EWM peripheral base address
* @param mask The interrupts to enable
* The parameter can be combination of the following source if defined
* @arg kEWM_InterruptEnable
*/
static inline void EWM_EnableInterrupts(EWM_Type *base, uint32_t mask)
{
base->CTRL |= mask;
}
/*!
* @brief Disables the EWM interrupt.
*
* This function enables the EWM interrupt.
*
* @param base EWM peripheral base address
* @param mask The interrupts to disable
* The parameter can be combination of the following source if defined
* @arg kEWM_InterruptEnable
*/
static inline void EWM_DisableInterrupts(EWM_Type *base, uint32_t mask)
{
base->CTRL &= ~mask;
}
/*!
* @brief Gets all status flags.
*
* This function gets all status flags.
*
* This is an example for getting the running flag.
* @code
* uint32_t status;
* status = EWM_GetStatusFlags(ewm_base) & kEWM_RunningFlag;
* @endcode
* @param base EWM peripheral base address
* @return State of the status flag: asserted (true) or not-asserted (false).@see _ewm_status_flags_t
* - True: a related status flag has been set.
* - False: a related status flag is not set.
*/
static inline uint32_t EWM_GetStatusFlags(EWM_Type *base)
{
return (base->CTRL & EWM_CTRL_EWMEN_MASK);
}
/*!
* @brief Services the EWM.
*
* This function resets the EWM counter to zero.
*
* @param base EWM peripheral base address
*/
void EWM_Refresh(EWM_Type *base);
/*@}*/
#if defined(__cplusplus)
}
#endif /* __cplusplus */
/*! @}*/
#endif /* _FSL_EWM_H_ */

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,279 @@
/*
* Copyright (c) 2015, Freescale Semiconductor, Inc.
* Copyright 2016-2017 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include "fsl_flexio.h"
/*******************************************************************************
* Definitions
******************************************************************************/
/*< @brief user configurable flexio handle count. */
#define FLEXIO_HANDLE_COUNT 2
/*******************************************************************************
* Variables
******************************************************************************/
/*< @brief pointer to array of FLEXIO handle. */
static void *s_flexioHandle[FLEXIO_HANDLE_COUNT];
/*< @brief pointer to array of FLEXIO IP types. */
static void *s_flexioType[FLEXIO_HANDLE_COUNT];
/*< @brief pointer to array of FLEXIO Isr. */
static flexio_isr_t s_flexioIsr[FLEXIO_HANDLE_COUNT];
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
/*! @brief Pointers to flexio clocks for each instance. */
const clock_ip_name_t s_flexioClocks[] = FLEXIO_CLOCKS;
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
/*! @brief Pointers to flexio bases for each instance. */
FLEXIO_Type *const s_flexioBases[] = FLEXIO_BASE_PTRS;
/*******************************************************************************
* Codes
******************************************************************************/
uint32_t FLEXIO_GetInstance(FLEXIO_Type *base)
{
uint32_t instance;
/* Find the instance index from base address mappings. */
for (instance = 0; instance < ARRAY_SIZE(s_flexioBases); instance++)
{
if (s_flexioBases[instance] == base)
{
break;
}
}
assert(instance < ARRAY_SIZE(s_flexioBases));
return instance;
}
void FLEXIO_Init(FLEXIO_Type *base, const flexio_config_t *userConfig)
{
uint32_t ctrlReg = 0;
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
CLOCK_EnableClock(s_flexioClocks[FLEXIO_GetInstance(base)]);
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
FLEXIO_Reset(base);
ctrlReg = base->CTRL;
ctrlReg &= ~(FLEXIO_CTRL_DOZEN_MASK | FLEXIO_CTRL_DBGE_MASK | FLEXIO_CTRL_FASTACC_MASK | FLEXIO_CTRL_FLEXEN_MASK);
ctrlReg |= (FLEXIO_CTRL_DBGE(userConfig->enableInDebug) | FLEXIO_CTRL_FASTACC(userConfig->enableFastAccess) |
FLEXIO_CTRL_FLEXEN(userConfig->enableFlexio));
if (!userConfig->enableInDoze)
{
ctrlReg |= FLEXIO_CTRL_DOZEN_MASK;
}
base->CTRL = ctrlReg;
}
void FLEXIO_Deinit(FLEXIO_Type *base)
{
FLEXIO_Enable(base, false);
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
CLOCK_DisableClock(s_flexioClocks[FLEXIO_GetInstance(base)]);
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
}
void FLEXIO_GetDefaultConfig(flexio_config_t *userConfig)
{
assert(userConfig);
userConfig->enableFlexio = true;
userConfig->enableInDoze = false;
userConfig->enableInDebug = true;
userConfig->enableFastAccess = false;
}
void FLEXIO_Reset(FLEXIO_Type *base)
{
/*do software reset, software reset operation affect all other FLEXIO registers except CTRL*/
base->CTRL |= FLEXIO_CTRL_SWRST_MASK;
base->CTRL = 0;
}
uint32_t FLEXIO_GetShifterBufferAddress(FLEXIO_Type *base, flexio_shifter_buffer_type_t type, uint8_t index)
{
assert(index < FLEXIO_SHIFTBUF_COUNT);
uint32_t address = 0;
switch (type)
{
case kFLEXIO_ShifterBuffer:
address = (uint32_t) & (base->SHIFTBUF[index]);
break;
case kFLEXIO_ShifterBufferBitSwapped:
address = (uint32_t) & (base->SHIFTBUFBIS[index]);
break;
case kFLEXIO_ShifterBufferByteSwapped:
address = (uint32_t) & (base->SHIFTBUFBYS[index]);
break;
case kFLEXIO_ShifterBufferBitByteSwapped:
address = (uint32_t) & (base->SHIFTBUFBBS[index]);
break;
#if defined(FSL_FEATURE_FLEXIO_HAS_SHFT_BUFFER_NIBBLE_BYTE_SWAP) && FSL_FEATURE_FLEXIO_HAS_SHFT_BUFFER_NIBBLE_BYTE_SWAP
case kFLEXIO_ShifterBufferNibbleByteSwapped:
address = (uint32_t) & (base->SHIFTBUFNBS[index]);
break;
#endif
#if defined(FSL_FEATURE_FLEXIO_HAS_SHFT_BUFFER_HALF_WORD_SWAP) && FSL_FEATURE_FLEXIO_HAS_SHFT_BUFFER_HALF_WORD_SWAP
case kFLEXIO_ShifterBufferHalfWordSwapped:
address = (uint32_t) & (base->SHIFTBUFHWS[index]);
break;
#endif
#if defined(FSL_FEATURE_FLEXIO_HAS_SHFT_BUFFER_NIBBLE_SWAP) && FSL_FEATURE_FLEXIO_HAS_SHFT_BUFFER_NIBBLE_SWAP
case kFLEXIO_ShifterBufferNibbleSwapped:
address = (uint32_t) & (base->SHIFTBUFNIS[index]);
break;
#endif
default:
break;
}
return address;
}
void FLEXIO_SetShifterConfig(FLEXIO_Type *base, uint8_t index, const flexio_shifter_config_t *shifterConfig)
{
base->SHIFTCFG[index] = FLEXIO_SHIFTCFG_INSRC(shifterConfig->inputSource)
#if FSL_FEATURE_FLEXIO_HAS_PARALLEL_WIDTH
| FLEXIO_SHIFTCFG_PWIDTH(shifterConfig->parallelWidth)
#endif /* FSL_FEATURE_FLEXIO_HAS_PARALLEL_WIDTH */
| FLEXIO_SHIFTCFG_SSTOP(shifterConfig->shifterStop) |
FLEXIO_SHIFTCFG_SSTART(shifterConfig->shifterStart);
base->SHIFTCTL[index] =
FLEXIO_SHIFTCTL_TIMSEL(shifterConfig->timerSelect) | FLEXIO_SHIFTCTL_TIMPOL(shifterConfig->timerPolarity) |
FLEXIO_SHIFTCTL_PINCFG(shifterConfig->pinConfig) | FLEXIO_SHIFTCTL_PINSEL(shifterConfig->pinSelect) |
FLEXIO_SHIFTCTL_PINPOL(shifterConfig->pinPolarity) | FLEXIO_SHIFTCTL_SMOD(shifterConfig->shifterMode);
}
void FLEXIO_SetTimerConfig(FLEXIO_Type *base, uint8_t index, const flexio_timer_config_t *timerConfig)
{
base->TIMCFG[index] =
FLEXIO_TIMCFG_TIMOUT(timerConfig->timerOutput) | FLEXIO_TIMCFG_TIMDEC(timerConfig->timerDecrement) |
FLEXIO_TIMCFG_TIMRST(timerConfig->timerReset) | FLEXIO_TIMCFG_TIMDIS(timerConfig->timerDisable) |
FLEXIO_TIMCFG_TIMENA(timerConfig->timerEnable) | FLEXIO_TIMCFG_TSTOP(timerConfig->timerStop) |
FLEXIO_TIMCFG_TSTART(timerConfig->timerStart);
base->TIMCMP[index] = FLEXIO_TIMCMP_CMP(timerConfig->timerCompare);
base->TIMCTL[index] = FLEXIO_TIMCTL_TRGSEL(timerConfig->triggerSelect) |
FLEXIO_TIMCTL_TRGPOL(timerConfig->triggerPolarity) |
FLEXIO_TIMCTL_TRGSRC(timerConfig->triggerSource) |
FLEXIO_TIMCTL_PINCFG(timerConfig->pinConfig) | FLEXIO_TIMCTL_PINSEL(timerConfig->pinSelect) |
FLEXIO_TIMCTL_PINPOL(timerConfig->pinPolarity) | FLEXIO_TIMCTL_TIMOD(timerConfig->timerMode);
}
status_t FLEXIO_RegisterHandleIRQ(void *base, void *handle, flexio_isr_t isr)
{
assert(base);
assert(handle);
assert(isr);
uint8_t index = 0;
/* Find the an empty handle pointer to store the handle. */
for (index = 0; index < FLEXIO_HANDLE_COUNT; index++)
{
if (s_flexioHandle[index] == NULL)
{
/* Register FLEXIO simulated driver base, handle and isr. */
s_flexioType[index] = base;
s_flexioHandle[index] = handle;
s_flexioIsr[index] = isr;
break;
}
}
if (index == FLEXIO_HANDLE_COUNT)
{
return kStatus_OutOfRange;
}
else
{
return kStatus_Success;
}
}
status_t FLEXIO_UnregisterHandleIRQ(void *base)
{
assert(base);
uint8_t index = 0;
/* Find the index from base address mappings. */
for (index = 0; index < FLEXIO_HANDLE_COUNT; index++)
{
if (s_flexioType[index] == base)
{
/* Unregister FLEXIO simulated driver handle and isr. */
s_flexioType[index] = NULL;
s_flexioHandle[index] = NULL;
s_flexioIsr[index] = NULL;
break;
}
}
if (index == FLEXIO_HANDLE_COUNT)
{
return kStatus_OutOfRange;
}
else
{
return kStatus_Success;
}
}
void FLEXIO_CommonIRQHandler(void)
{
uint8_t index;
for (index = 0; index < FLEXIO_HANDLE_COUNT; index++)
{
if (s_flexioHandle[index])
{
s_flexioIsr[index](s_flexioType[index], s_flexioHandle[index]);
}
}
}
void FLEXIO_DriverIRQHandler(void)
{
FLEXIO_CommonIRQHandler();
}
void FLEXIO0_DriverIRQHandler(void)
{
FLEXIO_CommonIRQHandler();
}
void FLEXIO1_DriverIRQHandler(void)
{
FLEXIO_CommonIRQHandler();
}
void UART2_FLEXIO_DriverIRQHandler(void)
{
FLEXIO_CommonIRQHandler();
}

View File

@ -0,0 +1,683 @@
/*
* Copyright (c) 2015, Freescale Semiconductor, Inc.
* Copyright 2016-2017 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef _FSL_FLEXIO_H_
#define _FSL_FLEXIO_H_
#include "fsl_common.h"
/*!
* @addtogroup flexio_driver
* @{
*/
/*******************************************************************************
* Definitions
******************************************************************************/
/*! @name Driver version */
/*@{*/
/*! @brief FlexIO driver version 2.0.1. */
#define FSL_FLEXIO_DRIVER_VERSION (MAKE_VERSION(2, 0, 1))
/*@}*/
/*! @brief Calculate FlexIO timer trigger.*/
#define FLEXIO_TIMER_TRIGGER_SEL_PININPUT(x) ((uint32_t)(x) << 1U)
#define FLEXIO_TIMER_TRIGGER_SEL_SHIFTnSTAT(x) (((uint32_t)(x) << 2U) | 0x1U)
#define FLEXIO_TIMER_TRIGGER_SEL_TIMn(x) (((uint32_t)(x) << 2U) | 0x3U)
/*! @brief Define time of timer trigger polarity.*/
typedef enum _flexio_timer_trigger_polarity
{
kFLEXIO_TimerTriggerPolarityActiveHigh = 0x0U, /*!< Active high. */
kFLEXIO_TimerTriggerPolarityActiveLow = 0x1U, /*!< Active low. */
} flexio_timer_trigger_polarity_t;
/*! @brief Define type of timer trigger source.*/
typedef enum _flexio_timer_trigger_source
{
kFLEXIO_TimerTriggerSourceExternal = 0x0U, /*!< External trigger selected. */
kFLEXIO_TimerTriggerSourceInternal = 0x1U, /*!< Internal trigger selected. */
} flexio_timer_trigger_source_t;
/*! @brief Define type of timer/shifter pin configuration.*/
typedef enum _flexio_pin_config
{
kFLEXIO_PinConfigOutputDisabled = 0x0U, /*!< Pin output disabled. */
kFLEXIO_PinConfigOpenDrainOrBidirection = 0x1U, /*!< Pin open drain or bidirectional output enable. */
kFLEXIO_PinConfigBidirectionOutputData = 0x2U, /*!< Pin bidirectional output data. */
kFLEXIO_PinConfigOutput = 0x3U, /*!< Pin output. */
} flexio_pin_config_t;
/*! @brief Definition of pin polarity.*/
typedef enum _flexio_pin_polarity
{
kFLEXIO_PinActiveHigh = 0x0U, /*!< Active high. */
kFLEXIO_PinActiveLow = 0x1U, /*!< Active low. */
} flexio_pin_polarity_t;
/*! @brief Define type of timer work mode.*/
typedef enum _flexio_timer_mode
{
kFLEXIO_TimerModeDisabled = 0x0U, /*!< Timer Disabled. */
kFLEXIO_TimerModeDual8BitBaudBit = 0x1U, /*!< Dual 8-bit counters baud/bit mode. */
kFLEXIO_TimerModeDual8BitPWM = 0x2U, /*!< Dual 8-bit counters PWM mode. */
kFLEXIO_TimerModeSingle16Bit = 0x3U, /*!< Single 16-bit counter mode. */
} flexio_timer_mode_t;
/*! @brief Define type of timer initial output or timer reset condition.*/
typedef enum _flexio_timer_output
{
kFLEXIO_TimerOutputOneNotAffectedByReset = 0x0U, /*!< Logic one when enabled and is not affected by timer
reset. */
kFLEXIO_TimerOutputZeroNotAffectedByReset = 0x1U, /*!< Logic zero when enabled and is not affected by timer
reset. */
kFLEXIO_TimerOutputOneAffectedByReset = 0x2U, /*!< Logic one when enabled and on timer reset. */
kFLEXIO_TimerOutputZeroAffectedByReset = 0x3U, /*!< Logic zero when enabled and on timer reset. */
} flexio_timer_output_t;
/*! @brief Define type of timer decrement.*/
typedef enum _flexio_timer_decrement_source
{
kFLEXIO_TimerDecSrcOnFlexIOClockShiftTimerOutput = 0x0U, /*!< Decrement counter on FlexIO clock, Shift clock
equals Timer output. */
kFLEXIO_TimerDecSrcOnTriggerInputShiftTimerOutput = 0x1U, /*!< Decrement counter on Trigger input (both edges),
Shift clock equals Timer output. */
kFLEXIO_TimerDecSrcOnPinInputShiftPinInput = 0x2U, /*!< Decrement counter on Pin input (both edges),
Shift clock equals Pin input. */
kFLEXIO_TimerDecSrcOnTriggerInputShiftTriggerInput = 0x3U, /*!< Decrement counter on Trigger input (both edges),
Shift clock equals Trigger input. */
} flexio_timer_decrement_source_t;
/*! @brief Define type of timer reset condition.*/
typedef enum _flexio_timer_reset_condition
{
kFLEXIO_TimerResetNever = 0x0U, /*!< Timer never reset. */
kFLEXIO_TimerResetOnTimerPinEqualToTimerOutput = 0x2U, /*!< Timer reset on Timer Pin equal to Timer Output. */
kFLEXIO_TimerResetOnTimerTriggerEqualToTimerOutput = 0x3U, /*!< Timer reset on Timer Trigger equal to
Timer Output. */
kFLEXIO_TimerResetOnTimerPinRisingEdge = 0x4U, /*!< Timer reset on Timer Pin rising edge. */
kFLEXIO_TimerResetOnTimerTriggerRisingEdge = 0x6U, /*!< Timer reset on Trigger rising edge. */
kFLEXIO_TimerResetOnTimerTriggerBothEdge = 0x7U, /*!< Timer reset on Trigger rising or falling edge. */
} flexio_timer_reset_condition_t;
/*! @brief Define type of timer disable condition.*/
typedef enum _flexio_timer_disable_condition
{
kFLEXIO_TimerDisableNever = 0x0U, /*!< Timer never disabled. */
kFLEXIO_TimerDisableOnPreTimerDisable = 0x1U, /*!< Timer disabled on Timer N-1 disable. */
kFLEXIO_TimerDisableOnTimerCompare = 0x2U, /*!< Timer disabled on Timer compare. */
kFLEXIO_TimerDisableOnTimerCompareTriggerLow = 0x3U, /*!< Timer disabled on Timer compare and Trigger Low. */
kFLEXIO_TimerDisableOnPinBothEdge = 0x4U, /*!< Timer disabled on Pin rising or falling edge. */
kFLEXIO_TimerDisableOnPinBothEdgeTriggerHigh = 0x5U, /*!< Timer disabled on Pin rising or falling edge provided
Trigger is high. */
kFLEXIO_TimerDisableOnTriggerFallingEdge = 0x6U, /*!< Timer disabled on Trigger falling edge. */
} flexio_timer_disable_condition_t;
/*! @brief Define type of timer enable condition.*/
typedef enum _flexio_timer_enable_condition
{
kFLEXIO_TimerEnabledAlways = 0x0U, /*!< Timer always enabled. */
kFLEXIO_TimerEnableOnPrevTimerEnable = 0x1U, /*!< Timer enabled on Timer N-1 enable. */
kFLEXIO_TimerEnableOnTriggerHigh = 0x2U, /*!< Timer enabled on Trigger high. */
kFLEXIO_TimerEnableOnTriggerHighPinHigh = 0x3U, /*!< Timer enabled on Trigger high and Pin high. */
kFLEXIO_TimerEnableOnPinRisingEdge = 0x4U, /*!< Timer enabled on Pin rising edge. */
kFLEXIO_TimerEnableOnPinRisingEdgeTriggerHigh = 0x5U, /*!< Timer enabled on Pin rising edge and Trigger high. */
kFLEXIO_TimerEnableOnTriggerRisingEdge = 0x6U, /*!< Timer enabled on Trigger rising edge. */
kFLEXIO_TimerEnableOnTriggerBothEdge = 0x7U, /*!< Timer enabled on Trigger rising or falling edge. */
} flexio_timer_enable_condition_t;
/*! @brief Define type of timer stop bit generate condition.*/
typedef enum _flexio_timer_stop_bit_condition
{
kFLEXIO_TimerStopBitDisabled = 0x0U, /*!< Stop bit disabled. */
kFLEXIO_TimerStopBitEnableOnTimerCompare = 0x1U, /*!< Stop bit is enabled on timer compare. */
kFLEXIO_TimerStopBitEnableOnTimerDisable = 0x2U, /*!< Stop bit is enabled on timer disable. */
kFLEXIO_TimerStopBitEnableOnTimerCompareDisable = 0x3U, /*!< Stop bit is enabled on timer compare and timer
disable. */
} flexio_timer_stop_bit_condition_t;
/*! @brief Define type of timer start bit generate condition.*/
typedef enum _flexio_timer_start_bit_condition
{
kFLEXIO_TimerStartBitDisabled = 0x0U, /*!< Start bit disabled. */
kFLEXIO_TimerStartBitEnabled = 0x1U, /*!< Start bit enabled. */
} flexio_timer_start_bit_condition_t;
/*! @brief Define type of timer polarity for shifter control. */
typedef enum _flexio_shifter_timer_polarity
{
kFLEXIO_ShifterTimerPolarityOnPositive = 0x0U, /* Shift on positive edge of shift clock. */
kFLEXIO_ShifterTimerPolarityOnNegitive = 0x1U, /* Shift on negative edge of shift clock. */
} flexio_shifter_timer_polarity_t;
/*! @brief Define type of shifter working mode.*/
typedef enum _flexio_shifter_mode
{
kFLEXIO_ShifterDisabled = 0x0U, /*!< Shifter is disabled. */
kFLEXIO_ShifterModeReceive = 0x1U, /*!< Receive mode. */
kFLEXIO_ShifterModeTransmit = 0x2U, /*!< Transmit mode. */
kFLEXIO_ShifterModeMatchStore = 0x4U, /*!< Match store mode. */
kFLEXIO_ShifterModeMatchContinuous = 0x5U, /*!< Match continuous mode. */
#if FSL_FEATURE_FLEXIO_HAS_STATE_MODE
kFLEXIO_ShifterModeState = 0x6U, /*!< SHIFTBUF contents are used for storing
programmable state attributes. */
#endif /* FSL_FEATURE_FLEXIO_HAS_STATE_MODE */
#if FSL_FEATURE_FLEXIO_HAS_LOGIC_MODE
kFLEXIO_ShifterModeLogic = 0x7U, /*!< SHIFTBUF contents are used for implementing
programmable logic look up table. */
#endif /* FSL_FEATURE_FLEXIO_HAS_LOGIC_MODE */
} flexio_shifter_mode_t;
/*! @brief Define type of shifter input source.*/
typedef enum _flexio_shifter_input_source
{
kFLEXIO_ShifterInputFromPin = 0x0U, /*!< Shifter input from pin. */
kFLEXIO_ShifterInputFromNextShifterOutput = 0x1U, /*!< Shifter input from Shifter N+1. */
} flexio_shifter_input_source_t;
/*! @brief Define of STOP bit configuration.*/
typedef enum _flexio_shifter_stop_bit
{
kFLEXIO_ShifterStopBitDisable = 0x0U, /*!< Disable shifter stop bit. */
kFLEXIO_ShifterStopBitLow = 0x2U, /*!< Set shifter stop bit to logic low level. */
kFLEXIO_ShifterStopBitHigh = 0x3U, /*!< Set shifter stop bit to logic high level. */
} flexio_shifter_stop_bit_t;
/*! @brief Define type of START bit configuration.*/
typedef enum _flexio_shifter_start_bit
{
kFLEXIO_ShifterStartBitDisabledLoadDataOnEnable = 0x0U, /*!< Disable shifter start bit, transmitter loads
data on enable. */
kFLEXIO_ShifterStartBitDisabledLoadDataOnShift = 0x1U, /*!< Disable shifter start bit, transmitter loads
data on first shift. */
kFLEXIO_ShifterStartBitLow = 0x2U, /*!< Set shifter start bit to logic low level. */
kFLEXIO_ShifterStartBitHigh = 0x3U, /*!< Set shifter start bit to logic high level. */
} flexio_shifter_start_bit_t;
/*! @brief Define FlexIO shifter buffer type*/
typedef enum _flexio_shifter_buffer_type
{
kFLEXIO_ShifterBuffer = 0x0U, /*!< Shifter Buffer N Register. */
kFLEXIO_ShifterBufferBitSwapped = 0x1U, /*!< Shifter Buffer N Bit Byte Swapped Register. */
kFLEXIO_ShifterBufferByteSwapped = 0x2U, /*!< Shifter Buffer N Byte Swapped Register. */
kFLEXIO_ShifterBufferBitByteSwapped = 0x3U, /*!< Shifter Buffer N Bit Swapped Register. */
#if defined(FSL_FEATURE_FLEXIO_HAS_SHFT_BUFFER_NIBBLE_BYTE_SWAP) && FSL_FEATURE_FLEXIO_HAS_SHFT_BUFFER_NIBBLE_BYTE_SWAP
kFLEXIO_ShifterBufferNibbleByteSwapped = 0x4U, /*!< Shifter Buffer N Nibble Byte Swapped Register. */
#endif /*FSL_FEATURE_FLEXIO_HAS_SHFT_BUFFER_NIBBLE_BYTE_SWAP*/
#if defined(FSL_FEATURE_FLEXIO_HAS_SHFT_BUFFER_HALF_WORD_SWAP) && FSL_FEATURE_FLEXIO_HAS_SHFT_BUFFER_HALF_WORD_SWAP
kFLEXIO_ShifterBufferHalfWordSwapped = 0x5U, /*!< Shifter Buffer N Half Word Swapped Register. */
#endif
#if defined(FSL_FEATURE_FLEXIO_HAS_SHFT_BUFFER_NIBBLE_SWAP) && FSL_FEATURE_FLEXIO_HAS_SHFT_BUFFER_NIBBLE_SWAP
kFLEXIO_ShifterBufferNibbleSwapped = 0x6U, /*!< Shifter Buffer N Nibble Swapped Register. */
#endif
} flexio_shifter_buffer_type_t;
/*! @brief Define FlexIO user configuration structure. */
typedef struct _flexio_config_
{
bool enableFlexio; /*!< Enable/disable FlexIO module */
bool enableInDoze; /*!< Enable/disable FlexIO operation in doze mode */
bool enableInDebug; /*!< Enable/disable FlexIO operation in debug mode */
bool enableFastAccess; /*!< Enable/disable fast access to FlexIO registers, fast access requires
the FlexIO clock to be at least twice the frequency of the bus clock. */
} flexio_config_t;
/*! @brief Define FlexIO timer configuration structure. */
typedef struct _flexio_timer_config
{
/* Trigger. */
uint32_t triggerSelect; /*!< The internal trigger selection number using MACROs. */
flexio_timer_trigger_polarity_t triggerPolarity; /*!< Trigger Polarity. */
flexio_timer_trigger_source_t triggerSource; /*!< Trigger Source, internal (see 'trgsel') or external. */
/* Pin. */
flexio_pin_config_t pinConfig; /*!< Timer Pin Configuration. */
uint32_t pinSelect; /*!< Timer Pin number Select. */
flexio_pin_polarity_t pinPolarity; /*!< Timer Pin Polarity. */
/* Timer. */
flexio_timer_mode_t timerMode; /*!< Timer work Mode. */
flexio_timer_output_t timerOutput; /*!< Configures the initial state of the Timer Output and
whether it is affected by the Timer reset. */
flexio_timer_decrement_source_t timerDecrement; /*!< Configures the source of the Timer decrement and the
source of the Shift clock. */
flexio_timer_reset_condition_t timerReset; /*!< Configures the condition that causes the timer counter
(and optionally the timer output) to be reset. */
flexio_timer_disable_condition_t timerDisable; /*!< Configures the condition that causes the Timer to be
disabled and stop decrementing. */
flexio_timer_enable_condition_t timerEnable; /*!< Configures the condition that causes the Timer to be
enabled and start decrementing. */
flexio_timer_stop_bit_condition_t timerStop; /*!< Timer STOP Bit generation. */
flexio_timer_start_bit_condition_t timerStart; /*!< Timer STRAT Bit generation. */
uint32_t timerCompare; /*!< Value for Timer Compare N Register. */
} flexio_timer_config_t;
/*! @brief Define FlexIO shifter configuration structure. */
typedef struct _flexio_shifter_config
{
/* Timer. */
uint32_t timerSelect; /*!< Selects which Timer is used for controlling the
logic/shift register and generating the Shift clock. */
flexio_shifter_timer_polarity_t timerPolarity; /*!< Timer Polarity. */
/* Pin. */
flexio_pin_config_t pinConfig; /*!< Shifter Pin Configuration. */
uint32_t pinSelect; /*!< Shifter Pin number Select. */
flexio_pin_polarity_t pinPolarity; /*!< Shifter Pin Polarity. */
/* Shifter. */
flexio_shifter_mode_t shifterMode; /*!< Configures the mode of the Shifter. */
#if FSL_FEATURE_FLEXIO_HAS_PARALLEL_WIDTH
uint32_t parallelWidth; /*!< Configures the parallel width when using parallel mode.*/
#endif /* FSL_FEATURE_FLEXIO_HAS_PARALLEL_WIDTH */
flexio_shifter_input_source_t inputSource; /*!< Selects the input source for the shifter. */
flexio_shifter_stop_bit_t shifterStop; /*!< Shifter STOP bit. */
flexio_shifter_start_bit_t shifterStart; /*!< Shifter START bit. */
} flexio_shifter_config_t;
/*! @brief typedef for FlexIO simulated driver interrupt handler.*/
typedef void (*flexio_isr_t)(void *base, void *handle);
/*******************************************************************************
* API
******************************************************************************/
#if defined(__cplusplus)
extern "C" {
#endif /*_cplusplus*/
/*!
* @name FlexIO Initialization and De-initialization
* @{
*/
/*!
* @brief Gets the default configuration to configure the FlexIO module. The configuration
* can used directly to call the FLEXIO_Configure().
*
* Example:
@code
flexio_config_t config;
FLEXIO_GetDefaultConfig(&config);
@endcode
*
* @param userConfig pointer to flexio_config_t structure
*/
void FLEXIO_GetDefaultConfig(flexio_config_t *userConfig);
/*!
* @brief Configures the FlexIO with a FlexIO configuration. The configuration structure
* can be filled by the user or be set with default values by FLEXIO_GetDefaultConfig().
*
* Example
@code
flexio_config_t config = {
.enableFlexio = true,
.enableInDoze = false,
.enableInDebug = true,
.enableFastAccess = false
};
FLEXIO_Configure(base, &config);
@endcode
*
* @param base FlexIO peripheral base address
* @param userConfig pointer to flexio_config_t structure
*/
void FLEXIO_Init(FLEXIO_Type *base, const flexio_config_t *userConfig);
/*!
* @brief Gates the FlexIO clock. Call this API to stop the FlexIO clock.
*
* @note After calling this API, call the FLEXO_Init to use the FlexIO module.
*
* @param base FlexIO peripheral base address
*/
void FLEXIO_Deinit(FLEXIO_Type *base);
/* @} */
/*!
* @name FlexIO Basic Operation
* @{
*/
/*!
* @brief Resets the FlexIO module.
*
* @param base FlexIO peripheral base address
*/
void FLEXIO_Reset(FLEXIO_Type *base);
/*!
* @brief Enables the FlexIO module operation.
*
* @param base FlexIO peripheral base address
* @param enable true to enable, false to disable.
*/
static inline void FLEXIO_Enable(FLEXIO_Type *base, bool enable)
{
if (enable)
{
base->CTRL |= FLEXIO_CTRL_FLEXEN_MASK;
}
else
{
base->CTRL &= ~FLEXIO_CTRL_FLEXEN_MASK;
}
}
#if defined(FSL_FEATURE_FLEXIO_HAS_PIN_STATUS) && FSL_FEATURE_FLEXIO_HAS_PIN_STATUS
/*!
* @brief Reads the input data on each of the FlexIO pins.
*
* @param base FlexIO peripheral base address
* @return FlexIO pin input data
*/
static inline uint32_t FLEXIO_ReadPinInput(FLEXIO_Type *base)
{
return base->PIN;
}
#endif /*FSL_FEATURE_FLEXIO_HAS_PIN_STATUS*/
#if defined(FSL_FEATURE_FLEXIO_HAS_STATE_MODE) && FSL_FEATURE_FLEXIO_HAS_STATE_MODE
/*!
* @brief Gets the current state pointer for state mode use.
*
* @param base FlexIO peripheral base address
* @return current State pointer
*/
static inline uint8_t FLEXIO_GetShifterState(FLEXIO_Type *base)
{
return ((base->SHIFTSTATE) & FLEXIO_SHIFTSTATE_STATE_MASK);
}
#endif /*FSL_FEATURE_FLEXIO_HAS_STATE_MODE*/
/*!
* @brief Configures the shifter with the shifter configuration. The configuration structure
* covers both the SHIFTCTL and SHIFTCFG registers. To configure the shifter to the proper
* mode, select which timer controls the shifter to shift, whether to generate start bit/stop
* bit, and the polarity of start bit and stop bit.
*
* Example
@code
flexio_shifter_config_t config = {
.timerSelect = 0,
.timerPolarity = kFLEXIO_ShifterTimerPolarityOnPositive,
.pinConfig = kFLEXIO_PinConfigOpenDrainOrBidirection,
.pinPolarity = kFLEXIO_PinActiveLow,
.shifterMode = kFLEXIO_ShifterModeTransmit,
.inputSource = kFLEXIO_ShifterInputFromPin,
.shifterStop = kFLEXIO_ShifterStopBitHigh,
.shifterStart = kFLEXIO_ShifterStartBitLow
};
FLEXIO_SetShifterConfig(base, &config);
@endcode
*
* @param base FlexIO peripheral base address
* @param index Shifter index
* @param shifterConfig Pointer to flexio_shifter_config_t structure
*/
void FLEXIO_SetShifterConfig(FLEXIO_Type *base, uint8_t index, const flexio_shifter_config_t *shifterConfig);
/*!
* @brief Configures the timer with the timer configuration. The configuration structure
* covers both the TIMCTL and TIMCFG registers. To configure the timer to the proper
* mode, select trigger source for timer and the timer pin output and the timing for timer.
*
* Example
@code
flexio_timer_config_t config = {
.triggerSelect = FLEXIO_TIMER_TRIGGER_SEL_SHIFTnSTAT(0),
.triggerPolarity = kFLEXIO_TimerTriggerPolarityActiveLow,
.triggerSource = kFLEXIO_TimerTriggerSourceInternal,
.pinConfig = kFLEXIO_PinConfigOpenDrainOrBidirection,
.pinSelect = 0,
.pinPolarity = kFLEXIO_PinActiveHigh,
.timerMode = kFLEXIO_TimerModeDual8BitBaudBit,
.timerOutput = kFLEXIO_TimerOutputZeroNotAffectedByReset,
.timerDecrement = kFLEXIO_TimerDecSrcOnFlexIOClockShiftTimerOutput,
.timerReset = kFLEXIO_TimerResetOnTimerPinEqualToTimerOutput,
.timerDisable = kFLEXIO_TimerDisableOnTimerCompare,
.timerEnable = kFLEXIO_TimerEnableOnTriggerHigh,
.timerStop = kFLEXIO_TimerStopBitEnableOnTimerDisable,
.timerStart = kFLEXIO_TimerStartBitEnabled
};
FLEXIO_SetTimerConfig(base, &config);
@endcode
*
* @param base FlexIO peripheral base address
* @param index Timer index
* @param timerConfig Pointer to the flexio_timer_config_t structure
*/
void FLEXIO_SetTimerConfig(FLEXIO_Type *base, uint8_t index, const flexio_timer_config_t *timerConfig);
/* @} */
/*!
* @name FlexIO Interrupt Operation
* @{
*/
/*!
* @brief Enables the shifter status interrupt. The interrupt generates when the corresponding SSF is set.
*
* @param base FlexIO peripheral base address
* @param mask The shifter status mask which can be calculated by (1 << shifter index)
* @note For multiple shifter status interrupt enable, for example, two shifter status enable, can calculate
* the mask by using ((1 << shifter index0) | (1 << shifter index1))
*/
static inline void FLEXIO_EnableShifterStatusInterrupts(FLEXIO_Type *base, uint32_t mask)
{
base->SHIFTSIEN |= mask;
}
/*!
* @brief Disables the shifter status interrupt. The interrupt won't generate when the corresponding SSF is set.
*
* @param base FlexIO peripheral base address
* @param mask The shifter status mask which can be calculated by (1 << shifter index)
* @note For multiple shifter status interrupt enable, for example, two shifter status enable, can calculate
* the mask by using ((1 << shifter index0) | (1 << shifter index1))
*/
static inline void FLEXIO_DisableShifterStatusInterrupts(FLEXIO_Type *base, uint32_t mask)
{
base->SHIFTSIEN &= ~mask;
}
/*!
* @brief Enables the shifter error interrupt. The interrupt generates when the corresponding SEF is set.
*
* @param base FlexIO peripheral base address
* @param mask The shifter error mask which can be calculated by (1 << shifter index)
* @note For multiple shifter error interrupt enable, for example, two shifter error enable, can calculate
* the mask by using ((1 << shifter index0) | (1 << shifter index1))
*/
static inline void FLEXIO_EnableShifterErrorInterrupts(FLEXIO_Type *base, uint32_t mask)
{
base->SHIFTEIEN |= mask;
}
/*!
* @brief Disables the shifter error interrupt. The interrupt won't generate when the corresponding SEF is set.
*
* @param base FlexIO peripheral base address
* @param mask The shifter error mask which can be calculated by (1 << shifter index)
* @note For multiple shifter error interrupt enable, for example, two shifter error enable, can calculate
* the mask by using ((1 << shifter index0) | (1 << shifter index1))
*/
static inline void FLEXIO_DisableShifterErrorInterrupts(FLEXIO_Type *base, uint32_t mask)
{
base->SHIFTEIEN &= ~mask;
}
/*!
* @brief Enables the timer status interrupt. The interrupt generates when the corresponding SSF is set.
*
* @param base FlexIO peripheral base address
* @param mask The timer status mask which can be calculated by (1 << timer index)
* @note For multiple timer status interrupt enable, for example, two timer status enable, can calculate
* the mask by using ((1 << timer index0) | (1 << timer index1))
*/
static inline void FLEXIO_EnableTimerStatusInterrupts(FLEXIO_Type *base, uint32_t mask)
{
base->TIMIEN |= mask;
}
/*!
* @brief Disables the timer status interrupt. The interrupt won't generate when the corresponding SSF is set.
*
* @param base FlexIO peripheral base address
* @param mask The timer status mask which can be calculated by (1 << timer index)
* @note For multiple timer status interrupt enable, for example, two timer status enable, can calculate
* the mask by using ((1 << timer index0) | (1 << timer index1))
*/
static inline void FLEXIO_DisableTimerStatusInterrupts(FLEXIO_Type *base, uint32_t mask)
{
base->TIMIEN &= ~mask;
}
/* @} */
/*!
* @name FlexIO Status Operation
* @{
*/
/*!
* @brief Gets the shifter status flags.
*
* @param base FlexIO peripheral base address
* @return Shifter status flags
*/
static inline uint32_t FLEXIO_GetShifterStatusFlags(FLEXIO_Type *base)
{
return ((base->SHIFTSTAT) & FLEXIO_SHIFTSTAT_SSF_MASK);
}
/*!
* @brief Clears the shifter status flags.
*
* @param base FlexIO peripheral base address
* @param mask The shifter status mask which can be calculated by (1 << shifter index)
* @note For clearing multiple shifter status flags, for example, two shifter status flags, can calculate
* the mask by using ((1 << shifter index0) | (1 << shifter index1))
*/
static inline void FLEXIO_ClearShifterStatusFlags(FLEXIO_Type *base, uint32_t mask)
{
base->SHIFTSTAT = mask;
}
/*!
* @brief Gets the shifter error flags.
*
* @param base FlexIO peripheral base address
* @return Shifter error flags
*/
static inline uint32_t FLEXIO_GetShifterErrorFlags(FLEXIO_Type *base)
{
return ((base->SHIFTERR) & FLEXIO_SHIFTERR_SEF_MASK);
}
/*!
* @brief Clears the shifter error flags.
*
* @param base FlexIO peripheral base address
* @param mask The shifter error mask which can be calculated by (1 << shifter index)
* @note For clearing multiple shifter error flags, for example, two shifter error flags, can calculate
* the mask by using ((1 << shifter index0) | (1 << shifter index1))
*/
static inline void FLEXIO_ClearShifterErrorFlags(FLEXIO_Type *base, uint32_t mask)
{
base->SHIFTERR = mask;
}
/*!
* @brief Gets the timer status flags.
*
* @param base FlexIO peripheral base address
* @return Timer status flags
*/
static inline uint32_t FLEXIO_GetTimerStatusFlags(FLEXIO_Type *base)
{
return ((base->TIMSTAT) & FLEXIO_TIMSTAT_TSF_MASK);
}
/*!
* @brief Clears the timer status flags.
*
* @param base FlexIO peripheral base address
* @param mask The timer status mask which can be calculated by (1 << timer index)
* @note For clearing multiple timer status flags, for example, two timer status flags, can calculate
* the mask by using ((1 << timer index0) | (1 << timer index1))
*/
static inline void FLEXIO_ClearTimerStatusFlags(FLEXIO_Type *base, uint32_t mask)
{
base->TIMSTAT = mask;
}
/* @} */
/*!
* @name FlexIO DMA Operation
* @{
*/
/*!
* @brief Enables/disables the shifter status DMA. The DMA request generates when the corresponding SSF is set.
*
* @note For multiple shifter status DMA enables, for example, calculate
* the mask by using ((1 << shifter index0) | (1 << shifter index1))
*
* @param base FlexIO peripheral base address
* @param mask The shifter status mask which can be calculated by (1 << shifter index)
* @param enable True to enable, false to disable.
*/
static inline void FLEXIO_EnableShifterStatusDMA(FLEXIO_Type *base, uint32_t mask, bool enable)
{
if (enable)
{
base->SHIFTSDEN |= mask;
}
else
{
base->SHIFTSDEN &= ~mask;
}
}
/*!
* @brief Gets the shifter buffer address for the DMA transfer usage.
*
* @param base FlexIO peripheral base address
* @param type Shifter type of flexio_shifter_buffer_type_t
* @param index Shifter index
* @return Corresponding shifter buffer index
*/
uint32_t FLEXIO_GetShifterBufferAddress(FLEXIO_Type *base, flexio_shifter_buffer_type_t type, uint8_t index);
/*!
* @brief Registers the handle and the interrupt handler for the FlexIO-simulated peripheral.
*
* @param base Pointer to the FlexIO simulated peripheral type.
* @param handle Pointer to the handler for FlexIO simulated peripheral.
* @param isr FlexIO simulated peripheral interrupt handler.
* @retval kStatus_Success Successfully create the handle.
* @retval kStatus_OutOfRange The FlexIO type/handle/ISR table out of range.
*/
status_t FLEXIO_RegisterHandleIRQ(void *base, void *handle, flexio_isr_t isr);
/*!
* @brief Unregisters the handle and the interrupt handler for the FlexIO-simulated peripheral.
*
* @param base Pointer to the FlexIO simulated peripheral type.
* @retval kStatus_Success Successfully create the handle.
* @retval kStatus_OutOfRange The FlexIO type/handle/ISR table out of range.
*/
status_t FLEXIO_UnregisterHandleIRQ(void *base);
/* @} */
#if defined(__cplusplus)
}
#endif /*_cplusplus*/
/*@}*/
#endif /*_FSL_FLEXIO_H_*/

View File

@ -0,0 +1,781 @@
/*
* Copyright (c) 2015, Freescale Semiconductor, Inc.
* Copyright 2016-2017 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include "fsl_flexio_i2c_master.h"
/*******************************************************************************
* Definitions
******************************************************************************/
/*! @brief FLEXIO I2C transfer state */
enum _flexio_i2c_master_transfer_states
{
kFLEXIO_I2C_Idle = 0x0U, /*!< I2C bus idle */
kFLEXIO_I2C_CheckAddress = 0x1U, /*!< 7-bit address check state */
kFLEXIO_I2C_SendCommand = 0x2U, /*!< Send command byte phase */
kFLEXIO_I2C_SendData = 0x3U, /*!< Send data transfer phase*/
kFLEXIO_I2C_ReceiveDataBegin = 0x4U, /*!< Receive data begin transfer phase*/
kFLEXIO_I2C_ReceiveData = 0x5U, /*!< Receive data transfer phase*/
};
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
extern const clock_ip_name_t s_flexioClocks[];
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
extern FLEXIO_Type *const s_flexioBases[];
/*******************************************************************************
* Prototypes
******************************************************************************/
extern uint32_t FLEXIO_GetInstance(FLEXIO_Type *base);
/*!
* @brief Set up master transfer, send slave address and decide the initial
* transfer state.
*
* @param base pointer to FLEXIO_I2C_Type structure
* @param handle pointer to flexio_i2c_master_handle_t structure which stores the transfer state
* @param transfer pointer to flexio_i2c_master_transfer_t structure
*/
static status_t FLEXIO_I2C_MasterTransferInitStateMachine(FLEXIO_I2C_Type *base,
flexio_i2c_master_handle_t *handle,
flexio_i2c_master_transfer_t *xfer);
/*!
* @brief Master run transfer state machine to perform a byte of transfer.
*
* @param base pointer to FLEXIO_I2C_Type structure
* @param handle pointer to flexio_i2c_master_handle_t structure which stores the transfer state
* @param statusFlags flexio i2c hardware status
* @retval kStatus_Success Successfully run state machine
* @retval kStatus_FLEXIO_I2C_Nak Receive Nak during transfer
*/
static status_t FLEXIO_I2C_MasterTransferRunStateMachine(FLEXIO_I2C_Type *base,
flexio_i2c_master_handle_t *handle,
uint32_t statusFlags);
/*!
* @brief Complete transfer, disable interrupt and call callback.
*
* @param base pointer to FLEXIO_I2C_Type structure
* @param handle pointer to flexio_i2c_master_handle_t structure which stores the transfer state
* @param status flexio transfer status
*/
static void FLEXIO_I2C_MasterTransferComplete(FLEXIO_I2C_Type *base,
flexio_i2c_master_handle_t *handle,
status_t status);
/*******************************************************************************
* Codes
******************************************************************************/
uint32_t FLEXIO_I2C_GetInstance(FLEXIO_I2C_Type *base)
{
return FLEXIO_GetInstance(base->flexioBase);
}
static status_t FLEXIO_I2C_MasterTransferInitStateMachine(FLEXIO_I2C_Type *base,
flexio_i2c_master_handle_t *handle,
flexio_i2c_master_transfer_t *xfer)
{
bool needRestart;
uint32_t byteCount;
/* Init the handle member. */
handle->transfer.slaveAddress = xfer->slaveAddress;
handle->transfer.direction = xfer->direction;
handle->transfer.subaddress = xfer->subaddress;
handle->transfer.subaddressSize = xfer->subaddressSize;
handle->transfer.data = xfer->data;
handle->transfer.dataSize = xfer->dataSize;
handle->transfer.flags = xfer->flags;
handle->transferSize = xfer->dataSize;
/* Initial state, i2c check address state. */
handle->state = kFLEXIO_I2C_CheckAddress;
/* Clear all status before transfer. */
FLEXIO_I2C_MasterClearStatusFlags(base, kFLEXIO_I2C_ReceiveNakFlag);
/* Calculate whether need to send re-start. */
needRestart = (handle->transfer.subaddressSize != 0) && (handle->transfer.direction == kFLEXIO_I2C_Read);
/* Calculate total byte count in a frame. */
byteCount = 1;
if (!needRestart)
{
byteCount += handle->transfer.dataSize;
}
if (handle->transfer.subaddressSize != 0)
{
byteCount += handle->transfer.subaddressSize;
/* Next state, send command byte. */
handle->state = kFLEXIO_I2C_SendCommand;
}
/* Configure data count. */
if (FLEXIO_I2C_MasterSetTransferCount(base, byteCount) != kStatus_Success)
{
return kStatus_InvalidArgument;
}
while (!((FLEXIO_GetShifterStatusFlags(base->flexioBase) & (1U << base->shifterIndex[0]))))
{
}
/* Send address byte first. */
if (needRestart)
{
FLEXIO_I2C_MasterStart(base, handle->transfer.slaveAddress, kFLEXIO_I2C_Write);
}
else
{
FLEXIO_I2C_MasterStart(base, handle->transfer.slaveAddress, handle->transfer.direction);
}
return kStatus_Success;
}
static status_t FLEXIO_I2C_MasterTransferRunStateMachine(FLEXIO_I2C_Type *base,
flexio_i2c_master_handle_t *handle,
uint32_t statusFlags)
{
if (statusFlags & kFLEXIO_I2C_ReceiveNakFlag)
{
/* Clear receive nak flag. */
FLEXIO_ClearShifterErrorFlags(base->flexioBase, 1U << base->shifterIndex[1]);
if ((!((handle->state == kFLEXIO_I2C_SendData) && (handle->transfer.dataSize == 0U))) &&
(!(((handle->state == kFLEXIO_I2C_ReceiveData) || (handle->state == kFLEXIO_I2C_ReceiveDataBegin)) &&
(handle->transfer.dataSize == 1U))))
{
FLEXIO_I2C_MasterReadByte(base);
FLEXIO_I2C_MasterAbortStop(base);
handle->state = kFLEXIO_I2C_Idle;
return kStatus_FLEXIO_I2C_Nak;
}
}
if (handle->state == kFLEXIO_I2C_CheckAddress)
{
if (handle->transfer.direction == kFLEXIO_I2C_Write)
{
/* Next state, send data. */
handle->state = kFLEXIO_I2C_SendData;
}
else
{
/* Next state, receive data begin. */
handle->state = kFLEXIO_I2C_ReceiveDataBegin;
}
}
if ((statusFlags & kFLEXIO_I2C_RxFullFlag) && (handle->state != kFLEXIO_I2C_ReceiveData))
{
FLEXIO_I2C_MasterReadByte(base);
}
switch (handle->state)
{
case kFLEXIO_I2C_SendCommand:
if (statusFlags & kFLEXIO_I2C_TxEmptyFlag)
{
if (handle->transfer.subaddressSize > 0)
{
handle->transfer.subaddressSize--;
FLEXIO_I2C_MasterWriteByte(
base, ((handle->transfer.subaddress) >> (8 * handle->transfer.subaddressSize)));
if (handle->transfer.subaddressSize == 0)
{
/* Load re-start in advance. */
if (handle->transfer.direction == kFLEXIO_I2C_Read)
{
while (!((FLEXIO_GetShifterStatusFlags(base->flexioBase) & (1U << base->shifterIndex[0]))))
{
}
FLEXIO_I2C_MasterRepeatedStart(base);
}
}
}
else
{
if (handle->transfer.direction == kFLEXIO_I2C_Write)
{
/* Next state, send data. */
handle->state = kFLEXIO_I2C_SendData;
/* Send first byte of data. */
if (handle->transfer.dataSize > 0)
{
FLEXIO_I2C_MasterWriteByte(base, *handle->transfer.data);
handle->transfer.data++;
handle->transfer.dataSize--;
}
}
else
{
FLEXIO_I2C_MasterSetTransferCount(base, (handle->transfer.dataSize + 1));
FLEXIO_I2C_MasterStart(base, handle->transfer.slaveAddress, kFLEXIO_I2C_Read);
/* Next state, receive data begin. */
handle->state = kFLEXIO_I2C_ReceiveDataBegin;
}
}
}
break;
/* Send command byte. */
case kFLEXIO_I2C_SendData:
if (statusFlags & kFLEXIO_I2C_TxEmptyFlag)
{
/* Send one byte of data. */
if (handle->transfer.dataSize > 0)
{
FLEXIO_I2C_MasterWriteByte(base, *handle->transfer.data);
handle->transfer.data++;
handle->transfer.dataSize--;
}
else
{
FLEXIO_I2C_MasterStop(base);
while (!(FLEXIO_I2C_MasterGetStatusFlags(base) & kFLEXIO_I2C_RxFullFlag))
{
}
FLEXIO_I2C_MasterReadByte(base);
handle->state = kFLEXIO_I2C_Idle;
}
}
break;
case kFLEXIO_I2C_ReceiveDataBegin:
if (statusFlags & kFLEXIO_I2C_RxFullFlag)
{
handle->state = kFLEXIO_I2C_ReceiveData;
/* Send nak at the last receive byte. */
if (handle->transfer.dataSize == 1)
{
FLEXIO_I2C_MasterEnableAck(base, false);
while (!((FLEXIO_GetShifterStatusFlags(base->flexioBase) & (1U << base->shifterIndex[0]))))
{
}
FLEXIO_I2C_MasterStop(base);
}
else
{
FLEXIO_I2C_MasterEnableAck(base, true);
}
}
else if (statusFlags & kFLEXIO_I2C_TxEmptyFlag)
{
/* Read one byte of data. */
FLEXIO_I2C_MasterWriteByte(base, 0xFFFFFFFFU);
}
else
{
}
break;
case kFLEXIO_I2C_ReceiveData:
if (statusFlags & kFLEXIO_I2C_RxFullFlag)
{
*handle->transfer.data = FLEXIO_I2C_MasterReadByte(base);
handle->transfer.data++;
if (handle->transfer.dataSize--)
{
if (handle->transfer.dataSize == 0)
{
FLEXIO_I2C_MasterDisableInterrupts(base, kFLEXIO_I2C_RxFullInterruptEnable);
handle->state = kFLEXIO_I2C_Idle;
}
/* Send nak at the last receive byte. */
if (handle->transfer.dataSize == 1)
{
FLEXIO_I2C_MasterEnableAck(base, false);
while (!((FLEXIO_GetShifterStatusFlags(base->flexioBase) & (1U << base->shifterIndex[0]))))
{
}
FLEXIO_I2C_MasterStop(base);
}
}
}
else if (statusFlags & kFLEXIO_I2C_TxEmptyFlag)
{
if (handle->transfer.dataSize > 1)
{
FLEXIO_I2C_MasterWriteByte(base, 0xFFFFFFFFU);
}
}
else
{
}
break;
default:
break;
}
return kStatus_Success;
}
static void FLEXIO_I2C_MasterTransferComplete(FLEXIO_I2C_Type *base,
flexio_i2c_master_handle_t *handle,
status_t status)
{
FLEXIO_I2C_MasterDisableInterrupts(base, kFLEXIO_I2C_TxEmptyInterruptEnable | kFLEXIO_I2C_RxFullInterruptEnable);
if (handle->completionCallback)
{
handle->completionCallback(base, handle, status, handle->userData);
}
}
status_t FLEXIO_I2C_MasterInit(FLEXIO_I2C_Type *base, flexio_i2c_master_config_t *masterConfig, uint32_t srcClock_Hz)
{
assert(base && masterConfig);
flexio_shifter_config_t shifterConfig;
flexio_timer_config_t timerConfig;
uint32_t controlVal = 0;
uint16_t timerDiv = 0;
status_t result = kStatus_Success;
memset(&shifterConfig, 0, sizeof(shifterConfig));
memset(&timerConfig, 0, sizeof(timerConfig));
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
/* Ungate flexio clock. */
CLOCK_EnableClock(s_flexioClocks[FLEXIO_I2C_GetInstance(base)]);
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
FLEXIO_Reset(base->flexioBase);
/* Do hardware configuration. */
/* 1. Configure the shifter 0 for tx. */
shifterConfig.timerSelect = base->timerIndex[1];
shifterConfig.timerPolarity = kFLEXIO_ShifterTimerPolarityOnPositive;
shifterConfig.pinConfig = kFLEXIO_PinConfigOpenDrainOrBidirection;
shifterConfig.pinSelect = base->SDAPinIndex;
shifterConfig.pinPolarity = kFLEXIO_PinActiveLow;
shifterConfig.shifterMode = kFLEXIO_ShifterModeTransmit;
shifterConfig.inputSource = kFLEXIO_ShifterInputFromPin;
shifterConfig.shifterStop = kFLEXIO_ShifterStopBitHigh;
shifterConfig.shifterStart = kFLEXIO_ShifterStartBitLow;
FLEXIO_SetShifterConfig(base->flexioBase, base->shifterIndex[0], &shifterConfig);
/* 2. Configure the shifter 1 for rx. */
shifterConfig.timerSelect = base->timerIndex[1];
shifterConfig.timerPolarity = kFLEXIO_ShifterTimerPolarityOnNegitive;
shifterConfig.pinConfig = kFLEXIO_PinConfigOutputDisabled;
shifterConfig.pinSelect = base->SDAPinIndex;
shifterConfig.pinPolarity = kFLEXIO_PinActiveHigh;
shifterConfig.shifterMode = kFLEXIO_ShifterModeReceive;
shifterConfig.inputSource = kFLEXIO_ShifterInputFromPin;
shifterConfig.shifterStop = kFLEXIO_ShifterStopBitLow;
shifterConfig.shifterStart = kFLEXIO_ShifterStartBitDisabledLoadDataOnEnable;
FLEXIO_SetShifterConfig(base->flexioBase, base->shifterIndex[1], &shifterConfig);
/*3. Configure the timer 0 for generating bit clock. */
timerConfig.triggerSelect = FLEXIO_TIMER_TRIGGER_SEL_SHIFTnSTAT(base->shifterIndex[0]);
timerConfig.triggerPolarity = kFLEXIO_TimerTriggerPolarityActiveLow;
timerConfig.triggerSource = kFLEXIO_TimerTriggerSourceInternal;
timerConfig.pinConfig = kFLEXIO_PinConfigOpenDrainOrBidirection;
timerConfig.pinSelect = base->SCLPinIndex;
timerConfig.pinPolarity = kFLEXIO_PinActiveHigh;
timerConfig.timerMode = kFLEXIO_TimerModeDual8BitBaudBit;
timerConfig.timerOutput = kFLEXIO_TimerOutputZeroNotAffectedByReset;
timerConfig.timerDecrement = kFLEXIO_TimerDecSrcOnFlexIOClockShiftTimerOutput;
timerConfig.timerReset = kFLEXIO_TimerResetOnTimerPinEqualToTimerOutput;
timerConfig.timerDisable = kFLEXIO_TimerDisableOnTimerCompare;
timerConfig.timerEnable = kFLEXIO_TimerEnableOnTriggerHigh;
timerConfig.timerStop = kFLEXIO_TimerStopBitEnableOnTimerDisable;
timerConfig.timerStart = kFLEXIO_TimerStartBitEnabled;
/* Set TIMCMP[7:0] = (baud rate divider / 2) - 1. */
timerDiv = (srcClock_Hz / masterConfig->baudRate_Bps) / 2 - 1;
if (timerDiv > 0xFFU)
{
result = kStatus_InvalidArgument;
return result;
}
timerConfig.timerCompare = timerDiv;
FLEXIO_SetTimerConfig(base->flexioBase, base->timerIndex[0], &timerConfig);
/* 4. Configure the timer 1 for controlling shifters. */
timerConfig.triggerSelect = FLEXIO_TIMER_TRIGGER_SEL_SHIFTnSTAT(base->shifterIndex[0]);
timerConfig.triggerPolarity = kFLEXIO_TimerTriggerPolarityActiveLow;
timerConfig.triggerSource = kFLEXIO_TimerTriggerSourceInternal;
timerConfig.pinConfig = kFLEXIO_PinConfigOutputDisabled;
timerConfig.pinSelect = base->SCLPinIndex;
timerConfig.pinPolarity = kFLEXIO_PinActiveLow;
timerConfig.timerMode = kFLEXIO_TimerModeSingle16Bit;
timerConfig.timerOutput = kFLEXIO_TimerOutputOneNotAffectedByReset;
timerConfig.timerDecrement = kFLEXIO_TimerDecSrcOnPinInputShiftPinInput;
timerConfig.timerReset = kFLEXIO_TimerResetNever;
timerConfig.timerDisable = kFLEXIO_TimerDisableOnPreTimerDisable;
timerConfig.timerEnable = kFLEXIO_TimerEnableOnPrevTimerEnable;
timerConfig.timerStop = kFLEXIO_TimerStopBitEnableOnTimerCompare;
timerConfig.timerStart = kFLEXIO_TimerStartBitEnabled;
/* Set TIMCMP[15:0] = (number of bits x 2) - 1. */
timerConfig.timerCompare = 8 * 2 - 1;
FLEXIO_SetTimerConfig(base->flexioBase, base->timerIndex[1], &timerConfig);
/* Configure FLEXIO I2C Master. */
controlVal = base->flexioBase->CTRL;
controlVal &=
~(FLEXIO_CTRL_DOZEN_MASK | FLEXIO_CTRL_DBGE_MASK | FLEXIO_CTRL_FASTACC_MASK | FLEXIO_CTRL_FLEXEN_MASK);
controlVal |= (FLEXIO_CTRL_DBGE(masterConfig->enableInDebug) | FLEXIO_CTRL_FASTACC(masterConfig->enableFastAccess) |
FLEXIO_CTRL_FLEXEN(masterConfig->enableMaster));
if (!masterConfig->enableInDoze)
{
controlVal |= FLEXIO_CTRL_DOZEN_MASK;
}
base->flexioBase->CTRL = controlVal;
return result;
}
void FLEXIO_I2C_MasterDeinit(FLEXIO_I2C_Type *base)
{
FLEXIO_Deinit(base->flexioBase);
}
void FLEXIO_I2C_MasterGetDefaultConfig(flexio_i2c_master_config_t *masterConfig)
{
assert(masterConfig);
masterConfig->enableMaster = true;
masterConfig->enableInDoze = false;
masterConfig->enableInDebug = true;
masterConfig->enableFastAccess = false;
/* Default baud rate at 100kbps. */
masterConfig->baudRate_Bps = 100000U;
}
uint32_t FLEXIO_I2C_MasterGetStatusFlags(FLEXIO_I2C_Type *base)
{
uint32_t status = 0;
status =
((FLEXIO_GetShifterStatusFlags(base->flexioBase) & (1U << base->shifterIndex[0])) >> base->shifterIndex[0]);
status |=
(((FLEXIO_GetShifterStatusFlags(base->flexioBase) & (1U << base->shifterIndex[1])) >> (base->shifterIndex[1]))
<< 1U);
status |=
(((FLEXIO_GetShifterErrorFlags(base->flexioBase) & (1U << base->shifterIndex[1])) >> (base->shifterIndex[1]))
<< 2U);
return status;
}
void FLEXIO_I2C_MasterClearStatusFlags(FLEXIO_I2C_Type *base, uint32_t mask)
{
if (mask & kFLEXIO_I2C_TxEmptyFlag)
{
FLEXIO_ClearShifterStatusFlags(base->flexioBase, 1U << base->shifterIndex[0]);
}
if (mask & kFLEXIO_I2C_RxFullFlag)
{
FLEXIO_ClearShifterStatusFlags(base->flexioBase, 1U << base->shifterIndex[1]);
}
if (mask & kFLEXIO_I2C_ReceiveNakFlag)
{
FLEXIO_ClearShifterErrorFlags(base->flexioBase, 1U << base->shifterIndex[1]);
}
}
void FLEXIO_I2C_MasterEnableInterrupts(FLEXIO_I2C_Type *base, uint32_t mask)
{
if (mask & kFLEXIO_I2C_TxEmptyInterruptEnable)
{
FLEXIO_EnableShifterStatusInterrupts(base->flexioBase, 1U << base->shifterIndex[0]);
}
if (mask & kFLEXIO_I2C_RxFullInterruptEnable)
{
FLEXIO_EnableShifterStatusInterrupts(base->flexioBase, 1U << base->shifterIndex[1]);
}
}
void FLEXIO_I2C_MasterDisableInterrupts(FLEXIO_I2C_Type *base, uint32_t mask)
{
if (mask & kFLEXIO_I2C_TxEmptyInterruptEnable)
{
FLEXIO_DisableShifterStatusInterrupts(base->flexioBase, 1U << base->shifterIndex[0]);
}
if (mask & kFLEXIO_I2C_RxFullInterruptEnable)
{
FLEXIO_DisableShifterStatusInterrupts(base->flexioBase, 1U << base->shifterIndex[1]);
}
}
void FLEXIO_I2C_MasterSetBaudRate(FLEXIO_I2C_Type *base, uint32_t baudRate_Bps, uint32_t srcClock_Hz)
{
uint16_t timerDiv = 0;
uint16_t timerCmp = 0;
FLEXIO_Type *flexioBase = base->flexioBase;
/* Set TIMCMP[7:0] = (baud rate divider / 2) - 1.*/
timerDiv = srcClock_Hz / baudRate_Bps;
timerDiv = timerDiv / 2 - 1U;
timerCmp = flexioBase->TIMCMP[base->timerIndex[0]];
timerCmp &= 0xFF00;
timerCmp |= timerDiv;
flexioBase->TIMCMP[base->timerIndex[0]] = timerCmp;
}
status_t FLEXIO_I2C_MasterSetTransferCount(FLEXIO_I2C_Type *base, uint8_t count)
{
if (count > 14U)
{
return kStatus_InvalidArgument;
}
uint16_t timerCmp = 0;
uint32_t timerConfig = 0;
FLEXIO_Type *flexioBase = base->flexioBase;
timerCmp = flexioBase->TIMCMP[base->timerIndex[0]];
timerCmp &= 0x00FFU;
timerCmp |= (count * 18 + 1U) << 8U;
flexioBase->TIMCMP[base->timerIndex[0]] = timerCmp;
timerConfig = flexioBase->TIMCFG[base->timerIndex[0]];
timerConfig &= ~FLEXIO_TIMCFG_TIMDIS_MASK;
timerConfig |= FLEXIO_TIMCFG_TIMDIS(kFLEXIO_TimerDisableOnTimerCompare);
flexioBase->TIMCFG[base->timerIndex[0]] = timerConfig;
return kStatus_Success;
}
void FLEXIO_I2C_MasterStart(FLEXIO_I2C_Type *base, uint8_t address, flexio_i2c_direction_t direction)
{
uint32_t data;
data = ((uint32_t)address) << 1U | ((direction == kFLEXIO_I2C_Read) ? 1U : 0U);
FLEXIO_I2C_MasterWriteByte(base, data);
}
void FLEXIO_I2C_MasterRepeatedStart(FLEXIO_I2C_Type *base)
{
/* Prepare for RESTART condition, no stop.*/
FLEXIO_I2C_MasterWriteByte(base, 0xFFFFFFFFU);
}
void FLEXIO_I2C_MasterStop(FLEXIO_I2C_Type *base)
{
/* Prepare normal stop. */
FLEXIO_I2C_MasterSetTransferCount(base, 0x0U);
FLEXIO_I2C_MasterWriteByte(base, 0x0U);
}
void FLEXIO_I2C_MasterAbortStop(FLEXIO_I2C_Type *base)
{
uint32_t tmpConfig;
/* Prepare abort stop. */
tmpConfig = base->flexioBase->TIMCFG[base->timerIndex[0]];
tmpConfig &= ~FLEXIO_TIMCFG_TIMDIS_MASK;
tmpConfig |= FLEXIO_TIMCFG_TIMDIS(kFLEXIO_TimerDisableOnPinBothEdge);
base->flexioBase->TIMCFG[base->timerIndex[0]] = tmpConfig;
}
void FLEXIO_I2C_MasterEnableAck(FLEXIO_I2C_Type *base, bool enable)
{
uint32_t tmpConfig = 0;
tmpConfig = base->flexioBase->SHIFTCFG[base->shifterIndex[0]];
tmpConfig &= ~FLEXIO_SHIFTCFG_SSTOP_MASK;
if (enable)
{
tmpConfig |= FLEXIO_SHIFTCFG_SSTOP(kFLEXIO_ShifterStopBitLow);
}
else
{
tmpConfig |= FLEXIO_SHIFTCFG_SSTOP(kFLEXIO_ShifterStopBitHigh);
}
base->flexioBase->SHIFTCFG[base->shifterIndex[0]] = tmpConfig;
}
status_t FLEXIO_I2C_MasterWriteBlocking(FLEXIO_I2C_Type *base, const uint8_t *txBuff, uint8_t txSize)
{
assert(txBuff);
assert(txSize);
uint32_t status;
while (txSize--)
{
FLEXIO_I2C_MasterWriteByte(base, *txBuff++);
/* Wait until data transfer complete. */
while (!((status = FLEXIO_I2C_MasterGetStatusFlags(base)) & kFLEXIO_I2C_RxFullFlag))
{
}
if (status & kFLEXIO_I2C_ReceiveNakFlag)
{
FLEXIO_ClearShifterErrorFlags(base->flexioBase, 1U << base->shifterIndex[1]);
return kStatus_FLEXIO_I2C_Nak;
}
}
return kStatus_Success;
}
void FLEXIO_I2C_MasterReadBlocking(FLEXIO_I2C_Type *base, uint8_t *rxBuff, uint8_t rxSize)
{
assert(rxBuff);
assert(rxSize);
while (rxSize--)
{
/* Wait until data transfer complete. */
while (!(FLEXIO_I2C_MasterGetStatusFlags(base) & kFLEXIO_I2C_RxFullFlag))
{
}
*rxBuff++ = FLEXIO_I2C_MasterReadByte(base);
}
}
status_t FLEXIO_I2C_MasterTransferBlocking(FLEXIO_I2C_Type *base, flexio_i2c_master_transfer_t *xfer)
{
assert(xfer);
flexio_i2c_master_handle_t tmpHandle;
uint32_t statusFlags;
uint32_t result = kStatus_Success;
/* Zero the handle. */
memset(&tmpHandle, 0, sizeof(tmpHandle));
/* Set up transfer machine. */
FLEXIO_I2C_MasterTransferInitStateMachine(base, &tmpHandle, xfer);
do
{
/* Wait either tx empty or rx full flag is asserted. */
while (!((statusFlags = FLEXIO_I2C_MasterGetStatusFlags(base)) &
(kFLEXIO_I2C_TxEmptyFlag | kFLEXIO_I2C_RxFullFlag)))
{
}
result = FLEXIO_I2C_MasterTransferRunStateMachine(base, &tmpHandle, statusFlags);
} while ((tmpHandle.state != kFLEXIO_I2C_Idle) && (result == kStatus_Success));
return result;
}
status_t FLEXIO_I2C_MasterTransferCreateHandle(FLEXIO_I2C_Type *base,
flexio_i2c_master_handle_t *handle,
flexio_i2c_master_transfer_callback_t callback,
void *userData)
{
assert(handle);
IRQn_Type flexio_irqs[] = FLEXIO_IRQS;
/* Zero the handle. */
memset(handle, 0, sizeof(*handle));
/* Register callback and userData. */
handle->completionCallback = callback;
handle->userData = userData;
/* Enable interrupt in NVIC. */
EnableIRQ(flexio_irqs[FLEXIO_I2C_GetInstance(base)]);
/* Save the context in global variables to support the double weak mechanism. */
return FLEXIO_RegisterHandleIRQ(base, handle, FLEXIO_I2C_MasterTransferHandleIRQ);
}
status_t FLEXIO_I2C_MasterTransferNonBlocking(FLEXIO_I2C_Type *base,
flexio_i2c_master_handle_t *handle,
flexio_i2c_master_transfer_t *xfer)
{
assert(handle);
assert(xfer);
if (handle->state != kFLEXIO_I2C_Idle)
{
return kStatus_FLEXIO_I2C_Busy;
}
else
{
/* Set up transfer machine. */
FLEXIO_I2C_MasterTransferInitStateMachine(base, handle, xfer);
/* Enable both tx empty and rxfull interrupt. */
FLEXIO_I2C_MasterEnableInterrupts(base, kFLEXIO_I2C_TxEmptyInterruptEnable | kFLEXIO_I2C_RxFullInterruptEnable);
return kStatus_Success;
}
}
void FLEXIO_I2C_MasterTransferAbort(FLEXIO_I2C_Type *base, flexio_i2c_master_handle_t *handle)
{
assert(handle);
/* Disable interrupts. */
FLEXIO_I2C_MasterDisableInterrupts(base, kFLEXIO_I2C_TxEmptyInterruptEnable | kFLEXIO_I2C_RxFullInterruptEnable);
/* Reset to idle state. */
handle->state = kFLEXIO_I2C_Idle;
}
status_t FLEXIO_I2C_MasterTransferGetCount(FLEXIO_I2C_Type *base, flexio_i2c_master_handle_t *handle, size_t *count)
{
if (!count)
{
return kStatus_InvalidArgument;
}
*count = handle->transferSize - handle->transfer.dataSize;
return kStatus_Success;
}
void FLEXIO_I2C_MasterTransferHandleIRQ(void *i2cType, void *i2cHandle)
{
FLEXIO_I2C_Type *base = (FLEXIO_I2C_Type *)i2cType;
flexio_i2c_master_handle_t *handle = (flexio_i2c_master_handle_t *)i2cHandle;
uint32_t statusFlags;
status_t result;
statusFlags = FLEXIO_I2C_MasterGetStatusFlags(base);
result = FLEXIO_I2C_MasterTransferRunStateMachine(base, handle, statusFlags);
if (handle->state == kFLEXIO_I2C_Idle)
{
FLEXIO_I2C_MasterTransferComplete(base, handle, result);
}
}

View File

@ -0,0 +1,465 @@
/*
* Copyright (c) 2015, Freescale Semiconductor, Inc.
* Copyright 2016-2017 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef _FSL_FLEXIO_I2C_MASTER_H_
#define _FSL_FLEXIO_I2C_MASTER_H_
#include "fsl_common.h"
#include "fsl_flexio.h"
/*!
* @addtogroup flexio_i2c_master
* @{
*/
/*******************************************************************************
* Definitions
******************************************************************************/
/*! @name Driver version */
/*@{*/
/*! @brief FlexIO I2C master driver version 2.1.2. */
#define FSL_FLEXIO_I2C_MASTER_DRIVER_VERSION (MAKE_VERSION(2, 1, 2))
/*@}*/
/*! @brief FlexIO I2C transfer status*/
enum _flexio_i2c_status
{
kStatus_FLEXIO_I2C_Busy = MAKE_STATUS(kStatusGroup_FLEXIO_I2C, 0), /*!< I2C is busy doing transfer. */
kStatus_FLEXIO_I2C_Idle = MAKE_STATUS(kStatusGroup_FLEXIO_I2C, 1), /*!< I2C is busy doing transfer. */
kStatus_FLEXIO_I2C_Nak = MAKE_STATUS(kStatusGroup_FLEXIO_I2C, 2), /*!< NAK received during transfer. */
};
/*! @brief Define FlexIO I2C master interrupt mask. */
enum _flexio_i2c_master_interrupt
{
kFLEXIO_I2C_TxEmptyInterruptEnable = 0x1U, /*!< Tx buffer empty interrupt enable. */
kFLEXIO_I2C_RxFullInterruptEnable = 0x2U, /*!< Rx buffer full interrupt enable. */
};
/*! @brief Define FlexIO I2C master status mask. */
enum _flexio_i2c_master_status_flags
{
kFLEXIO_I2C_TxEmptyFlag = 0x1U, /*!< Tx shifter empty flag. */
kFLEXIO_I2C_RxFullFlag = 0x2U, /*!< Rx shifter full/Transfer complete flag. */
kFLEXIO_I2C_ReceiveNakFlag = 0x4U, /*!< Receive NAK flag. */
};
/*! @brief Direction of master transfer.*/
typedef enum _flexio_i2c_direction
{
kFLEXIO_I2C_Write = 0x0U, /*!< Master send to slave. */
kFLEXIO_I2C_Read = 0x1U, /*!< Master receive from slave. */
} flexio_i2c_direction_t;
/*! @brief Define FlexIO I2C master access structure typedef. */
typedef struct _flexio_i2c_type
{
FLEXIO_Type *flexioBase; /*!< FlexIO base pointer. */
uint8_t SDAPinIndex; /*!< Pin select for I2C SDA. */
uint8_t SCLPinIndex; /*!< Pin select for I2C SCL. */
uint8_t shifterIndex[2]; /*!< Shifter index used in FlexIO I2C. */
uint8_t timerIndex[2]; /*!< Timer index used in FlexIO I2C. */
} FLEXIO_I2C_Type;
/*! @brief Define FlexIO I2C master user configuration structure. */
typedef struct _flexio_i2c_master_config
{
bool enableMaster; /*!< Enables the FlexIO I2C peripheral at initialization time. */
bool enableInDoze; /*!< Enable/disable FlexIO operation in doze mode. */
bool enableInDebug; /*!< Enable/disable FlexIO operation in debug mode. */
bool enableFastAccess; /*!< Enable/disable fast access to FlexIO registers, fast access requires
the FlexIO clock to be at least twice the frequency of the bus clock. */
uint32_t baudRate_Bps; /*!< Baud rate in Bps. */
} flexio_i2c_master_config_t;
/*! @brief Define FlexIO I2C master transfer structure. */
typedef struct _flexio_i2c_master_transfer
{
uint32_t flags; /*!< Transfer flag which controls the transfer, reserved for FlexIO I2C. */
uint8_t slaveAddress; /*!< 7-bit slave address. */
flexio_i2c_direction_t direction; /*!< Transfer direction, read or write. */
uint32_t subaddress; /*!< Sub address. Transferred MSB first. */
uint8_t subaddressSize; /*!< Size of command buffer. */
uint8_t volatile *data; /*!< Transfer buffer. */
volatile size_t dataSize; /*!< Transfer size. */
} flexio_i2c_master_transfer_t;
/*! @brief FlexIO I2C master handle typedef. */
typedef struct _flexio_i2c_master_handle flexio_i2c_master_handle_t;
/*! @brief FlexIO I2C master transfer callback typedef. */
typedef void (*flexio_i2c_master_transfer_callback_t)(FLEXIO_I2C_Type *base,
flexio_i2c_master_handle_t *handle,
status_t status,
void *userData);
/*! @brief Define FlexIO I2C master handle structure. */
struct _flexio_i2c_master_handle
{
flexio_i2c_master_transfer_t transfer; /*!< FlexIO I2C master transfer copy. */
size_t transferSize; /*!< Total bytes to be transferred. */
uint8_t state; /*!< Transfer state maintained during transfer. */
flexio_i2c_master_transfer_callback_t completionCallback; /*!< Callback function called at transfer event. */
/*!< Callback function called at transfer event. */
void *userData; /*!< Callback parameter passed to callback function. */
};
/*******************************************************************************
* API
******************************************************************************/
#if defined(__cplusplus)
extern "C" {
#endif /*_cplusplus*/
/*!
* @name Initialization and deinitialization
* @{
*/
/*!
* @brief Ungates the FlexIO clock, resets the FlexIO module, and configures the FlexIO I2C
* hardware configuration.
*
* Example
@code
FLEXIO_I2C_Type base = {
.flexioBase = FLEXIO,
.SDAPinIndex = 0,
.SCLPinIndex = 1,
.shifterIndex = {0,1},
.timerIndex = {0,1}
};
flexio_i2c_master_config_t config = {
.enableInDoze = false,
.enableInDebug = true,
.enableFastAccess = false,
.baudRate_Bps = 100000
};
FLEXIO_I2C_MasterInit(base, &config, srcClock_Hz);
@endcode
*
* @param base Pointer to FLEXIO_I2C_Type structure.
* @param masterConfig Pointer to flexio_i2c_master_config_t structure.
* @param srcClock_Hz FlexIO source clock in Hz.
* @retval kStatus_Success Initialization successful
* @retval kStatus_InvalidArgument The source clock exceed upper range limitation
*/
status_t FLEXIO_I2C_MasterInit(FLEXIO_I2C_Type *base, flexio_i2c_master_config_t *masterConfig, uint32_t srcClock_Hz);
/*!
* @brief De-initializes the FlexIO I2C master peripheral. Calling this API gates the FlexIO clock
* and the FlexIO I2C master module can't work unless the FLEXIO_I2C_MasterInit is called.
*
* @param base pointer to FLEXIO_I2C_Type structure.
*/
void FLEXIO_I2C_MasterDeinit(FLEXIO_I2C_Type *base);
/*!
* @brief Gets the default configuration to configure the FlexIO module. The configuration
* can be used directly for calling the FLEXIO_I2C_MasterInit().
*
* Example:
@code
flexio_i2c_master_config_t config;
FLEXIO_I2C_MasterGetDefaultConfig(&config);
@endcode
* @param masterConfig Pointer to flexio_i2c_master_config_t structure.
*/
void FLEXIO_I2C_MasterGetDefaultConfig(flexio_i2c_master_config_t *masterConfig);
/*!
* @brief Enables/disables the FlexIO module operation.
*
* @param base Pointer to FLEXIO_I2C_Type structure.
* @param enable Pass true to enable module, false to disable module.
*/
static inline void FLEXIO_I2C_MasterEnable(FLEXIO_I2C_Type *base, bool enable)
{
if (enable)
{
base->flexioBase->CTRL |= FLEXIO_CTRL_FLEXEN_MASK;
}
else
{
base->flexioBase->CTRL &= ~FLEXIO_CTRL_FLEXEN_MASK;
}
}
/* @} */
/*!
* @name Status
* @{
*/
/*!
* @brief Gets the FlexIO I2C master status flags.
*
* @param base Pointer to FLEXIO_I2C_Type structure
* @return Status flag, use status flag to AND #_flexio_i2c_master_status_flags can get the related status.
*/
uint32_t FLEXIO_I2C_MasterGetStatusFlags(FLEXIO_I2C_Type *base);
/*!
* @brief Clears the FlexIO I2C master status flags.
*
* @param base Pointer to FLEXIO_I2C_Type structure.
* @param mask Status flag.
* The parameter can be any combination of the following values:
* @arg kFLEXIO_I2C_RxFullFlag
* @arg kFLEXIO_I2C_ReceiveNakFlag
*/
void FLEXIO_I2C_MasterClearStatusFlags(FLEXIO_I2C_Type *base, uint32_t mask);
/*@}*/
/*!
* @name Interrupts
* @{
*/
/*!
* @brief Enables the FlexIO i2c master interrupt requests.
*
* @param base Pointer to FLEXIO_I2C_Type structure.
* @param mask Interrupt source.
* Currently only one interrupt request source:
* @arg kFLEXIO_I2C_TransferCompleteInterruptEnable
*/
void FLEXIO_I2C_MasterEnableInterrupts(FLEXIO_I2C_Type *base, uint32_t mask);
/*!
* @brief Disables the FlexIO I2C master interrupt requests.
*
* @param base Pointer to FLEXIO_I2C_Type structure.
* @param mask Interrupt source.
*/
void FLEXIO_I2C_MasterDisableInterrupts(FLEXIO_I2C_Type *base, uint32_t mask);
/*@}*/
/*!
* @name Bus Operations
* @{
*/
/*!
* @brief Sets the FlexIO I2C master transfer baudrate.
*
* @param base Pointer to FLEXIO_I2C_Type structure
* @param baudRate_Bps the baud rate value in HZ
* @param srcClock_Hz source clock in HZ
*/
void FLEXIO_I2C_MasterSetBaudRate(FLEXIO_I2C_Type *base, uint32_t baudRate_Bps, uint32_t srcClock_Hz);
/*!
* @brief Sends START + 7-bit address to the bus.
*
* @note This API should be called when the transfer configuration is ready to send a START signal
* and 7-bit address to the bus. This is a non-blocking API, which returns directly after the address
* is put into the data register but the address transfer is not finished on the bus. Ensure that
* the kFLEXIO_I2C_RxFullFlag status is asserted before calling this API.
* @param base Pointer to FLEXIO_I2C_Type structure.
* @param address 7-bit address.
* @param direction transfer direction.
* This parameter is one of the values in flexio_i2c_direction_t:
* @arg kFLEXIO_I2C_Write: Transmit
* @arg kFLEXIO_I2C_Read: Receive
*/
void FLEXIO_I2C_MasterStart(FLEXIO_I2C_Type *base, uint8_t address, flexio_i2c_direction_t direction);
/*!
* @brief Sends the stop signal on the bus.
*
* @param base Pointer to FLEXIO_I2C_Type structure.
*/
void FLEXIO_I2C_MasterStop(FLEXIO_I2C_Type *base);
/*!
* @brief Sends the repeated start signal on the bus.
*
* @param base Pointer to FLEXIO_I2C_Type structure.
*/
void FLEXIO_I2C_MasterRepeatedStart(FLEXIO_I2C_Type *base);
/*!
* @brief Sends the stop signal when transfer is still on-going.
*
* @param base Pointer to FLEXIO_I2C_Type structure.
*/
void FLEXIO_I2C_MasterAbortStop(FLEXIO_I2C_Type *base);
/*!
* @brief Configures the sent ACK/NAK for the following byte.
*
* @param base Pointer to FLEXIO_I2C_Type structure.
* @param enable True to configure send ACK, false configure to send NAK.
*/
void FLEXIO_I2C_MasterEnableAck(FLEXIO_I2C_Type *base, bool enable);
/*!
* @brief Sets the number of bytes to be transferred from a start signal to a stop signal.
*
* @note Call this API before a transfer begins because the timer generates a number of clocks according
* to the number of bytes that need to be transferred.
*
* @param base Pointer to FLEXIO_I2C_Type structure.
* @param count Number of bytes need to be transferred from a start signal to a re-start/stop signal
* @retval kStatus_Success Successfully configured the count.
* @retval kStatus_InvalidArgument Input argument is invalid.
*/
status_t FLEXIO_I2C_MasterSetTransferCount(FLEXIO_I2C_Type *base, uint8_t count);
/*!
* @brief Writes one byte of data to the I2C bus.
*
* @note This is a non-blocking API, which returns directly after the data is put into the
* data register but the data transfer is not finished on the bus. Ensure that
* the TxEmptyFlag is asserted before calling this API.
*
* @param base Pointer to FLEXIO_I2C_Type structure.
* @param data a byte of data.
*/
static inline void FLEXIO_I2C_MasterWriteByte(FLEXIO_I2C_Type *base, uint32_t data)
{
base->flexioBase->SHIFTBUFBBS[base->shifterIndex[0]] = data;
}
/*!
* @brief Reads one byte of data from the I2C bus.
*
* @note This is a non-blocking API, which returns directly after the data is read from the
* data register. Ensure that the data is ready in the register.
*
* @param base Pointer to FLEXIO_I2C_Type structure.
* @return data byte read.
*/
static inline uint8_t FLEXIO_I2C_MasterReadByte(FLEXIO_I2C_Type *base)
{
return base->flexioBase->SHIFTBUFBIS[base->shifterIndex[1]];
}
/*!
* @brief Sends a buffer of data in bytes.
*
* @note This function blocks via polling until all bytes have been sent.
*
* @param base Pointer to FLEXIO_I2C_Type structure.
* @param txBuff The data bytes to send.
* @param txSize The number of data bytes to send.
* @retval kStatus_Success Successfully write data.
* @retval kStatus_FLEXIO_I2C_Nak Receive NAK during writing data.
*/
status_t FLEXIO_I2C_MasterWriteBlocking(FLEXIO_I2C_Type *base, const uint8_t *txBuff, uint8_t txSize);
/*!
* @brief Receives a buffer of bytes.
*
* @note This function blocks via polling until all bytes have been received.
*
* @param base Pointer to FLEXIO_I2C_Type structure.
* @param rxBuff The buffer to store the received bytes.
* @param rxSize The number of data bytes to be received.
*/
void FLEXIO_I2C_MasterReadBlocking(FLEXIO_I2C_Type *base, uint8_t *rxBuff, uint8_t rxSize);
/*!
* @brief Performs a master polling transfer on the I2C bus.
*
* @note The API does not return until the transfer succeeds or fails due
* to receiving NAK.
*
* @param base pointer to FLEXIO_I2C_Type structure.
* @param xfer pointer to flexio_i2c_master_transfer_t structure.
* @return status of status_t.
*/
status_t FLEXIO_I2C_MasterTransferBlocking(FLEXIO_I2C_Type *base, flexio_i2c_master_transfer_t *xfer);
/*@}*/
/*Transactional APIs*/
/*!
* @name Transactional
* @{
*/
/*!
* @brief Initializes the I2C handle which is used in transactional functions.
*
* @param base Pointer to FLEXIO_I2C_Type structure.
* @param handle Pointer to flexio_i2c_master_handle_t structure to store the transfer state.
* @param callback Pointer to user callback function.
* @param userData User param passed to the callback function.
* @retval kStatus_Success Successfully create the handle.
* @retval kStatus_OutOfRange The FlexIO type/handle/isr table out of range.
*/
status_t FLEXIO_I2C_MasterTransferCreateHandle(FLEXIO_I2C_Type *base,
flexio_i2c_master_handle_t *handle,
flexio_i2c_master_transfer_callback_t callback,
void *userData);
/*!
* @brief Performs a master interrupt non-blocking transfer on the I2C bus.
*
* @note The API returns immediately after the transfer initiates.
* Call FLEXIO_I2C_MasterGetTransferCount to poll the transfer status to check whether
* the transfer is finished. If the return status is not kStatus_FLEXIO_I2C_Busy, the transfer
* is finished.
*
* @param base Pointer to FLEXIO_I2C_Type structure
* @param handle Pointer to flexio_i2c_master_handle_t structure which stores the transfer state
* @param xfer pointer to flexio_i2c_master_transfer_t structure
* @retval kStatus_Success Successfully start a transfer.
* @retval kStatus_FLEXIO_I2C_Busy FlexIO I2C is not idle, is running another transfer.
*/
status_t FLEXIO_I2C_MasterTransferNonBlocking(FLEXIO_I2C_Type *base,
flexio_i2c_master_handle_t *handle,
flexio_i2c_master_transfer_t *xfer);
/*!
* @brief Gets the master transfer status during a interrupt non-blocking transfer.
*
* @param base Pointer to FLEXIO_I2C_Type structure.
* @param handle Pointer to flexio_i2c_master_handle_t structure which stores the transfer state.
* @param count Number of bytes transferred so far by the non-blocking transaction.
* @retval kStatus_InvalidArgument count is Invalid.
* @retval kStatus_Success Successfully return the count.
*/
status_t FLEXIO_I2C_MasterTransferGetCount(FLEXIO_I2C_Type *base, flexio_i2c_master_handle_t *handle, size_t *count);
/*!
* @brief Aborts an interrupt non-blocking transfer early.
*
* @note This API can be called at any time when an interrupt non-blocking transfer initiates
* to abort the transfer early.
*
* @param base Pointer to FLEXIO_I2C_Type structure
* @param handle Pointer to flexio_i2c_master_handle_t structure which stores the transfer state
*/
void FLEXIO_I2C_MasterTransferAbort(FLEXIO_I2C_Type *base, flexio_i2c_master_handle_t *handle);
/*!
* @brief Master interrupt handler.
*
* @param i2cType Pointer to FLEXIO_I2C_Type structure
* @param i2cHandle Pointer to flexio_i2c_master_transfer_t structure
*/
void FLEXIO_I2C_MasterTransferHandleIRQ(void *i2cType, void *i2cHandle);
/*@}*/
#if defined(__cplusplus)
}
#endif /*_cplusplus*/
/*@}*/
#endif /*_FSL_FLEXIO_I2C_MASTER_H_*/

View File

@ -0,0 +1,978 @@
/*
* Copyright (c) 2015, Freescale Semiconductor, Inc.
* Copyright 2016-2017 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include "fsl_flexio_spi.h"
/*******************************************************************************
* Definitions
******************************************************************************/
/*! @brief FLEXIO SPI transfer state, which is used for SPI transactiaonl APIs' internal state. */
enum _flexio_spi_transfer_states
{
kFLEXIO_SPI_Idle = 0x0U, /*!< Nothing in the transmitter/receiver's queue. */
kFLEXIO_SPI_Busy, /*!< Transmiter/Receive's queue is not finished. */
};
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
extern const clock_ip_name_t s_flexioClocks[];
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
extern FLEXIO_Type *const s_flexioBases[];
/*******************************************************************************
* Prototypes
******************************************************************************/
extern uint32_t FLEXIO_GetInstance(FLEXIO_Type *base);
/*!
* @brief Send a piece of data for SPI.
*
* This function computes the number of data to be written into D register or Tx FIFO,
* and write the data into it. At the same time, this function updates the values in
* master handle structure.
*
* @param base pointer to FLEXIO_SPI_Type structure
* @param handle Pointer to SPI master handle structure.
*/
static void FLEXIO_SPI_TransferSendTransaction(FLEXIO_SPI_Type *base, flexio_spi_master_handle_t *handle);
/*!
* @brief Receive a piece of data for SPI master.
*
* This function computes the number of data to receive from D register or Rx FIFO,
* and write the data to destination address. At the same time, this function updates
* the values in master handle structure.
*
* @param base pointer to FLEXIO_SPI_Type structure
* @param handle Pointer to SPI master handle structure.
*/
static void FLEXIO_SPI_TransferReceiveTransaction(FLEXIO_SPI_Type *base, flexio_spi_master_handle_t *handle);
/*******************************************************************************
* Variables
******************************************************************************/
/*******************************************************************************
* Codes
******************************************************************************/
uint32_t FLEXIO_SPI_GetInstance(FLEXIO_SPI_Type *base)
{
return FLEXIO_GetInstance(base->flexioBase);
}
static void FLEXIO_SPI_TransferSendTransaction(FLEXIO_SPI_Type *base, flexio_spi_master_handle_t *handle)
{
uint16_t tmpData = FLEXIO_SPI_DUMMYDATA;
if (handle->txData != NULL)
{
/* Transmit data and update tx size/buff. */
if (handle->bytePerFrame == 1U)
{
tmpData = *(handle->txData);
handle->txData++;
}
else
{
if (handle->direction == kFLEXIO_SPI_MsbFirst)
{
tmpData = (uint32_t)(handle->txData[0]) << 8U;
tmpData += handle->txData[1];
}
else
{
tmpData = (uint32_t)(handle->txData[1]) << 8U;
tmpData += handle->txData[0];
}
handle->txData += 2U;
}
}
else
{
tmpData = FLEXIO_SPI_DUMMYDATA;
}
handle->txRemainingBytes -= handle->bytePerFrame;
FLEXIO_SPI_WriteData(base, handle->direction, tmpData);
if (!handle->txRemainingBytes)
{
FLEXIO_SPI_DisableInterrupts(base, kFLEXIO_SPI_TxEmptyInterruptEnable);
}
}
static void FLEXIO_SPI_TransferReceiveTransaction(FLEXIO_SPI_Type *base, flexio_spi_master_handle_t *handle)
{
uint16_t tmpData;
tmpData = FLEXIO_SPI_ReadData(base, handle->direction);
if (handle->rxData != NULL)
{
if (handle->bytePerFrame == 1U)
{
*handle->rxData = tmpData;
handle->rxData++;
}
else
{
if (handle->direction == kFLEXIO_SPI_MsbFirst)
{
*((uint16_t *)(handle->rxData)) = tmpData;
}
else
{
*((uint16_t *)(handle->rxData)) = (((tmpData << 8) & 0xff00U) | ((tmpData >> 8) & 0x00ffU));
}
handle->rxData += 2U;
}
}
handle->rxRemainingBytes -= handle->bytePerFrame;
}
void FLEXIO_SPI_MasterInit(FLEXIO_SPI_Type *base, flexio_spi_master_config_t *masterConfig, uint32_t srcClock_Hz)
{
assert(base);
assert(masterConfig);
flexio_shifter_config_t shifterConfig;
flexio_timer_config_t timerConfig;
uint32_t ctrlReg = 0;
uint16_t timerDiv = 0;
uint16_t timerCmp = 0;
/* Clear the shifterConfig & timerConfig struct. */
memset(&shifterConfig, 0, sizeof(shifterConfig));
memset(&timerConfig, 0, sizeof(timerConfig));
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
/* Ungate flexio clock. */
CLOCK_EnableClock(s_flexioClocks[FLEXIO_SPI_GetInstance(base)]);
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
/* Configure FLEXIO SPI Master */
ctrlReg = base->flexioBase->CTRL;
ctrlReg &= ~(FLEXIO_CTRL_DOZEN_MASK | FLEXIO_CTRL_DBGE_MASK | FLEXIO_CTRL_FASTACC_MASK | FLEXIO_CTRL_FLEXEN_MASK);
ctrlReg |= (FLEXIO_CTRL_DBGE(masterConfig->enableInDebug) | FLEXIO_CTRL_FASTACC(masterConfig->enableFastAccess) |
FLEXIO_CTRL_FLEXEN(masterConfig->enableMaster));
if (!masterConfig->enableInDoze)
{
ctrlReg |= FLEXIO_CTRL_DOZEN_MASK;
}
base->flexioBase->CTRL = ctrlReg;
/* Do hardware configuration. */
/* 1. Configure the shifter 0 for tx. */
shifterConfig.timerSelect = base->timerIndex[0];
shifterConfig.pinConfig = kFLEXIO_PinConfigOutput;
shifterConfig.pinSelect = base->SDOPinIndex;
shifterConfig.pinPolarity = kFLEXIO_PinActiveHigh;
shifterConfig.shifterMode = kFLEXIO_ShifterModeTransmit;
shifterConfig.inputSource = kFLEXIO_ShifterInputFromPin;
if (masterConfig->phase == kFLEXIO_SPI_ClockPhaseFirstEdge)
{
shifterConfig.timerPolarity = kFLEXIO_ShifterTimerPolarityOnNegitive;
shifterConfig.shifterStop = kFLEXIO_ShifterStopBitDisable;
shifterConfig.shifterStart = kFLEXIO_ShifterStartBitDisabledLoadDataOnEnable;
}
else
{
shifterConfig.timerPolarity = kFLEXIO_ShifterTimerPolarityOnPositive;
shifterConfig.shifterStop = kFLEXIO_ShifterStopBitLow;
shifterConfig.shifterStart = kFLEXIO_ShifterStartBitDisabledLoadDataOnShift;
}
FLEXIO_SetShifterConfig(base->flexioBase, base->shifterIndex[0], &shifterConfig);
/* 2. Configure the shifter 1 for rx. */
shifterConfig.timerSelect = base->timerIndex[0];
shifterConfig.pinConfig = kFLEXIO_PinConfigOutputDisabled;
shifterConfig.pinSelect = base->SDIPinIndex;
shifterConfig.pinPolarity = kFLEXIO_PinActiveHigh;
shifterConfig.shifterMode = kFLEXIO_ShifterModeReceive;
shifterConfig.inputSource = kFLEXIO_ShifterInputFromPin;
shifterConfig.shifterStop = kFLEXIO_ShifterStopBitDisable;
shifterConfig.shifterStart = kFLEXIO_ShifterStartBitDisabledLoadDataOnEnable;
if (masterConfig->phase == kFLEXIO_SPI_ClockPhaseFirstEdge)
{
shifterConfig.timerPolarity = kFLEXIO_ShifterTimerPolarityOnPositive;
}
else
{
shifterConfig.timerPolarity = kFLEXIO_ShifterTimerPolarityOnNegitive;
}
FLEXIO_SetShifterConfig(base->flexioBase, base->shifterIndex[1], &shifterConfig);
/*3. Configure the timer 0 for SCK. */
timerConfig.triggerSelect = FLEXIO_TIMER_TRIGGER_SEL_SHIFTnSTAT(base->shifterIndex[0]);
timerConfig.triggerPolarity = kFLEXIO_TimerTriggerPolarityActiveLow;
timerConfig.triggerSource = kFLEXIO_TimerTriggerSourceInternal;
timerConfig.pinConfig = kFLEXIO_PinConfigOutput;
timerConfig.pinSelect = base->SCKPinIndex;
timerConfig.pinPolarity = kFLEXIO_PinActiveHigh;
timerConfig.timerMode = kFLEXIO_TimerModeDual8BitBaudBit;
timerConfig.timerOutput = kFLEXIO_TimerOutputZeroNotAffectedByReset;
timerConfig.timerDecrement = kFLEXIO_TimerDecSrcOnFlexIOClockShiftTimerOutput;
timerConfig.timerReset = kFLEXIO_TimerResetNever;
timerConfig.timerDisable = kFLEXIO_TimerDisableOnTimerCompare;
timerConfig.timerEnable = kFLEXIO_TimerEnableOnTriggerHigh;
timerConfig.timerStop = kFLEXIO_TimerStopBitEnableOnTimerDisable;
timerConfig.timerStart = kFLEXIO_TimerStartBitEnabled;
timerDiv = srcClock_Hz / masterConfig->baudRate_Bps;
timerDiv = timerDiv / 2 - 1;
timerCmp = ((uint32_t)(masterConfig->dataMode * 2 - 1U)) << 8U;
timerCmp |= timerDiv;
timerConfig.timerCompare = timerCmp;
FLEXIO_SetTimerConfig(base->flexioBase, base->timerIndex[0], &timerConfig);
/* 4. Configure the timer 1 for CSn. */
timerConfig.triggerSelect = FLEXIO_TIMER_TRIGGER_SEL_TIMn(base->timerIndex[0]);
timerConfig.triggerPolarity = kFLEXIO_TimerTriggerPolarityActiveHigh;
timerConfig.triggerSource = kFLEXIO_TimerTriggerSourceInternal;
timerConfig.pinConfig = kFLEXIO_PinConfigOutput;
timerConfig.pinSelect = base->CSnPinIndex;
timerConfig.pinPolarity = kFLEXIO_PinActiveLow;
timerConfig.timerMode = kFLEXIO_TimerModeSingle16Bit;
timerConfig.timerOutput = kFLEXIO_TimerOutputOneNotAffectedByReset;
timerConfig.timerDecrement = kFLEXIO_TimerDecSrcOnFlexIOClockShiftTimerOutput;
timerConfig.timerReset = kFLEXIO_TimerResetNever;
timerConfig.timerDisable = kFLEXIO_TimerDisableOnPreTimerDisable;
timerConfig.timerEnable = kFLEXIO_TimerEnableOnPrevTimerEnable;
timerConfig.timerStop = kFLEXIO_TimerStopBitDisabled;
timerConfig.timerStart = kFLEXIO_TimerStartBitDisabled;
timerConfig.timerCompare = 0xFFFFU;
FLEXIO_SetTimerConfig(base->flexioBase, base->timerIndex[1], &timerConfig);
}
void FLEXIO_SPI_MasterDeinit(FLEXIO_SPI_Type *base)
{
/* Disable FLEXIO SPI module. */
FLEXIO_SPI_Enable(base, false);
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
/* Gate flexio clock. */
CLOCK_DisableClock(kCLOCK_Flexio0);
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
}
void FLEXIO_SPI_MasterGetDefaultConfig(flexio_spi_master_config_t *masterConfig)
{
assert(masterConfig);
masterConfig->enableMaster = true;
masterConfig->enableInDoze = false;
masterConfig->enableInDebug = true;
masterConfig->enableFastAccess = false;
/* Default baud rate 500kbps. */
masterConfig->baudRate_Bps = 500000U;
/* Default CPHA = 0. */
masterConfig->phase = kFLEXIO_SPI_ClockPhaseFirstEdge;
/* Default bit count at 8. */
masterConfig->dataMode = kFLEXIO_SPI_8BitMode;
}
void FLEXIO_SPI_SlaveInit(FLEXIO_SPI_Type *base, flexio_spi_slave_config_t *slaveConfig)
{
assert(base && slaveConfig);
flexio_shifter_config_t shifterConfig;
flexio_timer_config_t timerConfig;
uint32_t ctrlReg = 0;
/* Clear the shifterConfig & timerConfig struct. */
memset(&shifterConfig, 0, sizeof(shifterConfig));
memset(&timerConfig, 0, sizeof(timerConfig));
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
/* Ungate flexio clock. */
CLOCK_EnableClock(kCLOCK_Flexio0);
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
/* Configure FLEXIO SPI Slave */
ctrlReg = base->flexioBase->CTRL;
ctrlReg &= ~(FLEXIO_CTRL_DOZEN_MASK | FLEXIO_CTRL_DBGE_MASK | FLEXIO_CTRL_FASTACC_MASK | FLEXIO_CTRL_FLEXEN_MASK);
ctrlReg |= (FLEXIO_CTRL_DBGE(slaveConfig->enableInDebug) | FLEXIO_CTRL_FASTACC(slaveConfig->enableFastAccess) |
FLEXIO_CTRL_FLEXEN(slaveConfig->enableSlave));
if (!slaveConfig->enableInDoze)
{
ctrlReg |= FLEXIO_CTRL_DOZEN_MASK;
}
base->flexioBase->CTRL = ctrlReg;
/* Do hardware configuration. */
/* 1. Configure the shifter 0 for tx. */
shifterConfig.timerSelect = base->timerIndex[0];
shifterConfig.pinConfig = kFLEXIO_PinConfigOutput;
shifterConfig.pinSelect = base->SDOPinIndex;
shifterConfig.pinPolarity = kFLEXIO_PinActiveHigh;
shifterConfig.shifterMode = kFLEXIO_ShifterModeTransmit;
shifterConfig.inputSource = kFLEXIO_ShifterInputFromPin;
shifterConfig.shifterStop = kFLEXIO_ShifterStopBitDisable;
if (slaveConfig->phase == kFLEXIO_SPI_ClockPhaseFirstEdge)
{
shifterConfig.timerPolarity = kFLEXIO_ShifterTimerPolarityOnNegitive;
shifterConfig.shifterStart = kFLEXIO_ShifterStartBitDisabledLoadDataOnEnable;
}
else
{
shifterConfig.timerPolarity = kFLEXIO_ShifterTimerPolarityOnPositive;
shifterConfig.shifterStart = kFLEXIO_ShifterStartBitDisabledLoadDataOnShift;
}
FLEXIO_SetShifterConfig(base->flexioBase, base->shifterIndex[0], &shifterConfig);
/* 2. Configure the shifter 1 for rx. */
shifterConfig.timerSelect = base->timerIndex[0];
shifterConfig.pinConfig = kFLEXIO_PinConfigOutputDisabled;
shifterConfig.pinSelect = base->SDIPinIndex;
shifterConfig.pinPolarity = kFLEXIO_PinActiveHigh;
shifterConfig.shifterMode = kFLEXIO_ShifterModeReceive;
shifterConfig.inputSource = kFLEXIO_ShifterInputFromPin;
shifterConfig.shifterStop = kFLEXIO_ShifterStopBitDisable;
shifterConfig.shifterStart = kFLEXIO_ShifterStartBitDisabledLoadDataOnEnable;
if (slaveConfig->phase == kFLEXIO_SPI_ClockPhaseFirstEdge)
{
shifterConfig.timerPolarity = kFLEXIO_ShifterTimerPolarityOnPositive;
}
else
{
shifterConfig.timerPolarity = kFLEXIO_ShifterTimerPolarityOnNegitive;
}
FLEXIO_SetShifterConfig(base->flexioBase, base->shifterIndex[1], &shifterConfig);
/*3. Configure the timer 0 for shift clock. */
timerConfig.triggerSelect = FLEXIO_TIMER_TRIGGER_SEL_PININPUT(base->CSnPinIndex);
timerConfig.triggerPolarity = kFLEXIO_TimerTriggerPolarityActiveLow;
timerConfig.triggerSource = kFLEXIO_TimerTriggerSourceInternal;
timerConfig.pinConfig = kFLEXIO_PinConfigOutputDisabled;
timerConfig.pinSelect = base->SCKPinIndex;
timerConfig.pinPolarity = kFLEXIO_PinActiveHigh;
timerConfig.timerMode = kFLEXIO_TimerModeSingle16Bit;
timerConfig.timerOutput = kFLEXIO_TimerOutputZeroNotAffectedByReset;
timerConfig.timerDecrement = kFLEXIO_TimerDecSrcOnPinInputShiftPinInput;
timerConfig.timerReset = kFLEXIO_TimerResetNever;
timerConfig.timerEnable = kFLEXIO_TimerEnableOnTriggerRisingEdge;
timerConfig.timerStop = kFLEXIO_TimerStopBitDisabled;
if (slaveConfig->phase == kFLEXIO_SPI_ClockPhaseFirstEdge)
{
/* The configuration kFLEXIO_TimerDisableOnTimerCompare only support continuous
PCS access, change to kFLEXIO_TimerDisableNever to enable discontinuous PCS access. */
timerConfig.timerDisable = kFLEXIO_TimerDisableOnTimerCompare;
timerConfig.timerStart = kFLEXIO_TimerStartBitDisabled;
}
else
{
timerConfig.timerDisable = kFLEXIO_TimerDisableOnTriggerFallingEdge;
timerConfig.timerStart = kFLEXIO_TimerStartBitEnabled;
}
timerConfig.timerCompare = slaveConfig->dataMode * 2 - 1U;
FLEXIO_SetTimerConfig(base->flexioBase, base->timerIndex[0], &timerConfig);
}
void FLEXIO_SPI_SlaveDeinit(FLEXIO_SPI_Type *base)
{
FLEXIO_SPI_MasterDeinit(base);
}
void FLEXIO_SPI_SlaveGetDefaultConfig(flexio_spi_slave_config_t *slaveConfig)
{
assert(slaveConfig);
slaveConfig->enableSlave = true;
slaveConfig->enableInDoze = false;
slaveConfig->enableInDebug = true;
slaveConfig->enableFastAccess = false;
/* Default CPHA = 0. */
slaveConfig->phase = kFLEXIO_SPI_ClockPhaseFirstEdge;
/* Default bit count at 8. */
slaveConfig->dataMode = kFLEXIO_SPI_8BitMode;
}
void FLEXIO_SPI_EnableInterrupts(FLEXIO_SPI_Type *base, uint32_t mask)
{
if (mask & kFLEXIO_SPI_TxEmptyInterruptEnable)
{
FLEXIO_EnableShifterStatusInterrupts(base->flexioBase, 1 << base->shifterIndex[0]);
}
if (mask & kFLEXIO_SPI_RxFullInterruptEnable)
{
FLEXIO_EnableShifterStatusInterrupts(base->flexioBase, 1 << base->shifterIndex[1]);
}
}
void FLEXIO_SPI_DisableInterrupts(FLEXIO_SPI_Type *base, uint32_t mask)
{
if (mask & kFLEXIO_SPI_TxEmptyInterruptEnable)
{
FLEXIO_DisableShifterStatusInterrupts(base->flexioBase, 1 << base->shifterIndex[0]);
}
if (mask & kFLEXIO_SPI_RxFullInterruptEnable)
{
FLEXIO_DisableShifterStatusInterrupts(base->flexioBase, 1 << base->shifterIndex[1]);
}
}
void FLEXIO_SPI_EnableDMA(FLEXIO_SPI_Type *base, uint32_t mask, bool enable)
{
if (mask & kFLEXIO_SPI_TxDmaEnable)
{
FLEXIO_EnableShifterStatusDMA(base->flexioBase, 1U << base->shifterIndex[0], enable);
}
if (mask & kFLEXIO_SPI_RxDmaEnable)
{
FLEXIO_EnableShifterStatusDMA(base->flexioBase, 1U << base->shifterIndex[1], enable);
}
}
uint32_t FLEXIO_SPI_GetStatusFlags(FLEXIO_SPI_Type *base)
{
uint32_t shifterStatus = FLEXIO_GetShifterStatusFlags(base->flexioBase);
uint32_t status = 0;
status = ((shifterStatus & (1U << base->shifterIndex[0])) >> base->shifterIndex[0]);
status |= (((shifterStatus & (1U << base->shifterIndex[1])) >> (base->shifterIndex[1])) << 1U);
return status;
}
void FLEXIO_SPI_ClearStatusFlags(FLEXIO_SPI_Type *base, uint32_t mask)
{
if (mask & kFLEXIO_SPI_TxBufferEmptyFlag)
{
FLEXIO_ClearShifterStatusFlags(base->flexioBase, 1U << base->shifterIndex[0]);
}
if (mask & kFLEXIO_SPI_RxBufferFullFlag)
{
FLEXIO_ClearShifterStatusFlags(base->flexioBase, 1U << base->shifterIndex[1]);
}
}
void FLEXIO_SPI_MasterSetBaudRate(FLEXIO_SPI_Type *base, uint32_t baudRate_Bps, uint32_t srcClockHz)
{
uint16_t timerDiv = 0;
uint16_t timerCmp = 0;
FLEXIO_Type *flexioBase = base->flexioBase;
/* Set TIMCMP[7:0] = (baud rate divider / 2) - 1.*/
timerDiv = srcClockHz / baudRate_Bps;
timerDiv = timerDiv / 2 - 1U;
timerCmp = flexioBase->TIMCMP[base->timerIndex[0]];
timerCmp &= 0xFF00U;
timerCmp |= timerDiv;
flexioBase->TIMCMP[base->timerIndex[0]] = timerCmp;
}
void FLEXIO_SPI_WriteBlocking(FLEXIO_SPI_Type *base,
flexio_spi_shift_direction_t direction,
const uint8_t *buffer,
size_t size)
{
assert(buffer);
assert(size);
while (size--)
{
/* Wait until data transfer complete. */
while (!(FLEXIO_SPI_GetStatusFlags(base) & kFLEXIO_SPI_TxBufferEmptyFlag))
{
}
FLEXIO_SPI_WriteData(base, direction, *buffer++);
}
}
void FLEXIO_SPI_ReadBlocking(FLEXIO_SPI_Type *base,
flexio_spi_shift_direction_t direction,
uint8_t *buffer,
size_t size)
{
assert(buffer);
assert(size);
while (size--)
{
/* Wait until data transfer complete. */
while (!(FLEXIO_SPI_GetStatusFlags(base) & kFLEXIO_SPI_RxBufferFullFlag))
{
}
*buffer++ = FLEXIO_SPI_ReadData(base, direction);
}
}
void FLEXIO_SPI_MasterTransferBlocking(FLEXIO_SPI_Type *base, flexio_spi_transfer_t *xfer)
{
flexio_spi_shift_direction_t direction;
uint8_t bytesPerFrame;
uint32_t dataMode = 0;
uint16_t timerCmp = base->flexioBase->TIMCMP[base->timerIndex[0]];
uint16_t tmpData = FLEXIO_SPI_DUMMYDATA;
timerCmp &= 0x00FFU;
/* Configure the values in handle. */
switch (xfer->flags)
{
case kFLEXIO_SPI_8bitMsb:
dataMode = (8 * 2 - 1U) << 8U;
bytesPerFrame = 1;
direction = kFLEXIO_SPI_MsbFirst;
break;
case kFLEXIO_SPI_8bitLsb:
dataMode = (8 * 2 - 1U) << 8U;
bytesPerFrame = 1;
direction = kFLEXIO_SPI_LsbFirst;
break;
case kFLEXIO_SPI_16bitMsb:
dataMode = (16 * 2 - 1U) << 8U;
bytesPerFrame = 2;
direction = kFLEXIO_SPI_MsbFirst;
break;
case kFLEXIO_SPI_16bitLsb:
dataMode = (16 * 2 - 1U) << 8U;
bytesPerFrame = 2;
direction = kFLEXIO_SPI_LsbFirst;
break;
default:
dataMode = (8 * 2 - 1U) << 8U;
bytesPerFrame = 1;
direction = kFLEXIO_SPI_MsbFirst;
assert(true);
break;
}
dataMode |= timerCmp;
/* Configure transfer size. */
base->flexioBase->TIMCMP[base->timerIndex[0]] = dataMode;
while (xfer->dataSize)
{
/* Wait until data transfer complete. */
while (!(FLEXIO_SPI_GetStatusFlags(base) & kFLEXIO_SPI_TxBufferEmptyFlag))
{
}
if (xfer->txData != NULL)
{
/* Transmit data and update tx size/buff. */
if (bytesPerFrame == 1U)
{
tmpData = *(xfer->txData);
xfer->txData++;
}
else
{
if (direction == kFLEXIO_SPI_MsbFirst)
{
tmpData = (uint32_t)(xfer->txData[0]) << 8U;
tmpData += xfer->txData[1];
}
else
{
tmpData = (uint32_t)(xfer->txData[1]) << 8U;
tmpData += xfer->txData[0];
}
xfer->txData += 2U;
}
}
else
{
tmpData = FLEXIO_SPI_DUMMYDATA;
}
xfer->dataSize -= bytesPerFrame;
FLEXIO_SPI_WriteData(base, direction, tmpData);
while (!(FLEXIO_SPI_GetStatusFlags(base) & kFLEXIO_SPI_RxBufferFullFlag))
{
}
tmpData = FLEXIO_SPI_ReadData(base, direction);
if (xfer->rxData != NULL)
{
if (bytesPerFrame == 1U)
{
*xfer->rxData = tmpData;
xfer->rxData++;
}
else
{
if (direction == kFLEXIO_SPI_MsbFirst)
{
*((uint16_t *)(xfer->rxData)) = tmpData;
}
else
{
*((uint16_t *)(xfer->rxData)) = (((tmpData << 8) & 0xff00U) | ((tmpData >> 8) & 0x00ffU));
}
xfer->rxData += 2U;
}
}
}
}
status_t FLEXIO_SPI_MasterTransferCreateHandle(FLEXIO_SPI_Type *base,
flexio_spi_master_handle_t *handle,
flexio_spi_master_transfer_callback_t callback,
void *userData)
{
assert(handle);
IRQn_Type flexio_irqs[] = FLEXIO_IRQS;
/* Zero the handle. */
memset(handle, 0, sizeof(*handle));
/* Register callback and userData. */
handle->callback = callback;
handle->userData = userData;
/* Enable interrupt in NVIC. */
EnableIRQ(flexio_irqs[FLEXIO_SPI_GetInstance(base)]);
/* Save the context in global variables to support the double weak mechanism. */
return FLEXIO_RegisterHandleIRQ(base, handle, FLEXIO_SPI_MasterTransferHandleIRQ);
}
status_t FLEXIO_SPI_MasterTransferNonBlocking(FLEXIO_SPI_Type *base,
flexio_spi_master_handle_t *handle,
flexio_spi_transfer_t *xfer)
{
assert(handle);
assert(xfer);
uint32_t dataMode = 0;
uint16_t timerCmp = base->flexioBase->TIMCMP[base->timerIndex[0]];
uint16_t tmpData = FLEXIO_SPI_DUMMYDATA;
timerCmp &= 0x00FFU;
/* Check if SPI is busy. */
if (handle->state == kFLEXIO_SPI_Busy)
{
return kStatus_FLEXIO_SPI_Busy;
}
/* Check if the argument is legal. */
if ((xfer->txData == NULL) && (xfer->rxData == NULL))
{
return kStatus_InvalidArgument;
}
/* Configure the values in handle */
switch (xfer->flags)
{
case kFLEXIO_SPI_8bitMsb:
dataMode = (8 * 2 - 1U) << 8U;
handle->bytePerFrame = 1U;
handle->direction = kFLEXIO_SPI_MsbFirst;
break;
case kFLEXIO_SPI_8bitLsb:
dataMode = (8 * 2 - 1U) << 8U;
handle->bytePerFrame = 1U;
handle->direction = kFLEXIO_SPI_LsbFirst;
break;
case kFLEXIO_SPI_16bitMsb:
dataMode = (16 * 2 - 1U) << 8U;
handle->bytePerFrame = 2U;
handle->direction = kFLEXIO_SPI_MsbFirst;
break;
case kFLEXIO_SPI_16bitLsb:
dataMode = (16 * 2 - 1U) << 8U;
handle->bytePerFrame = 2U;
handle->direction = kFLEXIO_SPI_LsbFirst;
break;
default:
dataMode = (8 * 2 - 1U) << 8U;
handle->bytePerFrame = 1U;
handle->direction = kFLEXIO_SPI_MsbFirst;
assert(true);
break;
}
dataMode |= timerCmp;
/* Configure transfer size. */
base->flexioBase->TIMCMP[base->timerIndex[0]] = dataMode;
handle->state = kFLEXIO_SPI_Busy;
handle->txData = xfer->txData;
handle->rxData = xfer->rxData;
handle->rxRemainingBytes = xfer->dataSize;
/* Save total transfer size. */
handle->transferSize = xfer->dataSize;
/* Send first byte of data to trigger the rx interrupt. */
if (handle->txData != NULL)
{
/* Transmit data and update tx size/buff. */
if (handle->bytePerFrame == 1U)
{
tmpData = *(handle->txData);
handle->txData++;
}
else
{
if (handle->direction == kFLEXIO_SPI_MsbFirst)
{
tmpData = (uint32_t)(handle->txData[0]) << 8U;
tmpData += handle->txData[1];
}
else
{
tmpData = (uint32_t)(handle->txData[1]) << 8U;
tmpData += handle->txData[0];
}
handle->txData += 2U;
}
}
else
{
tmpData = FLEXIO_SPI_DUMMYDATA;
}
handle->txRemainingBytes = xfer->dataSize - handle->bytePerFrame;
FLEXIO_SPI_WriteData(base, handle->direction, tmpData);
/* Enable transmit and receive interrupt to handle rx. */
FLEXIO_SPI_EnableInterrupts(base, kFLEXIO_SPI_RxFullInterruptEnable);
return kStatus_Success;
}
status_t FLEXIO_SPI_MasterTransferGetCount(FLEXIO_SPI_Type *base, flexio_spi_master_handle_t *handle, size_t *count)
{
assert(handle);
if (!count)
{
return kStatus_InvalidArgument;
}
/* Return remaing bytes in different cases. */
if (handle->rxData)
{
*count = handle->transferSize - handle->rxRemainingBytes;
}
else
{
*count = handle->transferSize - handle->txRemainingBytes;
}
return kStatus_Success;
}
void FLEXIO_SPI_MasterTransferAbort(FLEXIO_SPI_Type *base, flexio_spi_master_handle_t *handle)
{
assert(handle);
FLEXIO_SPI_DisableInterrupts(base, kFLEXIO_SPI_RxFullInterruptEnable);
FLEXIO_SPI_DisableInterrupts(base, kFLEXIO_SPI_TxEmptyInterruptEnable);
/* Transfer finished, set the state to idle. */
handle->state = kFLEXIO_SPI_Idle;
/* Clear the internal state. */
handle->rxRemainingBytes = 0;
handle->txRemainingBytes = 0;
}
void FLEXIO_SPI_MasterTransferHandleIRQ(void *spiType, void *spiHandle)
{
assert(spiHandle);
flexio_spi_master_handle_t *handle = (flexio_spi_master_handle_t *)spiHandle;
FLEXIO_SPI_Type *base;
uint32_t status;
if (handle->state == kFLEXIO_SPI_Idle)
{
return;
}
base = (FLEXIO_SPI_Type *)spiType;
status = FLEXIO_SPI_GetStatusFlags(base);
/* Handle rx. */
if ((status & kFLEXIO_SPI_RxBufferFullFlag) && (handle->rxRemainingBytes))
{
FLEXIO_SPI_TransferReceiveTransaction(base, handle);
}
/* Handle tx. */
if ((status & kFLEXIO_SPI_TxBufferEmptyFlag) && (handle->txRemainingBytes))
{
FLEXIO_SPI_TransferSendTransaction(base, handle);
}
/* All the transfer finished. */
if ((handle->txRemainingBytes == 0U) && (handle->rxRemainingBytes == 0U))
{
FLEXIO_SPI_MasterTransferAbort(base, handle);
if (handle->callback)
{
(handle->callback)(base, handle, kStatus_FLEXIO_SPI_Idle, handle->userData);
}
}
}
status_t FLEXIO_SPI_SlaveTransferCreateHandle(FLEXIO_SPI_Type *base,
flexio_spi_slave_handle_t *handle,
flexio_spi_slave_transfer_callback_t callback,
void *userData)
{
assert(handle);
IRQn_Type flexio_irqs[] = FLEXIO_IRQS;
/* Zero the handle. */
memset(handle, 0, sizeof(*handle));
/* Register callback and userData. */
handle->callback = callback;
handle->userData = userData;
/* Enable interrupt in NVIC. */
EnableIRQ(flexio_irqs[FLEXIO_SPI_GetInstance(base)]);
/* Save the context in global variables to support the double weak mechanism. */
return FLEXIO_RegisterHandleIRQ(base, handle, FLEXIO_SPI_SlaveTransferHandleIRQ);
}
status_t FLEXIO_SPI_SlaveTransferNonBlocking(FLEXIO_SPI_Type *base,
flexio_spi_slave_handle_t *handle,
flexio_spi_transfer_t *xfer)
{
assert(handle);
assert(xfer);
uint32_t dataMode = 0;
/* Check if SPI is busy. */
if (handle->state == kFLEXIO_SPI_Busy)
{
return kStatus_FLEXIO_SPI_Busy;
}
/* Check if the argument is legal. */
if ((xfer->txData == NULL) && (xfer->rxData == NULL))
{
return kStatus_InvalidArgument;
}
/* Configure the values in handle */
switch (xfer->flags)
{
case kFLEXIO_SPI_8bitMsb:
dataMode = 8 * 2 - 1U;
handle->bytePerFrame = 1U;
handle->direction = kFLEXIO_SPI_MsbFirst;
break;
case kFLEXIO_SPI_8bitLsb:
dataMode = 8 * 2 - 1U;
handle->bytePerFrame = 1U;
handle->direction = kFLEXIO_SPI_LsbFirst;
break;
case kFLEXIO_SPI_16bitMsb:
dataMode = 16 * 2 - 1U;
handle->bytePerFrame = 2U;
handle->direction = kFLEXIO_SPI_MsbFirst;
break;
case kFLEXIO_SPI_16bitLsb:
dataMode = 16 * 2 - 1U;
handle->bytePerFrame = 2U;
handle->direction = kFLEXIO_SPI_LsbFirst;
break;
default:
dataMode = 8 * 2 - 1U;
handle->bytePerFrame = 1U;
handle->direction = kFLEXIO_SPI_MsbFirst;
assert(true);
break;
}
/* Configure transfer size. */
base->flexioBase->TIMCMP[base->timerIndex[0]] = dataMode;
handle->state = kFLEXIO_SPI_Busy;
handle->txData = xfer->txData;
handle->rxData = xfer->rxData;
handle->txRemainingBytes = xfer->dataSize;
handle->rxRemainingBytes = xfer->dataSize;
/* Save total transfer size. */
handle->transferSize = xfer->dataSize;
/* Enable transmit and receive interrupt to handle tx and rx. */
FLEXIO_SPI_EnableInterrupts(base, kFLEXIO_SPI_TxEmptyInterruptEnable);
FLEXIO_SPI_EnableInterrupts(base, kFLEXIO_SPI_RxFullInterruptEnable);
return kStatus_Success;
}
void FLEXIO_SPI_SlaveTransferHandleIRQ(void *spiType, void *spiHandle)
{
assert(spiHandle);
flexio_spi_master_handle_t *handle = (flexio_spi_master_handle_t *)spiHandle;
FLEXIO_SPI_Type *base;
uint32_t status;
if (handle->state == kFLEXIO_SPI_Idle)
{
return;
}
base = (FLEXIO_SPI_Type *)spiType;
status = FLEXIO_SPI_GetStatusFlags(base);
/* Handle tx. */
if ((status & kFLEXIO_SPI_TxBufferEmptyFlag) && (handle->txRemainingBytes))
{
FLEXIO_SPI_TransferSendTransaction(base, handle);
}
/* Handle rx. */
if ((status & kFLEXIO_SPI_RxBufferFullFlag) && (handle->rxRemainingBytes))
{
FLEXIO_SPI_TransferReceiveTransaction(base, handle);
}
/* All the transfer finished. */
if ((handle->txRemainingBytes == 0U) && (handle->rxRemainingBytes == 0U))
{
FLEXIO_SPI_SlaveTransferAbort(base, handle);
if (handle->callback)
{
(handle->callback)(base, handle, kStatus_FLEXIO_SPI_Idle, handle->userData);
}
}
}

View File

@ -0,0 +1,685 @@
/*
* Copyright (c) 2015, Freescale Semiconductor, Inc.
* Copyright 2016-2017 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef _FSL_FLEXIO_SPI_H_
#define _FSL_FLEXIO_SPI_H_
#include "fsl_common.h"
#include "fsl_flexio.h"
/*!
* @addtogroup flexio_spi
* @{
*/
/*******************************************************************************
* Definitions
******************************************************************************/
/*! @name Driver version */
/*@{*/
/*! @brief FlexIO SPI driver version 2.1.1. */
#define FSL_FLEXIO_SPI_DRIVER_VERSION (MAKE_VERSION(2, 1, 1))
/*@}*/
#ifndef FLEXIO_SPI_DUMMYDATA
/*! @brief FlexIO SPI dummy transfer data, the data is sent while txData is NULL. */
#define FLEXIO_SPI_DUMMYDATA (0xFFFFU)
#endif
/*! @brief Error codes for the FlexIO SPI driver. */
enum _flexio_spi_status
{
kStatus_FLEXIO_SPI_Busy = MAKE_STATUS(kStatusGroup_FLEXIO_SPI, 1), /*!< FlexIO SPI is busy. */
kStatus_FLEXIO_SPI_Idle = MAKE_STATUS(kStatusGroup_FLEXIO_SPI, 2), /*!< SPI is idle */
kStatus_FLEXIO_SPI_Error = MAKE_STATUS(kStatusGroup_FLEXIO_SPI, 3), /*!< FlexIO SPI error. */
};
/*! @brief FlexIO SPI clock phase configuration. */
typedef enum _flexio_spi_clock_phase
{
kFLEXIO_SPI_ClockPhaseFirstEdge = 0x0U, /*!< First edge on SPSCK occurs at the middle of the first
* cycle of a data transfer. */
kFLEXIO_SPI_ClockPhaseSecondEdge = 0x1U, /*!< First edge on SPSCK occurs at the start of the
* first cycle of a data transfer. */
} flexio_spi_clock_phase_t;
/*! @brief FlexIO SPI data shifter direction options. */
typedef enum _flexio_spi_shift_direction
{
kFLEXIO_SPI_MsbFirst = 0, /*!< Data transfers start with most significant bit. */
kFLEXIO_SPI_LsbFirst = 1, /*!< Data transfers start with least significant bit. */
} flexio_spi_shift_direction_t;
/*! @brief FlexIO SPI data length mode options. */
typedef enum _flexio_spi_data_bitcount_mode
{
kFLEXIO_SPI_8BitMode = 0x08U, /*!< 8-bit data transmission mode. */
kFLEXIO_SPI_16BitMode = 0x10U, /*!< 16-bit data transmission mode. */
} flexio_spi_data_bitcount_mode_t;
/*! @brief Define FlexIO SPI interrupt mask. */
enum _flexio_spi_interrupt_enable
{
kFLEXIO_SPI_TxEmptyInterruptEnable = 0x1U, /*!< Transmit buffer empty interrupt enable. */
kFLEXIO_SPI_RxFullInterruptEnable = 0x2U, /*!< Receive buffer full interrupt enable. */
};
/*! @brief Define FlexIO SPI status mask. */
enum _flexio_spi_status_flags
{
kFLEXIO_SPI_TxBufferEmptyFlag = 0x1U, /*!< Transmit buffer empty flag. */
kFLEXIO_SPI_RxBufferFullFlag = 0x2U, /*!< Receive buffer full flag. */
};
/*! @brief Define FlexIO SPI DMA mask. */
enum _flexio_spi_dma_enable
{
kFLEXIO_SPI_TxDmaEnable = 0x1U, /*!< Tx DMA request source */
kFLEXIO_SPI_RxDmaEnable = 0x2U, /*!< Rx DMA request source */
kFLEXIO_SPI_DmaAllEnable = 0x3U, /*!< All DMA request source*/
};
/*! @brief Define FlexIO SPI transfer flags. */
enum _flexio_spi_transfer_flags
{
kFLEXIO_SPI_8bitMsb = 0x1U, /*!< FlexIO SPI 8-bit MSB first */
kFLEXIO_SPI_8bitLsb = 0x2U, /*!< FlexIO SPI 8-bit LSB first */
kFLEXIO_SPI_16bitMsb = 0x9U, /*!< FlexIO SPI 16-bit MSB first */
kFLEXIO_SPI_16bitLsb = 0xaU, /*!< FlexIO SPI 16-bit LSB first */
};
/*! @brief Define FlexIO SPI access structure typedef. */
typedef struct _flexio_spi_type
{
FLEXIO_Type *flexioBase; /*!< FlexIO base pointer. */
uint8_t SDOPinIndex; /*!< Pin select for data output. */
uint8_t SDIPinIndex; /*!< Pin select for data input. */
uint8_t SCKPinIndex; /*!< Pin select for clock. */
uint8_t CSnPinIndex; /*!< Pin select for enable. */
uint8_t shifterIndex[2]; /*!< Shifter index used in FlexIO SPI. */
uint8_t timerIndex[2]; /*!< Timer index used in FlexIO SPI. */
} FLEXIO_SPI_Type;
/*! @brief Define FlexIO SPI master configuration structure. */
typedef struct _flexio_spi_master_config
{
bool enableMaster; /*!< Enable/disable FlexIO SPI master after configuration. */
bool enableInDoze; /*!< Enable/disable FlexIO operation in doze mode. */
bool enableInDebug; /*!< Enable/disable FlexIO operation in debug mode. */
bool enableFastAccess; /*!< Enable/disable fast access to FlexIO registers,
fast access requires the FlexIO clock to be at least
twice the frequency of the bus clock. */
uint32_t baudRate_Bps; /*!< Baud rate in Bps. */
flexio_spi_clock_phase_t phase; /*!< Clock phase. */
flexio_spi_data_bitcount_mode_t dataMode; /*!< 8bit or 16bit mode. */
} flexio_spi_master_config_t;
/*! @brief Define FlexIO SPI slave configuration structure. */
typedef struct _flexio_spi_slave_config
{
bool enableSlave; /*!< Enable/disable FlexIO SPI slave after configuration. */
bool enableInDoze; /*!< Enable/disable FlexIO operation in doze mode. */
bool enableInDebug; /*!< Enable/disable FlexIO operation in debug mode. */
bool enableFastAccess; /*!< Enable/disable fast access to FlexIO registers,
fast access requires the FlexIO clock to be at least
twice the frequency of the bus clock. */
flexio_spi_clock_phase_t phase; /*!< Clock phase. */
flexio_spi_data_bitcount_mode_t dataMode; /*!< 8bit or 16bit mode. */
} flexio_spi_slave_config_t;
/*! @brief Define FlexIO SPI transfer structure. */
typedef struct _flexio_spi_transfer
{
uint8_t *txData; /*!< Send buffer. */
uint8_t *rxData; /*!< Receive buffer. */
size_t dataSize; /*!< Transfer bytes. */
uint8_t flags; /*!< FlexIO SPI control flag, MSB first or LSB first. */
} flexio_spi_transfer_t;
/*! @brief typedef for flexio_spi_master_handle_t in advance. */
typedef struct _flexio_spi_master_handle flexio_spi_master_handle_t;
/*! @brief Slave handle is the same with master handle. */
typedef flexio_spi_master_handle_t flexio_spi_slave_handle_t;
/*! @brief FlexIO SPI master callback for finished transmit */
typedef void (*flexio_spi_master_transfer_callback_t)(FLEXIO_SPI_Type *base,
flexio_spi_master_handle_t *handle,
status_t status,
void *userData);
/*! @brief FlexIO SPI slave callback for finished transmit */
typedef void (*flexio_spi_slave_transfer_callback_t)(FLEXIO_SPI_Type *base,
flexio_spi_slave_handle_t *handle,
status_t status,
void *userData);
/*! @brief Define FlexIO SPI handle structure. */
struct _flexio_spi_master_handle
{
uint8_t *txData; /*!< Transfer buffer. */
uint8_t *rxData; /*!< Receive buffer. */
size_t transferSize; /*!< Total bytes to be transferred. */
volatile size_t txRemainingBytes; /*!< Send data remaining in bytes. */
volatile size_t rxRemainingBytes; /*!< Receive data remaining in bytes. */
volatile uint32_t state; /*!< FlexIO SPI internal state. */
uint8_t bytePerFrame; /*!< SPI mode, 2bytes or 1byte in a frame */
flexio_spi_shift_direction_t direction; /*!< Shift direction. */
flexio_spi_master_transfer_callback_t callback; /*!< FlexIO SPI callback. */
void *userData; /*!< Callback parameter. */
};
/*******************************************************************************
* API
******************************************************************************/
#if defined(__cplusplus)
extern "C" {
#endif /*_cplusplus*/
/*!
* @name FlexIO SPI Configuration
* @{
*/
/*!
* @brief Ungates the FlexIO clock, resets the FlexIO module, configures the FlexIO SPI master hardware,
* and configures the FlexIO SPI with FlexIO SPI master configuration. The
* configuration structure can be filled by the user, or be set with default values
* by the FLEXIO_SPI_MasterGetDefaultConfig().
*
* @note FlexIO SPI master only support CPOL = 0, which means clock inactive low.
*
* Example
@code
FLEXIO_SPI_Type spiDev = {
.flexioBase = FLEXIO,
.SDOPinIndex = 0,
.SDIPinIndex = 1,
.SCKPinIndex = 2,
.CSnPinIndex = 3,
.shifterIndex = {0,1},
.timerIndex = {0,1}
};
flexio_spi_master_config_t config = {
.enableMaster = true,
.enableInDoze = false,
.enableInDebug = true,
.enableFastAccess = false,
.baudRate_Bps = 500000,
.phase = kFLEXIO_SPI_ClockPhaseFirstEdge,
.direction = kFLEXIO_SPI_MsbFirst,
.dataMode = kFLEXIO_SPI_8BitMode
};
FLEXIO_SPI_MasterInit(&spiDev, &config, srcClock_Hz);
@endcode
*
* @param base Pointer to the FLEXIO_SPI_Type structure.
* @param masterConfig Pointer to the flexio_spi_master_config_t structure.
* @param srcClock_Hz FlexIO source clock in Hz.
*/
void FLEXIO_SPI_MasterInit(FLEXIO_SPI_Type *base, flexio_spi_master_config_t *masterConfig, uint32_t srcClock_Hz);
/*!
* @brief Gates the FlexIO clock.
*
* @param base Pointer to the FLEXIO_SPI_Type.
*/
void FLEXIO_SPI_MasterDeinit(FLEXIO_SPI_Type *base);
/*!
* @brief Gets the default configuration to configure the FlexIO SPI master. The configuration
* can be used directly by calling the FLEXIO_SPI_MasterConfigure().
* Example:
@code
flexio_spi_master_config_t masterConfig;
FLEXIO_SPI_MasterGetDefaultConfig(&masterConfig);
@endcode
* @param masterConfig Pointer to the flexio_spi_master_config_t structure.
*/
void FLEXIO_SPI_MasterGetDefaultConfig(flexio_spi_master_config_t *masterConfig);
/*!
* @brief Ungates the FlexIO clock, resets the FlexIO module, configures the FlexIO SPI slave hardware
* configuration, and configures the FlexIO SPI with FlexIO SPI slave configuration. The
* configuration structure can be filled by the user, or be set with default values
* by the FLEXIO_SPI_SlaveGetDefaultConfig().
*
* @note Only one timer is needed in the FlexIO SPI slave. As a result, the second timer index is ignored.
* FlexIO SPI slave only support CPOL = 0, which means clock inactive low.
* Example
@code
FLEXIO_SPI_Type spiDev = {
.flexioBase = FLEXIO,
.SDOPinIndex = 0,
.SDIPinIndex = 1,
.SCKPinIndex = 2,
.CSnPinIndex = 3,
.shifterIndex = {0,1},
.timerIndex = {0}
};
flexio_spi_slave_config_t config = {
.enableSlave = true,
.enableInDoze = false,
.enableInDebug = true,
.enableFastAccess = false,
.phase = kFLEXIO_SPI_ClockPhaseFirstEdge,
.direction = kFLEXIO_SPI_MsbFirst,
.dataMode = kFLEXIO_SPI_8BitMode
};
FLEXIO_SPI_SlaveInit(&spiDev, &config);
@endcode
* @param base Pointer to the FLEXIO_SPI_Type structure.
* @param slaveConfig Pointer to the flexio_spi_slave_config_t structure.
*/
void FLEXIO_SPI_SlaveInit(FLEXIO_SPI_Type *base, flexio_spi_slave_config_t *slaveConfig);
/*!
* @brief Gates the FlexIO clock.
*
* @param base Pointer to the FLEXIO_SPI_Type.
*/
void FLEXIO_SPI_SlaveDeinit(FLEXIO_SPI_Type *base);
/*!
* @brief Gets the default configuration to configure the FlexIO SPI slave. The configuration
* can be used directly for calling the FLEXIO_SPI_SlaveConfigure().
* Example:
@code
flexio_spi_slave_config_t slaveConfig;
FLEXIO_SPI_SlaveGetDefaultConfig(&slaveConfig);
@endcode
* @param slaveConfig Pointer to the flexio_spi_slave_config_t structure.
*/
void FLEXIO_SPI_SlaveGetDefaultConfig(flexio_spi_slave_config_t *slaveConfig);
/*@}*/
/*!
* @name Status
* @{
*/
/*!
* @brief Gets FlexIO SPI status flags.
*
* @param base Pointer to the FLEXIO_SPI_Type structure.
* @return status flag; Use the status flag to AND the following flag mask and get the status.
* @arg kFLEXIO_SPI_TxEmptyFlag
* @arg kFLEXIO_SPI_RxEmptyFlag
*/
uint32_t FLEXIO_SPI_GetStatusFlags(FLEXIO_SPI_Type *base);
/*!
* @brief Clears FlexIO SPI status flags.
*
* @param base Pointer to the FLEXIO_SPI_Type structure.
* @param mask status flag
* The parameter can be any combination of the following values:
* @arg kFLEXIO_SPI_TxEmptyFlag
* @arg kFLEXIO_SPI_RxEmptyFlag
*/
void FLEXIO_SPI_ClearStatusFlags(FLEXIO_SPI_Type *base, uint32_t mask);
/*@}*/
/*!
* @name Interrupts
* @{
*/
/*!
* @brief Enables the FlexIO SPI interrupt.
*
* This function enables the FlexIO SPI interrupt.
*
* @param base Pointer to the FLEXIO_SPI_Type structure.
* @param mask interrupt source. The parameter can be any combination of the following values:
* @arg kFLEXIO_SPI_RxFullInterruptEnable
* @arg kFLEXIO_SPI_TxEmptyInterruptEnable
*/
void FLEXIO_SPI_EnableInterrupts(FLEXIO_SPI_Type *base, uint32_t mask);
/*!
* @brief Disables the FlexIO SPI interrupt.
*
* This function disables the FlexIO SPI interrupt.
*
* @param base Pointer to the FLEXIO_SPI_Type structure.
* @param mask interrupt source The parameter can be any combination of the following values:
* @arg kFLEXIO_SPI_RxFullInterruptEnable
* @arg kFLEXIO_SPI_TxEmptyInterruptEnable
*/
void FLEXIO_SPI_DisableInterrupts(FLEXIO_SPI_Type *base, uint32_t mask);
/*@}*/
/*!
* @name DMA Control
* @{
*/
/*!
* @brief Enables/disables the FlexIO SPI transmit DMA. This function enables/disables the FlexIO SPI Tx DMA,
* which means that asserting the kFLEXIO_SPI_TxEmptyFlag does/doesn't trigger the DMA request.
*
* @param base Pointer to the FLEXIO_SPI_Type structure.
* @param mask SPI DMA source.
* @param enable True means enable DMA, false means disable DMA.
*/
void FLEXIO_SPI_EnableDMA(FLEXIO_SPI_Type *base, uint32_t mask, bool enable);
/*!
* @brief Gets the FlexIO SPI transmit data register address for MSB first transfer.
*
* This function returns the SPI data register address, which is mainly used by DMA/eDMA.
*
* @param base Pointer to the FLEXIO_SPI_Type structure.
* @param direction Shift direction of MSB first or LSB first.
* @return FlexIO SPI transmit data register address.
*/
static inline uint32_t FLEXIO_SPI_GetTxDataRegisterAddress(FLEXIO_SPI_Type *base,
flexio_spi_shift_direction_t direction)
{
if (direction == kFLEXIO_SPI_MsbFirst)
{
return FLEXIO_GetShifterBufferAddress(base->flexioBase, kFLEXIO_ShifterBufferBitSwapped,
base->shifterIndex[0]) +
3U;
}
else
{
return FLEXIO_GetShifterBufferAddress(base->flexioBase, kFLEXIO_ShifterBuffer, base->shifterIndex[0]);
}
}
/*!
* @brief Gets the FlexIO SPI receive data register address for the MSB first transfer.
*
* This function returns the SPI data register address, which is mainly used by DMA/eDMA.
*
* @param base Pointer to the FLEXIO_SPI_Type structure.
* @param direction Shift direction of MSB first or LSB first.
* @return FlexIO SPI receive data register address.
*/
static inline uint32_t FLEXIO_SPI_GetRxDataRegisterAddress(FLEXIO_SPI_Type *base,
flexio_spi_shift_direction_t direction)
{
if (direction == kFLEXIO_SPI_MsbFirst)
{
return FLEXIO_GetShifterBufferAddress(base->flexioBase, kFLEXIO_ShifterBufferBitSwapped, base->shifterIndex[1]);
}
else
{
return FLEXIO_GetShifterBufferAddress(base->flexioBase, kFLEXIO_ShifterBuffer, base->shifterIndex[1]) + 3U;
}
}
/*@}*/
/*!
* @name Bus Operations
* @{
*/
/*!
* @brief Enables/disables the FlexIO SPI module operation.
*
* @param base Pointer to the FLEXIO_SPI_Type.
* @param enable True to enable, false to disable.
*/
static inline void FLEXIO_SPI_Enable(FLEXIO_SPI_Type *base, bool enable)
{
if (enable)
{
base->flexioBase->CTRL |= FLEXIO_CTRL_FLEXEN_MASK;
}
else
{
base->flexioBase->CTRL &= ~FLEXIO_CTRL_FLEXEN_MASK;
}
}
/*!
* @brief Sets baud rate for the FlexIO SPI transfer, which is only used for the master.
*
* @param base Pointer to the FLEXIO_SPI_Type structure.
* @param baudRate_Bps Baud Rate needed in Hz.
* @param srcClockHz SPI source clock frequency in Hz.
*/
void FLEXIO_SPI_MasterSetBaudRate(FLEXIO_SPI_Type *base, uint32_t baudRate_Bps, uint32_t srcClockHz);
/*!
* @brief Writes one byte of data, which is sent using the MSB method.
*
* @note This is a non-blocking API, which returns directly after the data is put into the
* data register but the data transfer is not finished on the bus. Ensure that
* the TxEmptyFlag is asserted before calling this API.
*
* @param base Pointer to the FLEXIO_SPI_Type structure.
* @param direction Shift direction of MSB first or LSB first.
* @param data 8 bit/16 bit data.
*/
static inline void FLEXIO_SPI_WriteData(FLEXIO_SPI_Type *base, flexio_spi_shift_direction_t direction, uint16_t data)
{
if (direction == kFLEXIO_SPI_MsbFirst)
{
base->flexioBase->SHIFTBUFBBS[base->shifterIndex[0]] = data;
}
else
{
base->flexioBase->SHIFTBUF[base->shifterIndex[0]] = data;
}
}
/*!
* @brief Reads 8 bit/16 bit data.
*
* @note This is a non-blocking API, which returns directly after the data is read from the
* data register. Ensure that the RxFullFlag is asserted before calling this API.
*
* @param base Pointer to the FLEXIO_SPI_Type structure.
* @param direction Shift direction of MSB first or LSB first.
* @return 8 bit/16 bit data received.
*/
static inline uint16_t FLEXIO_SPI_ReadData(FLEXIO_SPI_Type *base, flexio_spi_shift_direction_t direction)
{
if (direction == kFLEXIO_SPI_MsbFirst)
{
return base->flexioBase->SHIFTBUFBIS[base->shifterIndex[1]];
}
else
{
return base->flexioBase->SHIFTBUFBYS[base->shifterIndex[1]];
}
}
/*!
* @brief Sends a buffer of data bytes.
*
* @note This function blocks using the polling method until all bytes have been sent.
*
* @param base Pointer to the FLEXIO_SPI_Type structure.
* @param direction Shift direction of MSB first or LSB first.
* @param buffer The data bytes to send.
* @param size The number of data bytes to send.
*/
void FLEXIO_SPI_WriteBlocking(FLEXIO_SPI_Type *base,
flexio_spi_shift_direction_t direction,
const uint8_t *buffer,
size_t size);
/*!
* @brief Receives a buffer of bytes.
*
* @note This function blocks using the polling method until all bytes have been received.
*
* @param base Pointer to the FLEXIO_SPI_Type structure.
* @param direction Shift direction of MSB first or LSB first.
* @param buffer The buffer to store the received bytes.
* @param size The number of data bytes to be received.
* @param direction Shift direction of MSB first or LSB first.
*/
void FLEXIO_SPI_ReadBlocking(FLEXIO_SPI_Type *base,
flexio_spi_shift_direction_t direction,
uint8_t *buffer,
size_t size);
/*!
* @brief Receives a buffer of bytes.
*
* @note This function blocks via polling until all bytes have been received.
*
* @param base pointer to FLEXIO_SPI_Type structure
* @param xfer FlexIO SPI transfer structure, see #flexio_spi_transfer_t.
*/
void FLEXIO_SPI_MasterTransferBlocking(FLEXIO_SPI_Type *base, flexio_spi_transfer_t *xfer);
/*Transactional APIs*/
/*!
* @name Transactional
* @{
*/
/*!
* @brief Initializes the FlexIO SPI Master handle, which is used in transactional functions.
*
* @param base Pointer to the FLEXIO_SPI_Type structure.
* @param handle Pointer to the flexio_spi_master_handle_t structure to store the transfer state.
* @param callback The callback function.
* @param userData The parameter of the callback function.
* @retval kStatus_Success Successfully create the handle.
* @retval kStatus_OutOfRange The FlexIO type/handle/ISR table out of range.
*/
status_t FLEXIO_SPI_MasterTransferCreateHandle(FLEXIO_SPI_Type *base,
flexio_spi_master_handle_t *handle,
flexio_spi_master_transfer_callback_t callback,
void *userData);
/*!
* @brief Master transfer data using IRQ.
*
* This function sends data using IRQ. This is a non-blocking function, which returns
* right away. When all data is sent out/received, the callback function is called.
*
* @param base Pointer to the FLEXIO_SPI_Type structure.
* @param handle Pointer to the flexio_spi_master_handle_t structure to store the transfer state.
* @param xfer FlexIO SPI transfer structure. See #flexio_spi_transfer_t.
* @retval kStatus_Success Successfully start a transfer.
* @retval kStatus_InvalidArgument Input argument is invalid.
* @retval kStatus_FLEXIO_SPI_Busy SPI is not idle, is running another transfer.
*/
status_t FLEXIO_SPI_MasterTransferNonBlocking(FLEXIO_SPI_Type *base,
flexio_spi_master_handle_t *handle,
flexio_spi_transfer_t *xfer);
/*!
* @brief Aborts the master data transfer, which used IRQ.
*
* @param base Pointer to the FLEXIO_SPI_Type structure.
* @param handle Pointer to the flexio_spi_master_handle_t structure to store the transfer state.
*/
void FLEXIO_SPI_MasterTransferAbort(FLEXIO_SPI_Type *base, flexio_spi_master_handle_t *handle);
/*!
* @brief Gets the data transfer status which used IRQ.
*
* @param base Pointer to the FLEXIO_SPI_Type structure.
* @param handle Pointer to the flexio_spi_master_handle_t structure to store the transfer state.
* @param count Number of bytes transferred so far by the non-blocking transaction.
* @retval kStatus_InvalidArgument count is Invalid.
* @retval kStatus_Success Successfully return the count.
*/
status_t FLEXIO_SPI_MasterTransferGetCount(FLEXIO_SPI_Type *base, flexio_spi_master_handle_t *handle, size_t *count);
/*!
* @brief FlexIO SPI master IRQ handler function.
*
* @param spiType Pointer to the FLEXIO_SPI_Type structure.
* @param spiHandle Pointer to the flexio_spi_master_handle_t structure to store the transfer state.
*/
void FLEXIO_SPI_MasterTransferHandleIRQ(void *spiType, void *spiHandle);
/*!
* @brief Initializes the FlexIO SPI Slave handle, which is used in transactional functions.
*
* @param base Pointer to the FLEXIO_SPI_Type structure.
* @param handle Pointer to the flexio_spi_slave_handle_t structure to store the transfer state.
* @param callback The callback function.
* @param userData The parameter of the callback function.
* @retval kStatus_Success Successfully create the handle.
* @retval kStatus_OutOfRange The FlexIO type/handle/ISR table out of range.
*/
status_t FLEXIO_SPI_SlaveTransferCreateHandle(FLEXIO_SPI_Type *base,
flexio_spi_slave_handle_t *handle,
flexio_spi_slave_transfer_callback_t callback,
void *userData);
/*!
* @brief Slave transfer data using IRQ.
*
* This function sends data using IRQ. This is a non-blocking function, which returns
* right away. When all data is sent out/received, the callback function is called.
* @param handle Pointer to the flexio_spi_slave_handle_t structure to store the transfer state.
*
* @param base Pointer to the FLEXIO_SPI_Type structure.
* @param xfer FlexIO SPI transfer structure. See #flexio_spi_transfer_t.
* @retval kStatus_Success Successfully start a transfer.
* @retval kStatus_InvalidArgument Input argument is invalid.
* @retval kStatus_FLEXIO_SPI_Busy SPI is not idle; it is running another transfer.
*/
status_t FLEXIO_SPI_SlaveTransferNonBlocking(FLEXIO_SPI_Type *base,
flexio_spi_slave_handle_t *handle,
flexio_spi_transfer_t *xfer);
/*!
* @brief Aborts the slave data transfer which used IRQ, share same API with master.
*
* @param base Pointer to the FLEXIO_SPI_Type structure.
* @param handle Pointer to the flexio_spi_slave_handle_t structure to store the transfer state.
*/
static inline void FLEXIO_SPI_SlaveTransferAbort(FLEXIO_SPI_Type *base, flexio_spi_slave_handle_t *handle)
{
FLEXIO_SPI_MasterTransferAbort(base, handle);
}
/*!
* @brief Gets the data transfer status which used IRQ, share same API with master.
*
* @param base Pointer to the FLEXIO_SPI_Type structure.
* @param handle Pointer to the flexio_spi_slave_handle_t structure to store the transfer state.
* @param count Number of bytes transferred so far by the non-blocking transaction.
* @retval kStatus_InvalidArgument count is Invalid.
* @retval kStatus_Success Successfully return the count.
*/
static inline status_t FLEXIO_SPI_SlaveTransferGetCount(FLEXIO_SPI_Type *base,
flexio_spi_slave_handle_t *handle,
size_t *count)
{
return FLEXIO_SPI_MasterTransferGetCount(base, handle, count);
}
/*!
* @brief FlexIO SPI slave IRQ handler function.
*
* @param spiType Pointer to the FLEXIO_SPI_Type structure.
* @param spiHandle Pointer to the flexio_spi_slave_handle_t structure to store the transfer state.
*/
void FLEXIO_SPI_SlaveTransferHandleIRQ(void *spiType, void *spiHandle);
/*@}*/
#if defined(__cplusplus)
}
#endif /*_cplusplus*/
/*@}*/
#endif /*_FSL_FLEXIO_SPI_H_*/

View File

@ -0,0 +1,410 @@
/*
* Copyright (c) 2015, Freescale Semiconductor, Inc.
* Copyright 2016-2017 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include "fsl_flexio_spi_edma.h"
/*******************************************************************************
* Definitons
******************************************************************************/
/*<! Structure definition for spi_edma_private_handle_t. The structure is private. */
typedef struct _flexio_spi_master_edma_private_handle
{
FLEXIO_SPI_Type *base;
flexio_spi_master_edma_handle_t *handle;
} flexio_spi_master_edma_private_handle_t;
/*******************************************************************************
* Prototypes
******************************************************************************/
/*!
* @brief EDMA callback function for FLEXIO SPI send transfer.
*
* @param handle EDMA handle pointer.
* @param param Callback function parameter.
*/
static void FLEXIO_SPI_TxEDMACallback(edma_handle_t *handle, void *param, bool transferDone, uint32_t tcds);
/*!
* @brief EDMA callback function for FLEXIO SPI receive transfer.
*
* @param handle EDMA handle pointer.
* @param param Callback function parameter.
*/
static void FLEXIO_SPI_RxEDMACallback(edma_handle_t *handle, void *param, bool transferDone, uint32_t tcds);
/*!
* @brief EDMA config for FLEXIO SPI transfer.
*
* @param base pointer to FLEXIO_SPI_Type structure.
* @param handle pointer to flexio_spi_master_edma_handle_t structure to store the transfer state.
* @param xfer Pointer to flexio spi transfer structure.
*/
static void FLEXIO_SPI_EDMAConfig(FLEXIO_SPI_Type *base,
flexio_spi_master_edma_handle_t *handle,
flexio_spi_transfer_t *xfer);
/*******************************************************************************
* Variables
******************************************************************************/
/* Dummy data used to send */
static const uint16_t s_dummyData = FLEXIO_SPI_DUMMYDATA;
/*< @brief user configurable flexio spi handle count. */
#define FLEXIO_SPI_HANDLE_COUNT 2
/*<! Private handle only used for internally. */
static flexio_spi_master_edma_private_handle_t s_edmaPrivateHandle[FLEXIO_SPI_HANDLE_COUNT];
/*******************************************************************************
* Code
******************************************************************************/
static void FLEXIO_SPI_TxEDMACallback(edma_handle_t *handle, void *param, bool transferDone, uint32_t tcds)
{
tcds = tcds;
flexio_spi_master_edma_private_handle_t *spiPrivateHandle = (flexio_spi_master_edma_private_handle_t *)param;
/* Disable Tx DMA */
if (transferDone)
{
FLEXIO_SPI_EnableDMA(spiPrivateHandle->base, kFLEXIO_SPI_TxDmaEnable, false);
/* change the state */
spiPrivateHandle->handle->txInProgress = false;
/* All finished, call the callback */
if ((spiPrivateHandle->handle->txInProgress == false) && (spiPrivateHandle->handle->rxInProgress == false))
{
if (spiPrivateHandle->handle->callback)
{
(spiPrivateHandle->handle->callback)(spiPrivateHandle->base, spiPrivateHandle->handle, kStatus_Success,
spiPrivateHandle->handle->userData);
}
}
}
}
static void FLEXIO_SPI_RxEDMACallback(edma_handle_t *handle, void *param, bool transferDone, uint32_t tcds)
{
tcds = tcds;
flexio_spi_master_edma_private_handle_t *spiPrivateHandle = (flexio_spi_master_edma_private_handle_t *)param;
if (transferDone)
{
/* Disable Rx dma */
FLEXIO_SPI_EnableDMA(spiPrivateHandle->base, kFLEXIO_SPI_RxDmaEnable, false);
/* change the state */
spiPrivateHandle->handle->rxInProgress = false;
/* All finished, call the callback */
if ((spiPrivateHandle->handle->txInProgress == false) && (spiPrivateHandle->handle->rxInProgress == false))
{
if (spiPrivateHandle->handle->callback)
{
(spiPrivateHandle->handle->callback)(spiPrivateHandle->base, spiPrivateHandle->handle, kStatus_Success,
spiPrivateHandle->handle->userData);
}
}
}
}
static void FLEXIO_SPI_EDMAConfig(FLEXIO_SPI_Type *base,
flexio_spi_master_edma_handle_t *handle,
flexio_spi_transfer_t *xfer)
{
edma_transfer_config_t xferConfig;
flexio_spi_shift_direction_t direction;
uint8_t bytesPerFrame;
/* Configure the values in handle. */
switch (xfer->flags)
{
case kFLEXIO_SPI_8bitMsb:
bytesPerFrame = 1;
direction = kFLEXIO_SPI_MsbFirst;
break;
case kFLEXIO_SPI_8bitLsb:
bytesPerFrame = 1;
direction = kFLEXIO_SPI_LsbFirst;
break;
case kFLEXIO_SPI_16bitMsb:
bytesPerFrame = 2;
direction = kFLEXIO_SPI_MsbFirst;
break;
case kFLEXIO_SPI_16bitLsb:
bytesPerFrame = 2;
direction = kFLEXIO_SPI_LsbFirst;
break;
default:
bytesPerFrame = 1U;
direction = kFLEXIO_SPI_MsbFirst;
assert(true);
break;
}
/* Save total transfer size. */
handle->transferSize = xfer->dataSize;
/* Configure tx transfer EDMA. */
xferConfig.destAddr = FLEXIO_SPI_GetTxDataRegisterAddress(base, direction);
xferConfig.destOffset = 0;
if (bytesPerFrame == 1U)
{
xferConfig.srcTransferSize = kEDMA_TransferSize1Bytes;
xferConfig.destTransferSize = kEDMA_TransferSize1Bytes;
xferConfig.minorLoopBytes = 1;
}
else
{
if (direction == kFLEXIO_SPI_MsbFirst)
{
xferConfig.destAddr -= 1U;
}
xferConfig.srcTransferSize = kEDMA_TransferSize2Bytes;
xferConfig.destTransferSize = kEDMA_TransferSize2Bytes;
xferConfig.minorLoopBytes = 2;
}
/* Configure DMA channel. */
if (xfer->txData)
{
xferConfig.srcOffset = bytesPerFrame;
xferConfig.srcAddr = (uint32_t)(xfer->txData);
}
else
{
/* Disable the source increasement and source set to dummyData. */
xferConfig.srcOffset = 0;
xferConfig.srcAddr = (uint32_t)(&s_dummyData);
}
xferConfig.majorLoopCounts = (xfer->dataSize / xferConfig.minorLoopBytes);
/* Store the initially configured eDMA minor byte transfer count into the FLEXIO SPI handle */
handle->nbytes = xferConfig.minorLoopBytes;
if (handle->txHandle)
{
EDMA_SubmitTransfer(handle->txHandle, &xferConfig);
}
/* Configure tx transfer EDMA. */
if (xfer->rxData)
{
xferConfig.srcAddr = FLEXIO_SPI_GetRxDataRegisterAddress(base, direction);
if (bytesPerFrame == 2U)
{
if (direction == kFLEXIO_SPI_LsbFirst)
{
xferConfig.srcAddr -= 1U;
}
}
xferConfig.srcOffset = 0;
xferConfig.destAddr = (uint32_t)(xfer->rxData);
xferConfig.destOffset = bytesPerFrame;
EDMA_SubmitTransfer(handle->rxHandle, &xferConfig);
handle->rxInProgress = true;
FLEXIO_SPI_EnableDMA(base, kFLEXIO_SPI_RxDmaEnable, true);
EDMA_StartTransfer(handle->rxHandle);
}
/* Always start Tx transfer. */
if (handle->txHandle)
{
handle->txInProgress = true;
FLEXIO_SPI_EnableDMA(base, kFLEXIO_SPI_TxDmaEnable, true);
EDMA_StartTransfer(handle->txHandle);
}
}
status_t FLEXIO_SPI_MasterTransferCreateHandleEDMA(FLEXIO_SPI_Type *base,
flexio_spi_master_edma_handle_t *handle,
flexio_spi_master_edma_transfer_callback_t callback,
void *userData,
edma_handle_t *txHandle,
edma_handle_t *rxHandle)
{
assert(handle);
uint8_t index = 0;
/* Find the an empty handle pointer to store the handle. */
for (index = 0; index < FLEXIO_SPI_HANDLE_COUNT; index++)
{
if (s_edmaPrivateHandle[index].base == NULL)
{
s_edmaPrivateHandle[index].base = base;
s_edmaPrivateHandle[index].handle = handle;
break;
}
}
if (index == FLEXIO_SPI_HANDLE_COUNT)
{
return kStatus_OutOfRange;
}
/* Set spi base to handle. */
handle->txHandle = txHandle;
handle->rxHandle = rxHandle;
/* Register callback and userData. */
handle->callback = callback;
handle->userData = userData;
/* Set SPI state to idle. */
handle->txInProgress = false;
handle->rxInProgress = false;
/* Install callback for Tx/Rx dma channel. */
if (handle->txHandle)
{
EDMA_SetCallback(handle->txHandle, FLEXIO_SPI_TxEDMACallback, &s_edmaPrivateHandle[index]);
}
if (handle->rxHandle)
{
EDMA_SetCallback(handle->rxHandle, FLEXIO_SPI_RxEDMACallback, &s_edmaPrivateHandle[index]);
}
return kStatus_Success;
}
status_t FLEXIO_SPI_MasterTransferEDMA(FLEXIO_SPI_Type *base,
flexio_spi_master_edma_handle_t *handle,
flexio_spi_transfer_t *xfer)
{
assert(handle);
assert(xfer);
uint32_t dataMode = 0;
uint16_t timerCmp = base->flexioBase->TIMCMP[base->timerIndex[0]];
timerCmp &= 0x00FFU;
/* Check if the device is busy. */
if ((handle->txInProgress) || (handle->rxInProgress))
{
return kStatus_FLEXIO_SPI_Busy;
}
/* Check if input parameter invalid. */
if (((xfer->txData == NULL) && (xfer->rxData == NULL)) || (xfer->dataSize == 0U))
{
return kStatus_InvalidArgument;
}
/* configure data mode. */
if ((xfer->flags == kFLEXIO_SPI_8bitMsb) || (xfer->flags == kFLEXIO_SPI_8bitLsb))
{
dataMode = (8 * 2 - 1U) << 8U;
}
else if ((xfer->flags == kFLEXIO_SPI_16bitMsb) || (xfer->flags == kFLEXIO_SPI_16bitLsb))
{
dataMode = (16 * 2 - 1U) << 8U;
}
else
{
dataMode = 8 * 2 - 1U;
}
dataMode |= timerCmp;
base->flexioBase->TIMCMP[base->timerIndex[0]] = dataMode;
FLEXIO_SPI_EDMAConfig(base, handle, xfer);
return kStatus_Success;
}
status_t FLEXIO_SPI_MasterTransferGetCountEDMA(FLEXIO_SPI_Type *base,
flexio_spi_master_edma_handle_t *handle,
size_t *count)
{
assert(handle);
if (!count)
{
return kStatus_InvalidArgument;
}
if (handle->rxInProgress)
{
*count = (handle->transferSize -
(uint32_t)handle->nbytes *
EDMA_GetRemainingMajorLoopCount(handle->rxHandle->base, handle->rxHandle->channel));
}
else
{
*count = (handle->transferSize -
(uint32_t)handle->nbytes *
EDMA_GetRemainingMajorLoopCount(handle->txHandle->base, handle->txHandle->channel));
}
return kStatus_Success;
}
void FLEXIO_SPI_MasterTransferAbortEDMA(FLEXIO_SPI_Type *base, flexio_spi_master_edma_handle_t *handle)
{
assert(handle);
/* Disable dma. */
EDMA_StopTransfer(handle->txHandle);
EDMA_StopTransfer(handle->rxHandle);
/* Disable DMA enable bit. */
FLEXIO_SPI_EnableDMA(base, kFLEXIO_SPI_DmaAllEnable, false);
/* Set the handle state. */
handle->txInProgress = false;
handle->rxInProgress = false;
}
status_t FLEXIO_SPI_SlaveTransferEDMA(FLEXIO_SPI_Type *base,
flexio_spi_slave_edma_handle_t *handle,
flexio_spi_transfer_t *xfer)
{
assert(handle);
assert(xfer);
uint32_t dataMode = 0;
/* Check if the device is busy. */
if ((handle->txInProgress) || (handle->rxInProgress))
{
return kStatus_FLEXIO_SPI_Busy;
}
/* Check if input parameter invalid. */
if (((xfer->txData == NULL) && (xfer->rxData == NULL)) || (xfer->dataSize == 0U))
{
return kStatus_InvalidArgument;
}
/* configure data mode. */
if ((xfer->flags == kFLEXIO_SPI_8bitMsb) || (xfer->flags == kFLEXIO_SPI_8bitLsb))
{
dataMode = 8 * 2 - 1U;
}
else if ((xfer->flags == kFLEXIO_SPI_16bitMsb) || (xfer->flags == kFLEXIO_SPI_16bitLsb))
{
dataMode = 16 * 2 - 1U;
}
else
{
dataMode = 8 * 2 - 1U;
}
base->flexioBase->TIMCMP[base->timerIndex[0]] = dataMode;
FLEXIO_SPI_EDMAConfig(base, handle, xfer);
return kStatus_Success;
}

View File

@ -0,0 +1,200 @@
/*
* Copyright (c) 2015, Freescale Semiconductor, Inc.
* Copyright 2016-2017 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef _FSL_FLEXIO_SPI_EDMA_H_
#define _FSL_FLEXIO_SPI_EDMA_H_
#include "fsl_flexio_spi.h"
#include "fsl_edma.h"
/*!
* @addtogroup flexio_edma_spi
* @{
*/
/*******************************************************************************
* Definitions
******************************************************************************/
/*! @brief typedef for flexio_spi_master_edma_handle_t in advance. */
typedef struct _flexio_spi_master_edma_handle flexio_spi_master_edma_handle_t;
/*! @brief Slave handle is the same with master handle. */
typedef flexio_spi_master_edma_handle_t flexio_spi_slave_edma_handle_t;
/*! @brief FlexIO SPI master callback for finished transmit */
typedef void (*flexio_spi_master_edma_transfer_callback_t)(FLEXIO_SPI_Type *base,
flexio_spi_master_edma_handle_t *handle,
status_t status,
void *userData);
/*! @brief FlexIO SPI slave callback for finished transmit */
typedef void (*flexio_spi_slave_edma_transfer_callback_t)(FLEXIO_SPI_Type *base,
flexio_spi_slave_edma_handle_t *handle,
status_t status,
void *userData);
/*! @brief FlexIO SPI eDMA transfer handle, users should not touch the content of the handle.*/
struct _flexio_spi_master_edma_handle
{
size_t transferSize; /*!< Total bytes to be transferred. */
uint8_t nbytes; /*!< eDMA minor byte transfer count initially configured. */
bool txInProgress; /*!< Send transfer in progress */
bool rxInProgress; /*!< Receive transfer in progress */
edma_handle_t *txHandle; /*!< DMA handler for SPI send */
edma_handle_t *rxHandle; /*!< DMA handler for SPI receive */
flexio_spi_master_edma_transfer_callback_t callback; /*!< Callback for SPI DMA transfer */
void *userData; /*!< User Data for SPI DMA callback */
};
/*******************************************************************************
* APIs
******************************************************************************/
#if defined(__cplusplus)
extern "C" {
#endif
/*!
* @name eDMA Transactional
* @{
*/
/*!
* @brief Initializes the FlexIO SPI master eDMA handle.
*
* This function initializes the FlexIO SPI master eDMA handle which can be used for other FlexIO SPI master transactional
* APIs.
* For a specified FlexIO SPI instance, call this API once to get the initialized handle.
*
* @param base Pointer to FLEXIO_SPI_Type structure.
* @param handle Pointer to flexio_spi_master_edma_handle_t structure to store the transfer state.
* @param callback SPI callback, NULL means no callback.
* @param userData callback function parameter.
* @param txHandle User requested eDMA handle for FlexIO SPI RX eDMA transfer.
* @param rxHandle User requested eDMA handle for FlexIO SPI TX eDMA transfer.
* @retval kStatus_Success Successfully create the handle.
* @retval kStatus_OutOfRange The FlexIO SPI eDMA type/handle table out of range.
*/
status_t FLEXIO_SPI_MasterTransferCreateHandleEDMA(FLEXIO_SPI_Type *base,
flexio_spi_master_edma_handle_t *handle,
flexio_spi_master_edma_transfer_callback_t callback,
void *userData,
edma_handle_t *txHandle,
edma_handle_t *rxHandle);
/*!
* @brief Performs a non-blocking FlexIO SPI transfer using eDMA.
*
* @note This interface returns immediately after transfer initiates. Call
* FLEXIO_SPI_MasterGetTransferCountEDMA to poll the transfer status and check
* whether the FlexIO SPI transfer is finished.
*
* @param base Pointer to FLEXIO_SPI_Type structure.
* @param handle Pointer to flexio_spi_master_edma_handle_t structure to store the transfer state.
* @param xfer Pointer to FlexIO SPI transfer structure.
* @retval kStatus_Success Successfully start a transfer.
* @retval kStatus_InvalidArgument Input argument is invalid.
* @retval kStatus_FLEXIO_SPI_Busy FlexIO SPI is not idle, is running another transfer.
*/
status_t FLEXIO_SPI_MasterTransferEDMA(FLEXIO_SPI_Type *base,
flexio_spi_master_edma_handle_t *handle,
flexio_spi_transfer_t *xfer);
/*!
* @brief Aborts a FlexIO SPI transfer using eDMA.
*
* @param base Pointer to FLEXIO_SPI_Type structure.
* @param handle FlexIO SPI eDMA handle pointer.
*/
void FLEXIO_SPI_MasterTransferAbortEDMA(FLEXIO_SPI_Type *base, flexio_spi_master_edma_handle_t *handle);
/*!
* @brief Gets the remaining bytes for FlexIO SPI eDMA transfer.
*
* @param base Pointer to FLEXIO_SPI_Type structure.
* @param handle FlexIO SPI eDMA handle pointer.
* @param count Number of bytes transferred so far by the non-blocking transaction.
*/
status_t FLEXIO_SPI_MasterTransferGetCountEDMA(FLEXIO_SPI_Type *base,
flexio_spi_master_edma_handle_t *handle,
size_t *count);
/*!
* @brief Initializes the FlexIO SPI slave eDMA handle.
*
* This function initializes the FlexIO SPI slave eDMA handle.
*
* @param base Pointer to FLEXIO_SPI_Type structure.
* @param handle Pointer to flexio_spi_slave_edma_handle_t structure to store the transfer state.
* @param callback SPI callback, NULL means no callback.
* @param userData callback function parameter.
* @param txHandle User requested eDMA handle for FlexIO SPI TX eDMA transfer.
* @param rxHandle User requested eDMA handle for FlexIO SPI RX eDMA transfer.
*/
static inline void FLEXIO_SPI_SlaveTransferCreateHandleEDMA(FLEXIO_SPI_Type *base,
flexio_spi_slave_edma_handle_t *handle,
flexio_spi_slave_edma_transfer_callback_t callback,
void *userData,
edma_handle_t *txHandle,
edma_handle_t *rxHandle)
{
FLEXIO_SPI_MasterTransferCreateHandleEDMA(base, handle, callback, userData, txHandle, rxHandle);
}
/*!
* @brief Performs a non-blocking FlexIO SPI transfer using eDMA.
*
* @note This interface returns immediately after transfer initiates. Call
* FLEXIO_SPI_SlaveGetTransferCountEDMA to poll the transfer status and
* check whether the FlexIO SPI transfer is finished.
*
* @param base Pointer to FLEXIO_SPI_Type structure.
* @param handle Pointer to flexio_spi_slave_edma_handle_t structure to store the transfer state.
* @param xfer Pointer to FlexIO SPI transfer structure.
* @retval kStatus_Success Successfully start a transfer.
* @retval kStatus_InvalidArgument Input argument is invalid.
* @retval kStatus_FLEXIO_SPI_Busy FlexIO SPI is not idle, is running another transfer.
*/
status_t FLEXIO_SPI_SlaveTransferEDMA(FLEXIO_SPI_Type *base,
flexio_spi_slave_edma_handle_t *handle,
flexio_spi_transfer_t *xfer);
/*!
* @brief Aborts a FlexIO SPI transfer using eDMA.
*
* @param base Pointer to FLEXIO_SPI_Type structure.
* @param handle Pointer to flexio_spi_slave_edma_handle_t structure to store the transfer state.
*/
static inline void FLEXIO_SPI_SlaveTransferAbortEDMA(FLEXIO_SPI_Type *base, flexio_spi_slave_edma_handle_t *handle)
{
FLEXIO_SPI_MasterTransferAbortEDMA(base, handle);
}
/*!
* @brief Gets the remaining bytes to be transferred for FlexIO SPI eDMA.
*
* @param base Pointer to FLEXIO_SPI_Type structure.
* @param handle FlexIO SPI eDMA handle pointer.
* @param count Number of bytes transferred so far by the non-blocking transaction.
*/
static inline status_t FLEXIO_SPI_SlaveTransferGetCountEDMA(FLEXIO_SPI_Type *base,
flexio_spi_slave_edma_handle_t *handle,
size_t *count)
{
return FLEXIO_SPI_MasterTransferGetCountEDMA(base, handle, count);
}
/*! @} */
#if defined(__cplusplus)
}
#endif
/*!
* @}
*/
#endif

View File

@ -0,0 +1,700 @@
/*
* Copyright (c) 2015-2016, Freescale Semiconductor, Inc.
* Copyright 2016-2017 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include "fsl_flexio_uart.h"
/*******************************************************************************
* Definitions
******************************************************************************/
/*<! @brief uart transfer state. */
enum _flexio_uart_transfer_states
{
kFLEXIO_UART_TxIdle, /* TX idle. */
kFLEXIO_UART_TxBusy, /* TX busy. */
kFLEXIO_UART_RxIdle, /* RX idle. */
kFLEXIO_UART_RxBusy /* RX busy. */
};
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
extern const clock_ip_name_t s_flexioClocks[];
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
extern FLEXIO_Type *const s_flexioBases[];
/*******************************************************************************
* Prototypes
******************************************************************************/
extern uint32_t FLEXIO_GetInstance(FLEXIO_Type *base);
/*!
* @brief Get the length of received data in RX ring buffer.
*
* @param handle FLEXIO UART handle pointer.
* @return Length of received data in RX ring buffer.
*/
static size_t FLEXIO_UART_TransferGetRxRingBufferLength(flexio_uart_handle_t *handle);
/*!
* @brief Check whether the RX ring buffer is full.
*
* @param handle FLEXIO UART handle pointer.
* @retval true RX ring buffer is full.
* @retval false RX ring buffer is not full.
*/
static bool FLEXIO_UART_TransferIsRxRingBufferFull(flexio_uart_handle_t *handle);
/*******************************************************************************
* Codes
******************************************************************************/
uint32_t FLEXIO_UART_GetInstance(FLEXIO_UART_Type *base)
{
return FLEXIO_GetInstance(base->flexioBase);
}
static size_t FLEXIO_UART_TransferGetRxRingBufferLength(flexio_uart_handle_t *handle)
{
size_t size;
if (handle->rxRingBufferTail > handle->rxRingBufferHead)
{
size = (size_t)(handle->rxRingBufferHead + handle->rxRingBufferSize - handle->rxRingBufferTail);
}
else
{
size = (size_t)(handle->rxRingBufferHead - handle->rxRingBufferTail);
}
return size;
}
static bool FLEXIO_UART_TransferIsRxRingBufferFull(flexio_uart_handle_t *handle)
{
bool full;
if (FLEXIO_UART_TransferGetRxRingBufferLength(handle) == (handle->rxRingBufferSize - 1U))
{
full = true;
}
else
{
full = false;
}
return full;
}
status_t FLEXIO_UART_Init(FLEXIO_UART_Type *base, const flexio_uart_config_t *userConfig, uint32_t srcClock_Hz)
{
assert(base && userConfig);
flexio_shifter_config_t shifterConfig;
flexio_timer_config_t timerConfig;
uint32_t ctrlReg = 0;
uint16_t timerDiv = 0;
uint16_t timerCmp = 0;
status_t result = kStatus_Success;
/* Clear the shifterConfig & timerConfig struct. */
memset(&shifterConfig, 0, sizeof(shifterConfig));
memset(&timerConfig, 0, sizeof(timerConfig));
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
/* Ungate flexio clock. */
CLOCK_EnableClock(s_flexioClocks[FLEXIO_UART_GetInstance(base)]);
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
/* Reset FLEXIO before configuration. */
FLEXIO_Reset(base->flexioBase);
/* Configure FLEXIO UART */
ctrlReg = base->flexioBase->CTRL;
ctrlReg &= ~(FLEXIO_CTRL_DOZEN_MASK | FLEXIO_CTRL_DBGE_MASK | FLEXIO_CTRL_FASTACC_MASK | FLEXIO_CTRL_FLEXEN_MASK);
ctrlReg |= (FLEXIO_CTRL_DBGE(userConfig->enableInDebug) | FLEXIO_CTRL_FASTACC(userConfig->enableFastAccess) |
FLEXIO_CTRL_FLEXEN(userConfig->enableUart));
if (!userConfig->enableInDoze)
{
ctrlReg |= FLEXIO_CTRL_DOZEN_MASK;
}
base->flexioBase->CTRL = ctrlReg;
/* Do hardware configuration. */
/* 1. Configure the shifter 0 for tx. */
shifterConfig.timerSelect = base->timerIndex[0];
shifterConfig.timerPolarity = kFLEXIO_ShifterTimerPolarityOnPositive;
shifterConfig.pinConfig = kFLEXIO_PinConfigOutput;
shifterConfig.pinSelect = base->TxPinIndex;
shifterConfig.pinPolarity = kFLEXIO_PinActiveHigh;
shifterConfig.shifterMode = kFLEXIO_ShifterModeTransmit;
shifterConfig.inputSource = kFLEXIO_ShifterInputFromPin;
shifterConfig.shifterStop = kFLEXIO_ShifterStopBitHigh;
shifterConfig.shifterStart = kFLEXIO_ShifterStartBitLow;
FLEXIO_SetShifterConfig(base->flexioBase, base->shifterIndex[0], &shifterConfig);
/*2. Configure the timer 0 for tx. */
timerConfig.triggerSelect = FLEXIO_TIMER_TRIGGER_SEL_SHIFTnSTAT(base->shifterIndex[0]);
timerConfig.triggerPolarity = kFLEXIO_TimerTriggerPolarityActiveLow;
timerConfig.triggerSource = kFLEXIO_TimerTriggerSourceInternal;
timerConfig.pinConfig = kFLEXIO_PinConfigOutputDisabled;
timerConfig.pinSelect = base->TxPinIndex;
timerConfig.pinPolarity = kFLEXIO_PinActiveHigh;
timerConfig.timerMode = kFLEXIO_TimerModeDual8BitBaudBit;
timerConfig.timerOutput = kFLEXIO_TimerOutputOneNotAffectedByReset;
timerConfig.timerDecrement = kFLEXIO_TimerDecSrcOnFlexIOClockShiftTimerOutput;
timerConfig.timerReset = kFLEXIO_TimerResetNever;
timerConfig.timerDisable = kFLEXIO_TimerDisableOnTimerCompare;
timerConfig.timerEnable = kFLEXIO_TimerEnableOnTriggerHigh;
timerConfig.timerStop = kFLEXIO_TimerStopBitEnableOnTimerDisable;
timerConfig.timerStart = kFLEXIO_TimerStartBitEnabled;
timerDiv = srcClock_Hz / userConfig->baudRate_Bps;
timerDiv = timerDiv / 2 - 1;
if (timerDiv > 0xFFU)
{
result = kStatus_InvalidArgument;
}
timerCmp = ((uint32_t)(userConfig->bitCountPerChar * 2 - 1)) << 8U;
timerCmp |= timerDiv;
timerConfig.timerCompare = timerCmp;
FLEXIO_SetTimerConfig(base->flexioBase, base->timerIndex[0], &timerConfig);
/* 3. Configure the shifter 1 for rx. */
shifterConfig.timerSelect = base->timerIndex[1];
shifterConfig.timerPolarity = kFLEXIO_ShifterTimerPolarityOnNegitive;
shifterConfig.pinConfig = kFLEXIO_PinConfigOutputDisabled;
shifterConfig.pinSelect = base->RxPinIndex;
shifterConfig.pinPolarity = kFLEXIO_PinActiveHigh;
shifterConfig.shifterMode = kFLEXIO_ShifterModeReceive;
shifterConfig.inputSource = kFLEXIO_ShifterInputFromPin;
shifterConfig.shifterStop = kFLEXIO_ShifterStopBitHigh;
shifterConfig.shifterStart = kFLEXIO_ShifterStartBitLow;
FLEXIO_SetShifterConfig(base->flexioBase, base->shifterIndex[1], &shifterConfig);
/* 4. Configure the timer 1 for rx. */
timerConfig.triggerSelect = FLEXIO_TIMER_TRIGGER_SEL_PININPUT(base->RxPinIndex);
timerConfig.triggerPolarity = kFLEXIO_TimerTriggerPolarityActiveHigh;
timerConfig.triggerSource = kFLEXIO_TimerTriggerSourceExternal;
timerConfig.pinConfig = kFLEXIO_PinConfigOutputDisabled;
timerConfig.pinSelect = base->RxPinIndex;
timerConfig.pinPolarity = kFLEXIO_PinActiveLow;
timerConfig.timerMode = kFLEXIO_TimerModeDual8BitBaudBit;
timerConfig.timerOutput = kFLEXIO_TimerOutputOneAffectedByReset;
timerConfig.timerDecrement = kFLEXIO_TimerDecSrcOnFlexIOClockShiftTimerOutput;
timerConfig.timerReset = kFLEXIO_TimerResetOnTimerPinRisingEdge;
timerConfig.timerDisable = kFLEXIO_TimerDisableOnTimerCompare;
timerConfig.timerEnable = kFLEXIO_TimerEnableOnPinRisingEdge;
timerConfig.timerStop = kFLEXIO_TimerStopBitEnableOnTimerDisable;
timerConfig.timerStart = kFLEXIO_TimerStartBitEnabled;
timerConfig.timerCompare = timerCmp;
FLEXIO_SetTimerConfig(base->flexioBase, base->timerIndex[1], &timerConfig);
return result;
}
void FLEXIO_UART_Deinit(FLEXIO_UART_Type *base)
{
/* Disable FLEXIO UART module. */
FLEXIO_UART_Enable(base, false);
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
/* Gate flexio clock. */
CLOCK_DisableClock(kCLOCK_Flexio0);
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
}
void FLEXIO_UART_GetDefaultConfig(flexio_uart_config_t *userConfig)
{
assert(userConfig);
userConfig->enableUart = true;
userConfig->enableInDoze = false;
userConfig->enableInDebug = true;
userConfig->enableFastAccess = false;
/* Default baud rate 115200. */
userConfig->baudRate_Bps = 115200U;
/* Default bit count at 8. */
userConfig->bitCountPerChar = kFLEXIO_UART_8BitsPerChar;
}
void FLEXIO_UART_EnableInterrupts(FLEXIO_UART_Type *base, uint32_t mask)
{
if (mask & kFLEXIO_UART_TxDataRegEmptyInterruptEnable)
{
FLEXIO_EnableShifterStatusInterrupts(base->flexioBase, 1U << base->shifterIndex[0]);
}
if (mask & kFLEXIO_UART_RxDataRegFullInterruptEnable)
{
FLEXIO_EnableShifterStatusInterrupts(base->flexioBase, 1U << base->shifterIndex[1]);
}
}
void FLEXIO_UART_DisableInterrupts(FLEXIO_UART_Type *base, uint32_t mask)
{
if (mask & kFLEXIO_UART_TxDataRegEmptyInterruptEnable)
{
FLEXIO_DisableShifterStatusInterrupts(base->flexioBase, 1U << base->shifterIndex[0]);
}
if (mask & kFLEXIO_UART_RxDataRegFullInterruptEnable)
{
FLEXIO_DisableShifterStatusInterrupts(base->flexioBase, 1U << base->shifterIndex[1]);
}
}
uint32_t FLEXIO_UART_GetStatusFlags(FLEXIO_UART_Type *base)
{
uint32_t status = 0;
status =
((FLEXIO_GetShifterStatusFlags(base->flexioBase) & (1U << base->shifterIndex[0])) >> base->shifterIndex[0]);
status |=
(((FLEXIO_GetShifterStatusFlags(base->flexioBase) & (1U << base->shifterIndex[1])) >> (base->shifterIndex[1]))
<< 1U);
status |=
(((FLEXIO_GetShifterErrorFlags(base->flexioBase) & (1U << base->shifterIndex[1])) >> (base->shifterIndex[1]))
<< 2U);
return status;
}
void FLEXIO_UART_ClearStatusFlags(FLEXIO_UART_Type *base, uint32_t mask)
{
if (mask & kFLEXIO_UART_TxDataRegEmptyFlag)
{
FLEXIO_ClearShifterStatusFlags(base->flexioBase, 1U << base->shifterIndex[0]);
}
if (mask & kFLEXIO_UART_RxDataRegFullFlag)
{
FLEXIO_ClearShifterStatusFlags(base->flexioBase, 1U << base->shifterIndex[1]);
}
if (mask & kFLEXIO_UART_RxOverRunFlag)
{
FLEXIO_ClearShifterErrorFlags(base->flexioBase, 1U << base->shifterIndex[1]);
}
}
void FLEXIO_UART_WriteBlocking(FLEXIO_UART_Type *base, const uint8_t *txData, size_t txSize)
{
assert(txData);
assert(txSize);
while (txSize--)
{
/* Wait until data transfer complete. */
while (!(FLEXIO_GetShifterStatusFlags(base->flexioBase) & (1U << base->shifterIndex[0])))
{
}
base->flexioBase->SHIFTBUF[base->shifterIndex[0]] = *txData++;
}
}
void FLEXIO_UART_ReadBlocking(FLEXIO_UART_Type *base, uint8_t *rxData, size_t rxSize)
{
assert(rxData);
assert(rxSize);
while (rxSize--)
{
/* Wait until data transfer complete. */
while (!(FLEXIO_UART_GetStatusFlags(base) & kFLEXIO_UART_RxDataRegFullFlag))
{
}
*rxData++ = base->flexioBase->SHIFTBUFBYS[base->shifterIndex[1]];
}
}
status_t FLEXIO_UART_TransferCreateHandle(FLEXIO_UART_Type *base,
flexio_uart_handle_t *handle,
flexio_uart_transfer_callback_t callback,
void *userData)
{
assert(handle);
IRQn_Type flexio_irqs[] = FLEXIO_IRQS;
/* Zero the handle. */
memset(handle, 0, sizeof(*handle));
/* Set the TX/RX state. */
handle->rxState = kFLEXIO_UART_RxIdle;
handle->txState = kFLEXIO_UART_TxIdle;
/* Set the callback and user data. */
handle->callback = callback;
handle->userData = userData;
/* Enable interrupt in NVIC. */
EnableIRQ(flexio_irqs[FLEXIO_UART_GetInstance(base)]);
/* Save the context in global variables to support the double weak mechanism. */
return FLEXIO_RegisterHandleIRQ(base, handle, FLEXIO_UART_TransferHandleIRQ);
}
void FLEXIO_UART_TransferStartRingBuffer(FLEXIO_UART_Type *base,
flexio_uart_handle_t *handle,
uint8_t *ringBuffer,
size_t ringBufferSize)
{
assert(handle);
/* Setup the ringbuffer address */
if (ringBuffer)
{
handle->rxRingBuffer = ringBuffer;
handle->rxRingBufferSize = ringBufferSize;
handle->rxRingBufferHead = 0U;
handle->rxRingBufferTail = 0U;
/* Enable the interrupt to accept the data when user need the ring buffer. */
FLEXIO_UART_EnableInterrupts(base, kFLEXIO_UART_RxDataRegFullInterruptEnable);
}
}
void FLEXIO_UART_TransferStopRingBuffer(FLEXIO_UART_Type *base, flexio_uart_handle_t *handle)
{
assert(handle);
if (handle->rxState == kFLEXIO_UART_RxIdle)
{
FLEXIO_UART_DisableInterrupts(base, kFLEXIO_UART_RxDataRegFullInterruptEnable);
}
handle->rxRingBuffer = NULL;
handle->rxRingBufferSize = 0U;
handle->rxRingBufferHead = 0U;
handle->rxRingBufferTail = 0U;
}
status_t FLEXIO_UART_TransferSendNonBlocking(FLEXIO_UART_Type *base,
flexio_uart_handle_t *handle,
flexio_uart_transfer_t *xfer)
{
status_t status;
/* Return error if xfer invalid. */
if ((0U == xfer->dataSize) || (NULL == xfer->data))
{
return kStatus_InvalidArgument;
}
/* Return error if current TX busy. */
if (kFLEXIO_UART_TxBusy == handle->txState)
{
status = kStatus_FLEXIO_UART_TxBusy;
}
else
{
handle->txData = xfer->data;
handle->txDataSize = xfer->dataSize;
handle->txDataSizeAll = xfer->dataSize;
handle->txState = kFLEXIO_UART_TxBusy;
/* Enable transmiter interrupt. */
FLEXIO_UART_EnableInterrupts(base, kFLEXIO_UART_TxDataRegEmptyInterruptEnable);
status = kStatus_Success;
}
return status;
}
void FLEXIO_UART_TransferAbortSend(FLEXIO_UART_Type *base, flexio_uart_handle_t *handle)
{
/* Disable the transmitter and disable the interrupt. */
FLEXIO_UART_DisableInterrupts(base, kFLEXIO_UART_TxDataRegEmptyInterruptEnable);
handle->txDataSize = 0;
handle->txState = kFLEXIO_UART_TxIdle;
}
status_t FLEXIO_UART_TransferGetSendCount(FLEXIO_UART_Type *base, flexio_uart_handle_t *handle, size_t *count)
{
assert(handle);
assert(count);
if (kFLEXIO_UART_TxIdle == handle->txState)
{
return kStatus_NoTransferInProgress;
}
*count = handle->txDataSizeAll - handle->txDataSize;
return kStatus_Success;
}
status_t FLEXIO_UART_TransferReceiveNonBlocking(FLEXIO_UART_Type *base,
flexio_uart_handle_t *handle,
flexio_uart_transfer_t *xfer,
size_t *receivedBytes)
{
uint32_t i;
status_t status;
/* How many bytes to copy from ring buffer to user memory. */
size_t bytesToCopy = 0U;
/* How many bytes to receive. */
size_t bytesToReceive;
/* How many bytes currently have received. */
size_t bytesCurrentReceived;
/* Return error if xfer invalid. */
if ((0U == xfer->dataSize) || (NULL == xfer->data))
{
return kStatus_InvalidArgument;
}
/* How to get data:
1. If RX ring buffer is not enabled, then save xfer->data and xfer->dataSize
to uart handle, enable interrupt to store received data to xfer->data. When
all data received, trigger callback.
2. If RX ring buffer is enabled and not empty, get data from ring buffer first.
If there are enough data in ring buffer, copy them to xfer->data and return.
If there are not enough data in ring buffer, copy all of them to xfer->data,
save the xfer->data remained empty space to uart handle, receive data
to this empty space and trigger callback when finished. */
if (kFLEXIO_UART_RxBusy == handle->rxState)
{
status = kStatus_FLEXIO_UART_RxBusy;
}
else
{
bytesToReceive = xfer->dataSize;
bytesCurrentReceived = 0U;
/* If RX ring buffer is used. */
if (handle->rxRingBuffer)
{
/* Disable FLEXIO_UART RX IRQ, protect ring buffer. */
FLEXIO_UART_DisableInterrupts(base, kFLEXIO_UART_RxDataRegFullInterruptEnable);
/* How many bytes in RX ring buffer currently. */
bytesToCopy = FLEXIO_UART_TransferGetRxRingBufferLength(handle);
if (bytesToCopy)
{
bytesToCopy = MIN(bytesToReceive, bytesToCopy);
bytesToReceive -= bytesToCopy;
/* Copy data from ring buffer to user memory. */
for (i = 0U; i < bytesToCopy; i++)
{
xfer->data[bytesCurrentReceived++] = handle->rxRingBuffer[handle->rxRingBufferTail];
/* Wrap to 0. Not use modulo (%) because it might be large and slow. */
if (handle->rxRingBufferTail + 1U == handle->rxRingBufferSize)
{
handle->rxRingBufferTail = 0U;
}
else
{
handle->rxRingBufferTail++;
}
}
}
/* If ring buffer does not have enough data, still need to read more data. */
if (bytesToReceive)
{
/* No data in ring buffer, save the request to UART handle. */
handle->rxData = xfer->data + bytesCurrentReceived;
handle->rxDataSize = bytesToReceive;
handle->rxDataSizeAll = bytesToReceive;
handle->rxState = kFLEXIO_UART_RxBusy;
}
/* Enable FLEXIO_UART RX IRQ if previously enabled. */
FLEXIO_UART_EnableInterrupts(base, kFLEXIO_UART_RxDataRegFullInterruptEnable);
}
/* Ring buffer not used. */
else
{
handle->rxData = xfer->data + bytesCurrentReceived;
handle->rxDataSize = bytesToReceive;
handle->rxDataSizeAll = bytesToReceive;
handle->rxState = kFLEXIO_UART_RxBusy;
/* Enable RX interrupt. */
FLEXIO_UART_EnableInterrupts(base, kFLEXIO_UART_RxDataRegFullInterruptEnable);
}
/* Return the how many bytes have read. */
if (receivedBytes)
{
*receivedBytes = bytesCurrentReceived;
}
status = kStatus_Success;
}
return status;
}
void FLEXIO_UART_TransferAbortReceive(FLEXIO_UART_Type *base, flexio_uart_handle_t *handle)
{
/* Only abort the receive to handle->rxData, the RX ring buffer is still working. */
if (!handle->rxRingBuffer)
{
/* Disable RX interrupt. */
FLEXIO_UART_DisableInterrupts(base, kFLEXIO_UART_RxDataRegFullInterruptEnable);
}
handle->rxDataSize = 0U;
handle->rxState = kFLEXIO_UART_RxIdle;
}
status_t FLEXIO_UART_TransferGetReceiveCount(FLEXIO_UART_Type *base, flexio_uart_handle_t *handle, size_t *count)
{
assert(handle);
assert(count);
if (kFLEXIO_UART_RxIdle == handle->rxState)
{
return kStatus_NoTransferInProgress;
}
*count = handle->rxDataSizeAll - handle->rxDataSize;
return kStatus_Success;
}
void FLEXIO_UART_TransferHandleIRQ(void *uartType, void *uartHandle)
{
uint8_t count = 1;
FLEXIO_UART_Type *base = (FLEXIO_UART_Type *)uartType;
flexio_uart_handle_t *handle = (flexio_uart_handle_t *)uartHandle;
/* Read the status back. */
uint8_t status = FLEXIO_UART_GetStatusFlags(base);
/* If RX overrun. */
if (kFLEXIO_UART_RxOverRunFlag & status)
{
/* Clear Overrun flag. */
FLEXIO_UART_ClearStatusFlags(base, kFLEXIO_UART_RxOverRunFlag);
/* Trigger callback. */
if (handle->callback)
{
handle->callback(base, handle, kStatus_FLEXIO_UART_RxHardwareOverrun, handle->userData);
}
}
/* Receive data register full */
if ((kFLEXIO_UART_RxDataRegFullFlag & status) && (base->flexioBase->SHIFTSIEN & (1U << base->shifterIndex[1])))
{
/* If handle->rxDataSize is not 0, first save data to handle->rxData. */
if (handle->rxDataSize)
{
/* Using non block API to read the data from the registers. */
FLEXIO_UART_ReadByte(base, handle->rxData);
handle->rxDataSize--;
handle->rxData++;
count--;
/* If all the data required for upper layer is ready, trigger callback. */
if (!handle->rxDataSize)
{
handle->rxState = kFLEXIO_UART_RxIdle;
if (handle->callback)
{
handle->callback(base, handle, kStatus_FLEXIO_UART_RxIdle, handle->userData);
}
}
}
if (handle->rxRingBuffer)
{
if (count)
{
/* If RX ring buffer is full, trigger callback to notify over run. */
if (FLEXIO_UART_TransferIsRxRingBufferFull(handle))
{
if (handle->callback)
{
handle->callback(base, handle, kStatus_FLEXIO_UART_RxRingBufferOverrun, handle->userData);
}
}
/* If ring buffer is still full after callback function, the oldest data is overrided. */
if (FLEXIO_UART_TransferIsRxRingBufferFull(handle))
{
/* Increase handle->rxRingBufferTail to make room for new data. */
if (handle->rxRingBufferTail + 1U == handle->rxRingBufferSize)
{
handle->rxRingBufferTail = 0U;
}
else
{
handle->rxRingBufferTail++;
}
}
/* Read data. */
handle->rxRingBuffer[handle->rxRingBufferHead] = base->flexioBase->SHIFTBUFBYS[base->shifterIndex[1]];
/* Increase handle->rxRingBufferHead. */
if (handle->rxRingBufferHead + 1U == handle->rxRingBufferSize)
{
handle->rxRingBufferHead = 0U;
}
else
{
handle->rxRingBufferHead++;
}
}
}
/* If no receive requst pending, stop RX interrupt. */
else if (!handle->rxDataSize)
{
FLEXIO_UART_DisableInterrupts(base, kFLEXIO_UART_RxDataRegFullInterruptEnable);
}
else
{
}
}
/* Send data register empty and the interrupt is enabled. */
if ((kFLEXIO_UART_TxDataRegEmptyFlag & status) && (base->flexioBase->SHIFTSIEN & (1U << base->shifterIndex[0])))
{
if (handle->txDataSize)
{
/* Using non block API to write the data to the registers. */
FLEXIO_UART_WriteByte(base, handle->txData);
handle->txData++;
handle->txDataSize--;
count--;
/* If all the data are written to data register, TX finished. */
if (!handle->txDataSize)
{
handle->txState = kFLEXIO_UART_TxIdle;
/* Disable TX register empty interrupt. */
FLEXIO_UART_DisableInterrupts(base, kFLEXIO_UART_TxDataRegEmptyInterruptEnable);
/* Trigger callback. */
if (handle->callback)
{
handle->callback(base, handle, kStatus_FLEXIO_UART_TxIdle, handle->userData);
}
}
}
}
}

View File

@ -0,0 +1,564 @@
/*
* Copyright (c) 2015-2016, Freescale Semiconductor, Inc.
* Copyright 2016-2017 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef _FSL_FLEXIO_UART_H_
#define _FSL_FLEXIO_UART_H_
#include "fsl_common.h"
#include "fsl_flexio.h"
/*!
* @addtogroup flexio_uart
* @{
*/
/*******************************************************************************
* Definitions
******************************************************************************/
/*! @name Driver version */
/*@{*/
/*! @brief FlexIO UART driver version 2.1.2. */
#define FSL_FLEXIO_UART_DRIVER_VERSION (MAKE_VERSION(2, 1, 2))
/*@}*/
/*! @brief Error codes for the UART driver. */
enum _flexio_uart_status
{
kStatus_FLEXIO_UART_TxBusy = MAKE_STATUS(kStatusGroup_FLEXIO_UART, 0), /*!< Transmitter is busy. */
kStatus_FLEXIO_UART_RxBusy = MAKE_STATUS(kStatusGroup_FLEXIO_UART, 1), /*!< Receiver is busy. */
kStatus_FLEXIO_UART_TxIdle = MAKE_STATUS(kStatusGroup_FLEXIO_UART, 2), /*!< UART transmitter is idle. */
kStatus_FLEXIO_UART_RxIdle = MAKE_STATUS(kStatusGroup_FLEXIO_UART, 3), /*!< UART receiver is idle. */
kStatus_FLEXIO_UART_ERROR = MAKE_STATUS(kStatusGroup_FLEXIO_UART, 4), /*!< ERROR happens on UART. */
kStatus_FLEXIO_UART_RxRingBufferOverrun =
MAKE_STATUS(kStatusGroup_FLEXIO_UART, 5), /*!< UART RX software ring buffer overrun. */
kStatus_FLEXIO_UART_RxHardwareOverrun = MAKE_STATUS(kStatusGroup_FLEXIO_UART, 6) /*!< UART RX receiver overrun. */
};
/*! @brief FlexIO UART bit count per char. */
typedef enum _flexio_uart_bit_count_per_char
{
kFLEXIO_UART_7BitsPerChar = 7U, /*!< 7-bit data characters */
kFLEXIO_UART_8BitsPerChar = 8U, /*!< 8-bit data characters */
kFLEXIO_UART_9BitsPerChar = 9U, /*!< 9-bit data characters */
} flexio_uart_bit_count_per_char_t;
/*! @brief Define FlexIO UART interrupt mask. */
enum _flexio_uart_interrupt_enable
{
kFLEXIO_UART_TxDataRegEmptyInterruptEnable = 0x1U, /*!< Transmit buffer empty interrupt enable. */
kFLEXIO_UART_RxDataRegFullInterruptEnable = 0x2U, /*!< Receive buffer full interrupt enable. */
};
/*! @brief Define FlexIO UART status mask. */
enum _flexio_uart_status_flags
{
kFLEXIO_UART_TxDataRegEmptyFlag = 0x1U, /*!< Transmit buffer empty flag. */
kFLEXIO_UART_RxDataRegFullFlag = 0x2U, /*!< Receive buffer full flag. */
kFLEXIO_UART_RxOverRunFlag = 0x4U, /*!< Receive buffer over run flag. */
};
/*! @brief Define FlexIO UART access structure typedef. */
typedef struct _flexio_uart_type
{
FLEXIO_Type *flexioBase; /*!< FlexIO base pointer. */
uint8_t TxPinIndex; /*!< Pin select for UART_Tx. */
uint8_t RxPinIndex; /*!< Pin select for UART_Rx. */
uint8_t shifterIndex[2]; /*!< Shifter index used in FlexIO UART. */
uint8_t timerIndex[2]; /*!< Timer index used in FlexIO UART. */
} FLEXIO_UART_Type;
/*! @brief Define FlexIO UART user configuration structure. */
typedef struct _flexio_uart_config
{
bool enableUart; /*!< Enable/disable FlexIO UART TX & RX. */
bool enableInDoze; /*!< Enable/disable FlexIO operation in doze mode*/
bool enableInDebug; /*!< Enable/disable FlexIO operation in debug mode*/
bool enableFastAccess; /*!< Enable/disable fast access to FlexIO registers,
fast access requires the FlexIO clock to be at least
twice the frequency of the bus clock. */
uint32_t baudRate_Bps; /*!< Baud rate in Bps. */
flexio_uart_bit_count_per_char_t bitCountPerChar; /*!< number of bits, 7/8/9 -bit */
} flexio_uart_config_t;
/*! @brief Define FlexIO UART transfer structure. */
typedef struct _flexio_uart_transfer
{
uint8_t *data; /*!< Transfer buffer*/
size_t dataSize; /*!< Transfer size*/
} flexio_uart_transfer_t;
/* Forward declaration of the handle typedef. */
typedef struct _flexio_uart_handle flexio_uart_handle_t;
/*! @brief FlexIO UART transfer callback function. */
typedef void (*flexio_uart_transfer_callback_t)(FLEXIO_UART_Type *base,
flexio_uart_handle_t *handle,
status_t status,
void *userData);
/*! @brief Define FLEXIO UART handle structure*/
struct _flexio_uart_handle
{
uint8_t *volatile txData; /*!< Address of remaining data to send. */
volatile size_t txDataSize; /*!< Size of the remaining data to send. */
uint8_t *volatile rxData; /*!< Address of remaining data to receive. */
volatile size_t rxDataSize; /*!< Size of the remaining data to receive. */
size_t txDataSizeAll; /*!< Total bytes to be sent. */
size_t rxDataSizeAll; /*!< Total bytes to be received. */
uint8_t *rxRingBuffer; /*!< Start address of the receiver ring buffer. */
size_t rxRingBufferSize; /*!< Size of the ring buffer. */
volatile uint16_t rxRingBufferHead; /*!< Index for the driver to store received data into ring buffer. */
volatile uint16_t rxRingBufferTail; /*!< Index for the user to get data from the ring buffer. */
flexio_uart_transfer_callback_t callback; /*!< Callback function. */
void *userData; /*!< UART callback function parameter.*/
volatile uint8_t txState; /*!< TX transfer state. */
volatile uint8_t rxState; /*!< RX transfer state */
};
/*******************************************************************************
* API
******************************************************************************/
#if defined(__cplusplus)
extern "C" {
#endif /*_cplusplus*/
/*!
* @name Initialization and deinitialization
* @{
*/
/*!
* @brief Ungates the FlexIO clock, resets the FlexIO module, configures FlexIO UART
* hardware, and configures the FlexIO UART with FlexIO UART configuration.
* The configuration structure can be filled by the user or be set with
* default values by FLEXIO_UART_GetDefaultConfig().
*
* Example
@code
FLEXIO_UART_Type base = {
.flexioBase = FLEXIO,
.TxPinIndex = 0,
.RxPinIndex = 1,
.shifterIndex = {0,1},
.timerIndex = {0,1}
};
flexio_uart_config_t config = {
.enableInDoze = false,
.enableInDebug = true,
.enableFastAccess = false,
.baudRate_Bps = 115200U,
.bitCountPerChar = 8
};
FLEXIO_UART_Init(base, &config, srcClock_Hz);
@endcode
*
* @param base Pointer to the FLEXIO_UART_Type structure.
* @param userConfig Pointer to the flexio_uart_config_t structure.
* @param srcClock_Hz FlexIO source clock in Hz.
* @retval kStatus_Success Configuration success
* @retval kStatus_InvalidArgument Buadrate configuration out of range
*/
status_t FLEXIO_UART_Init(FLEXIO_UART_Type *base, const flexio_uart_config_t *userConfig, uint32_t srcClock_Hz);
/*!
* @brief Disables the FlexIO UART and gates the FlexIO clock.
*
* @note After calling this API, call the FLEXO_UART_Init to use the FlexIO UART module.
*
* @param base Pointer to FLEXIO_UART_Type structure
*/
void FLEXIO_UART_Deinit(FLEXIO_UART_Type *base);
/*!
* @brief Gets the default configuration to configure the FlexIO UART. The configuration
* can be used directly for calling the FLEXIO_UART_Init().
* Example:
@code
flexio_uart_config_t config;
FLEXIO_UART_GetDefaultConfig(&userConfig);
@endcode
* @param userConfig Pointer to the flexio_uart_config_t structure.
*/
void FLEXIO_UART_GetDefaultConfig(flexio_uart_config_t *userConfig);
/* @} */
/*!
* @name Status
* @{
*/
/*!
* @brief Gets the FlexIO UART status flags.
*
* @param base Pointer to the FLEXIO_UART_Type structure.
* @return FlexIO UART status flags.
*/
uint32_t FLEXIO_UART_GetStatusFlags(FLEXIO_UART_Type *base);
/*!
* @brief Gets the FlexIO UART status flags.
*
* @param base Pointer to the FLEXIO_UART_Type structure.
* @param mask Status flag.
* The parameter can be any combination of the following values:
* @arg kFLEXIO_UART_TxDataRegEmptyFlag
* @arg kFLEXIO_UART_RxEmptyFlag
* @arg kFLEXIO_UART_RxOverRunFlag
*/
void FLEXIO_UART_ClearStatusFlags(FLEXIO_UART_Type *base, uint32_t mask);
/* @} */
/*!
* @name Interrupts
* @{
*/
/*!
* @brief Enables the FlexIO UART interrupt.
*
* This function enables the FlexIO UART interrupt.
*
* @param base Pointer to the FLEXIO_UART_Type structure.
* @param mask Interrupt source.
*/
void FLEXIO_UART_EnableInterrupts(FLEXIO_UART_Type *base, uint32_t mask);
/*!
* @brief Disables the FlexIO UART interrupt.
*
* This function disables the FlexIO UART interrupt.
*
* @param base Pointer to the FLEXIO_UART_Type structure.
* @param mask Interrupt source.
*/
void FLEXIO_UART_DisableInterrupts(FLEXIO_UART_Type *base, uint32_t mask);
/* @} */
/*!
* @name DMA Control
* @{
*/
/*!
* @brief Gets the FlexIO UARt transmit data register address.
*
* This function returns the UART data register address, which is mainly used by DMA/eDMA.
*
* @param base Pointer to the FLEXIO_UART_Type structure.
* @return FlexIO UART transmit data register address.
*/
static inline uint32_t FLEXIO_UART_GetTxDataRegisterAddress(FLEXIO_UART_Type *base)
{
return FLEXIO_GetShifterBufferAddress(base->flexioBase, kFLEXIO_ShifterBuffer, base->shifterIndex[0]);
}
/*!
* @brief Gets the FlexIO UART receive data register address.
*
* This function returns the UART data register address, which is mainly used by DMA/eDMA.
*
* @param base Pointer to the FLEXIO_UART_Type structure.
* @return FlexIO UART receive data register address.
*/
static inline uint32_t FLEXIO_UART_GetRxDataRegisterAddress(FLEXIO_UART_Type *base)
{
return FLEXIO_GetShifterBufferAddress(base->flexioBase, kFLEXIO_ShifterBufferByteSwapped, base->shifterIndex[1]);
}
/*!
* @brief Enables/disables the FlexIO UART transmit DMA.
* This function enables/disables the FlexIO UART Tx DMA,
* which means asserting the kFLEXIO_UART_TxDataRegEmptyFlag does/doesn't trigger the DMA request.
*
* @param base Pointer to the FLEXIO_UART_Type structure.
* @param enable True to enable, false to disable.
*/
static inline void FLEXIO_UART_EnableTxDMA(FLEXIO_UART_Type *base, bool enable)
{
FLEXIO_EnableShifterStatusDMA(base->flexioBase, 1 << base->shifterIndex[0], enable);
}
/*!
* @brief Enables/disables the FlexIO UART receive DMA.
* This function enables/disables the FlexIO UART Rx DMA,
* which means asserting kFLEXIO_UART_RxDataRegFullFlag does/doesn't trigger the DMA request.
*
* @param base Pointer to the FLEXIO_UART_Type structure.
* @param enable True to enable, false to disable.
*/
static inline void FLEXIO_UART_EnableRxDMA(FLEXIO_UART_Type *base, bool enable)
{
FLEXIO_EnableShifterStatusDMA(base->flexioBase, 1 << base->shifterIndex[1], enable);
}
/* @} */
/*!
* @name Bus Operations
* @{
*/
/*!
* @brief Enables/disables the FlexIO UART module operation.
*
* @param base Pointer to the FLEXIO_UART_Type.
* @param enable True to enable, false to disable.
*/
static inline void FLEXIO_UART_Enable(FLEXIO_UART_Type *base, bool enable)
{
if (enable)
{
base->flexioBase->CTRL |= FLEXIO_CTRL_FLEXEN_MASK;
}
else
{
base->flexioBase->CTRL &= ~FLEXIO_CTRL_FLEXEN_MASK;
}
}
/*!
* @brief Writes one byte of data.
*
* @note This is a non-blocking API, which returns directly after the data is put into the
* data register. Ensure that the TxEmptyFlag is asserted before calling
* this API.
*
* @param base Pointer to the FLEXIO_UART_Type structure.
* @param buffer The data bytes to send.
*/
static inline void FLEXIO_UART_WriteByte(FLEXIO_UART_Type *base, const uint8_t *buffer)
{
base->flexioBase->SHIFTBUF[base->shifterIndex[0]] = *buffer;
}
/*!
* @brief Reads one byte of data.
*
* @note This is a non-blocking API, which returns directly after the data is read from the
* data register. Ensure that the RxFullFlag is asserted before calling this API.
*
* @param base Pointer to the FLEXIO_UART_Type structure.
* @param buffer The buffer to store the received bytes.
*/
static inline void FLEXIO_UART_ReadByte(FLEXIO_UART_Type *base, uint8_t *buffer)
{
*buffer = base->flexioBase->SHIFTBUFBYS[base->shifterIndex[1]];
}
/*!
* @brief Sends a buffer of data bytes.
*
* @note This function blocks using the polling method until all bytes have been sent.
*
* @param base Pointer to the FLEXIO_UART_Type structure.
* @param txData The data bytes to send.
* @param txSize The number of data bytes to send.
*/
void FLEXIO_UART_WriteBlocking(FLEXIO_UART_Type *base, const uint8_t *txData, size_t txSize);
/*!
* @brief Receives a buffer of bytes.
*
* @note This function blocks using the polling method until all bytes have been received.
*
* @param base Pointer to the FLEXIO_UART_Type structure.
* @param rxData The buffer to store the received bytes.
* @param rxSize The number of data bytes to be received.
*/
void FLEXIO_UART_ReadBlocking(FLEXIO_UART_Type *base, uint8_t *rxData, size_t rxSize);
/* @} */
/*!
* @name Transactional
* @{
*/
/*!
* @brief Initializes the UART handle.
*
* This function initializes the FlexIO UART handle, which can be used for other FlexIO
* UART transactional APIs. Call this API once to get the
* initialized handle.
*
* The UART driver supports the "background" receiving, which means that users can set up
* a RX ring buffer optionally. Data received is stored into the ring buffer even when
* the user doesn't call the FLEXIO_UART_TransferReceiveNonBlocking() API. If there is already data
* received in the ring buffer, users can get the received data from the ring buffer
* directly. The ring buffer is disabled if passing NULL as @p ringBuffer.
*
* @param base to FLEXIO_UART_Type structure.
* @param handle Pointer to the flexio_uart_handle_t structure to store the transfer state.
* @param callback The callback function.
* @param userData The parameter of the callback function.
* @retval kStatus_Success Successfully create the handle.
* @retval kStatus_OutOfRange The FlexIO type/handle/ISR table out of range.
*/
status_t FLEXIO_UART_TransferCreateHandle(FLEXIO_UART_Type *base,
flexio_uart_handle_t *handle,
flexio_uart_transfer_callback_t callback,
void *userData);
/*!
* @brief Sets up the RX ring buffer.
*
* This function sets up the RX ring buffer to a specific UART handle.
*
* When the RX ring buffer is used, data received is stored into the ring buffer even when
* the user doesn't call the UART_ReceiveNonBlocking() API. If there is already data received
* in the ring buffer, users can get the received data from the ring buffer directly.
*
* @note When using the RX ring buffer, one byte is reserved for internal use. In other
* words, if @p ringBufferSize is 32, only 31 bytes are used for saving data.
*
* @param base Pointer to the FLEXIO_UART_Type structure.
* @param handle Pointer to the flexio_uart_handle_t structure to store the transfer state.
* @param ringBuffer Start address of ring buffer for background receiving. Pass NULL to disable the ring buffer.
* @param ringBufferSize Size of the ring buffer.
*/
void FLEXIO_UART_TransferStartRingBuffer(FLEXIO_UART_Type *base,
flexio_uart_handle_t *handle,
uint8_t *ringBuffer,
size_t ringBufferSize);
/*!
* @brief Aborts the background transfer and uninstalls the ring buffer.
*
* This function aborts the background transfer and uninstalls the ring buffer.
*
* @param base Pointer to the FLEXIO_UART_Type structure.
* @param handle Pointer to the flexio_uart_handle_t structure to store the transfer state.
*/
void FLEXIO_UART_TransferStopRingBuffer(FLEXIO_UART_Type *base, flexio_uart_handle_t *handle);
/*!
* @brief Transmits a buffer of data using the interrupt method.
*
* This function sends data using an interrupt method. This is a non-blocking function,
* which returns directly without waiting for all data to be written to the TX register. When
* all data is written to the TX register in ISR, the FlexIO UART driver calls the callback
* function and passes the @ref kStatus_FLEXIO_UART_TxIdle as status parameter.
*
* @note The kStatus_FLEXIO_UART_TxIdle is passed to the upper layer when all data is written
* to the TX register. However, it does not ensure that all data is sent out.
*
* @param base Pointer to the FLEXIO_UART_Type structure.
* @param handle Pointer to the flexio_uart_handle_t structure to store the transfer state.
* @param xfer FlexIO UART transfer structure. See #flexio_uart_transfer_t.
* @retval kStatus_Success Successfully starts the data transmission.
* @retval kStatus_UART_TxBusy Previous transmission still not finished, data not written to the TX register.
*/
status_t FLEXIO_UART_TransferSendNonBlocking(FLEXIO_UART_Type *base,
flexio_uart_handle_t *handle,
flexio_uart_transfer_t *xfer);
/*!
* @brief Aborts the interrupt-driven data transmit.
*
* This function aborts the interrupt-driven data sending. Get the remainBytes to find out
* how many bytes are still not sent out.
*
* @param base Pointer to the FLEXIO_UART_Type structure.
* @param handle Pointer to the flexio_uart_handle_t structure to store the transfer state.
*/
void FLEXIO_UART_TransferAbortSend(FLEXIO_UART_Type *base, flexio_uart_handle_t *handle);
/*!
* @brief Gets the number of bytes sent.
*
* This function gets the number of bytes sent driven by interrupt.
*
* @param base Pointer to the FLEXIO_UART_Type structure.
* @param handle Pointer to the flexio_uart_handle_t structure to store the transfer state.
* @param count Number of bytes sent so far by the non-blocking transaction.
* @retval kStatus_NoTransferInProgress transfer has finished or no transfer in progress.
* @retval kStatus_Success Successfully return the count.
*/
status_t FLEXIO_UART_TransferGetSendCount(FLEXIO_UART_Type *base, flexio_uart_handle_t *handle, size_t *count);
/*!
* @brief Receives a buffer of data using the interrupt method.
*
* This function receives data using the interrupt method. This is a non-blocking function,
* which returns without waiting for all data to be received.
* If the RX ring buffer is used and not empty, the data in ring buffer is copied and
* the parameter @p receivedBytes shows how many bytes are copied from the ring buffer.
* After copying, if the data in ring buffer is not enough to read, the receive
* request is saved by the UART driver. When new data arrives, the receive request
* is serviced first. When all data is received, the UART driver notifies the upper layer
* through a callback function and passes the status parameter @ref kStatus_UART_RxIdle.
* For example, if the upper layer needs 10 bytes but there are only 5 bytes in the ring buffer,
* the 5 bytes are copied to xfer->data. This function returns with the
* parameter @p receivedBytes set to 5. For the last 5 bytes, newly arrived data is
* saved from the xfer->data[5]. When 5 bytes are received, the UART driver notifies upper layer.
* If the RX ring buffer is not enabled, this function enables the RX and RX interrupt
* to receive data to xfer->data. When all data is received, the upper layer is notified.
*
* @param base Pointer to the FLEXIO_UART_Type structure.
* @param handle Pointer to the flexio_uart_handle_t structure to store the transfer state.
* @param xfer UART transfer structure. See #flexio_uart_transfer_t.
* @param receivedBytes Bytes received from the ring buffer directly.
* @retval kStatus_Success Successfully queue the transfer into the transmit queue.
* @retval kStatus_FLEXIO_UART_RxBusy Previous receive request is not finished.
*/
status_t FLEXIO_UART_TransferReceiveNonBlocking(FLEXIO_UART_Type *base,
flexio_uart_handle_t *handle,
flexio_uart_transfer_t *xfer,
size_t *receivedBytes);
/*!
* @brief Aborts the receive data which was using IRQ.
*
* This function aborts the receive data which was using IRQ.
*
* @param base Pointer to the FLEXIO_UART_Type structure.
* @param handle Pointer to the flexio_uart_handle_t structure to store the transfer state.
*/
void FLEXIO_UART_TransferAbortReceive(FLEXIO_UART_Type *base, flexio_uart_handle_t *handle);
/*!
* @brief Gets the number of bytes received.
*
* This function gets the number of bytes received driven by interrupt.
*
* @param base Pointer to the FLEXIO_UART_Type structure.
* @param handle Pointer to the flexio_uart_handle_t structure to store the transfer state.
* @param count Number of bytes received so far by the non-blocking transaction.
* @retval kStatus_NoTransferInProgress transfer has finished or no transfer in progress.
* @retval kStatus_Success Successfully return the count.
*/
status_t FLEXIO_UART_TransferGetReceiveCount(FLEXIO_UART_Type *base, flexio_uart_handle_t *handle, size_t *count);
/*!
* @brief FlexIO UART IRQ handler function.
*
* This function processes the FlexIO UART transmit and receives the IRQ request.
*
* @param uartType Pointer to the FLEXIO_UART_Type structure.
* @param uartHandle Pointer to the flexio_uart_handle_t structure to store the transfer state.
*/
void FLEXIO_UART_TransferHandleIRQ(void *uartType, void *uartHandle);
/*@}*/
#if defined(__cplusplus)
}
#endif /*_cplusplus*/
/*@}*/
#endif /*_FSL_FLEXIO_UART_H_*/

View File

@ -0,0 +1,327 @@
/*
* Copyright (c) 2015, Freescale Semiconductor, Inc.
* Copyright 2016-2017 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include "fsl_flexio_uart_edma.h"
/*******************************************************************************
* Definitions
******************************************************************************/
/*<! Structure definition for uart_edma_private_handle_t. The structure is private. */
typedef struct _flexio_uart_edma_private_handle
{
FLEXIO_UART_Type *base;
flexio_uart_edma_handle_t *handle;
} flexio_uart_edma_private_handle_t;
/* UART EDMA transfer handle. */
enum _flexio_uart_edma_tansfer_states
{
kFLEXIO_UART_TxIdle, /* TX idle. */
kFLEXIO_UART_TxBusy, /* TX busy. */
kFLEXIO_UART_RxIdle, /* RX idle. */
kFLEXIO_UART_RxBusy /* RX busy. */
};
/*******************************************************************************
* Definitions
******************************************************************************/
/*< @brief user configurable flexio uart handle count. */
#define FLEXIO_UART_HANDLE_COUNT 2
/*<! Private handle only used for internally. */
static flexio_uart_edma_private_handle_t s_edmaPrivateHandle[FLEXIO_UART_HANDLE_COUNT];
/*******************************************************************************
* Prototypes
******************************************************************************/
/*!
* @brief FLEXIO UART EDMA send finished callback function.
*
* This function is called when FLEXIO UART EDMA send finished. It disables the UART
* TX EDMA request and sends @ref kStatus_FLEXIO_UART_TxIdle to FLEXIO UART callback.
*
* @param handle The EDMA handle.
* @param param Callback function parameter.
*/
static void FLEXIO_UART_TransferSendEDMACallback(edma_handle_t *handle, void *param, bool transferDone, uint32_t tcds);
/*!
* @brief FLEXIO UART EDMA receive finished callback function.
*
* This function is called when FLEXIO UART EDMA receive finished. It disables the UART
* RX EDMA request and sends @ref kStatus_FLEXIO_UART_RxIdle to UART callback.
*
* @param handle The EDMA handle.
* @param param Callback function parameter.
*/
static void FLEXIO_UART_TransferReceiveEDMACallback(edma_handle_t *handle,
void *param,
bool transferDone,
uint32_t tcds);
/*******************************************************************************
* Code
******************************************************************************/
static void FLEXIO_UART_TransferSendEDMACallback(edma_handle_t *handle, void *param, bool transferDone, uint32_t tcds)
{
flexio_uart_edma_private_handle_t *uartPrivateHandle = (flexio_uart_edma_private_handle_t *)param;
assert(uartPrivateHandle->handle);
/* Avoid the warning for unused variables. */
handle = handle;
tcds = tcds;
if (transferDone)
{
FLEXIO_UART_TransferAbortSendEDMA(uartPrivateHandle->base, uartPrivateHandle->handle);
if (uartPrivateHandle->handle->callback)
{
uartPrivateHandle->handle->callback(uartPrivateHandle->base, uartPrivateHandle->handle,
kStatus_FLEXIO_UART_TxIdle, uartPrivateHandle->handle->userData);
}
}
}
static void FLEXIO_UART_TransferReceiveEDMACallback(edma_handle_t *handle,
void *param,
bool transferDone,
uint32_t tcds)
{
flexio_uart_edma_private_handle_t *uartPrivateHandle = (flexio_uart_edma_private_handle_t *)param;
assert(uartPrivateHandle->handle);
/* Avoid the warning for unused variables. */
handle = handle;
tcds = tcds;
if (transferDone)
{
/* Disable transfer. */
FLEXIO_UART_TransferAbortReceiveEDMA(uartPrivateHandle->base, uartPrivateHandle->handle);
if (uartPrivateHandle->handle->callback)
{
uartPrivateHandle->handle->callback(uartPrivateHandle->base, uartPrivateHandle->handle,
kStatus_FLEXIO_UART_RxIdle, uartPrivateHandle->handle->userData);
}
}
}
status_t FLEXIO_UART_TransferCreateHandleEDMA(FLEXIO_UART_Type *base,
flexio_uart_edma_handle_t *handle,
flexio_uart_edma_transfer_callback_t callback,
void *userData,
edma_handle_t *txEdmaHandle,
edma_handle_t *rxEdmaHandle)
{
assert(handle);
uint8_t index = 0;
/* Find the an empty handle pointer to store the handle. */
for (index = 0; index < FLEXIO_UART_HANDLE_COUNT; index++)
{
if (s_edmaPrivateHandle[index].base == NULL)
{
s_edmaPrivateHandle[index].base = base;
s_edmaPrivateHandle[index].handle = handle;
break;
}
}
if (index == FLEXIO_UART_HANDLE_COUNT)
{
return kStatus_OutOfRange;
}
memset(handle, 0, sizeof(*handle));
handle->rxState = kFLEXIO_UART_RxIdle;
handle->txState = kFLEXIO_UART_TxIdle;
handle->rxEdmaHandle = rxEdmaHandle;
handle->txEdmaHandle = txEdmaHandle;
handle->callback = callback;
handle->userData = userData;
/* Configure TX. */
if (txEdmaHandle)
{
EDMA_SetCallback(handle->txEdmaHandle, FLEXIO_UART_TransferSendEDMACallback, &s_edmaPrivateHandle);
}
/* Configure RX. */
if (rxEdmaHandle)
{
EDMA_SetCallback(handle->rxEdmaHandle, FLEXIO_UART_TransferReceiveEDMACallback, &s_edmaPrivateHandle);
}
return kStatus_Success;
}
status_t FLEXIO_UART_TransferSendEDMA(FLEXIO_UART_Type *base,
flexio_uart_edma_handle_t *handle,
flexio_uart_transfer_t *xfer)
{
assert(handle->txEdmaHandle);
edma_transfer_config_t xferConfig;
status_t status;
/* Return error if xfer invalid. */
if ((0U == xfer->dataSize) || (NULL == xfer->data))
{
return kStatus_InvalidArgument;
}
/* If previous TX not finished. */
if (kFLEXIO_UART_TxBusy == handle->txState)
{
status = kStatus_FLEXIO_UART_TxBusy;
}
else
{
handle->txState = kFLEXIO_UART_TxBusy;
handle->txDataSizeAll = xfer->dataSize;
/* Prepare transfer. */
EDMA_PrepareTransfer(&xferConfig, xfer->data, sizeof(uint8_t),
(void *)FLEXIO_UART_GetTxDataRegisterAddress(base), sizeof(uint8_t), sizeof(uint8_t),
xfer->dataSize, kEDMA_MemoryToPeripheral);
/* Store the initially configured eDMA minor byte transfer count into the FLEXIO UART handle */
handle->nbytes = sizeof(uint8_t);
/* Submit transfer. */
EDMA_SubmitTransfer(handle->txEdmaHandle, &xferConfig);
EDMA_StartTransfer(handle->txEdmaHandle);
/* Enable UART TX EDMA. */
FLEXIO_UART_EnableTxDMA(base, true);
status = kStatus_Success;
}
return status;
}
status_t FLEXIO_UART_TransferReceiveEDMA(FLEXIO_UART_Type *base,
flexio_uart_edma_handle_t *handle,
flexio_uart_transfer_t *xfer)
{
assert(handle->rxEdmaHandle);
edma_transfer_config_t xferConfig;
status_t status;
/* Return error if xfer invalid. */
if ((0U == xfer->dataSize) || (NULL == xfer->data))
{
return kStatus_InvalidArgument;
}
/* If previous RX not finished. */
if (kFLEXIO_UART_RxBusy == handle->rxState)
{
status = kStatus_FLEXIO_UART_RxBusy;
}
else
{
handle->rxState = kFLEXIO_UART_RxBusy;
handle->rxDataSizeAll = xfer->dataSize;
/* Prepare transfer. */
EDMA_PrepareTransfer(&xferConfig, (void *)FLEXIO_UART_GetRxDataRegisterAddress(base), sizeof(uint8_t),
xfer->data, sizeof(uint8_t), sizeof(uint8_t), xfer->dataSize, kEDMA_PeripheralToMemory);
/* Store the initially configured eDMA minor byte transfer count into the FLEXIO UART handle */
handle->nbytes = sizeof(uint8_t);
/* Submit transfer. */
EDMA_SubmitTransfer(handle->rxEdmaHandle, &xferConfig);
EDMA_StartTransfer(handle->rxEdmaHandle);
/* Enable UART RX EDMA. */
FLEXIO_UART_EnableRxDMA(base, true);
status = kStatus_Success;
}
return status;
}
void FLEXIO_UART_TransferAbortSendEDMA(FLEXIO_UART_Type *base, flexio_uart_edma_handle_t *handle)
{
assert(handle->txEdmaHandle);
/* Disable UART TX EDMA. */
FLEXIO_UART_EnableTxDMA(base, false);
/* Stop transfer. */
EDMA_StopTransfer(handle->txEdmaHandle);
handle->txState = kFLEXIO_UART_TxIdle;
}
void FLEXIO_UART_TransferAbortReceiveEDMA(FLEXIO_UART_Type *base, flexio_uart_edma_handle_t *handle)
{
assert(handle->rxEdmaHandle);
/* Disable UART RX EDMA. */
FLEXIO_UART_EnableRxDMA(base, false);
/* Stop transfer. */
EDMA_StopTransfer(handle->rxEdmaHandle);
handle->rxState = kFLEXIO_UART_RxIdle;
}
status_t FLEXIO_UART_TransferGetReceiveCountEDMA(FLEXIO_UART_Type *base,
flexio_uart_edma_handle_t *handle,
size_t *count)
{
assert(handle);
assert(handle->rxEdmaHandle);
assert(count);
if (kFLEXIO_UART_RxIdle == handle->rxState)
{
return kStatus_NoTransferInProgress;
}
*count = handle->rxDataSizeAll -
(uint32_t)handle->nbytes *
EDMA_GetRemainingMajorLoopCount(handle->rxEdmaHandle->base, handle->rxEdmaHandle->channel);
return kStatus_Success;
}
status_t FLEXIO_UART_TransferGetSendCountEDMA(FLEXIO_UART_Type *base, flexio_uart_edma_handle_t *handle, size_t *count)
{
assert(handle);
assert(handle->txEdmaHandle);
assert(count);
if (kFLEXIO_UART_TxIdle == handle->txState)
{
return kStatus_NoTransferInProgress;
}
*count = handle->txDataSizeAll -
(uint32_t)handle->nbytes *
EDMA_GetRemainingMajorLoopCount(handle->txEdmaHandle->base, handle->txEdmaHandle->channel);
return kStatus_Success;
}

View File

@ -0,0 +1,172 @@
/*
* Copyright (c) 2015, Freescale Semiconductor, Inc.
* Copyright 2016-2017 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef _FSL_FLEXIO_UART_EDMA_H_
#define _FSL_FLEXIO_UART_EDMA_H_
#include "fsl_flexio_uart.h"
#include "fsl_edma.h"
/*!
* @addtogroup flexio_edma_uart
* @{
*/
/*******************************************************************************
* Definitions
******************************************************************************/
/* Forward declaration of the handle typedef. */
typedef struct _flexio_uart_edma_handle flexio_uart_edma_handle_t;
/*! @brief UART transfer callback function. */
typedef void (*flexio_uart_edma_transfer_callback_t)(FLEXIO_UART_Type *base,
flexio_uart_edma_handle_t *handle,
status_t status,
void *userData);
/*!
* @brief UART eDMA handle
*/
struct _flexio_uart_edma_handle
{
flexio_uart_edma_transfer_callback_t callback; /*!< Callback function. */
void *userData; /*!< UART callback function parameter.*/
size_t txDataSizeAll; /*!< Total bytes to be sent. */
size_t rxDataSizeAll; /*!< Total bytes to be received. */
edma_handle_t *txEdmaHandle; /*!< The eDMA TX channel used. */
edma_handle_t *rxEdmaHandle; /*!< The eDMA RX channel used. */
uint8_t nbytes; /*!< eDMA minor byte transfer count initially configured. */
volatile uint8_t txState; /*!< TX transfer state. */
volatile uint8_t rxState; /*!< RX transfer state */
};
/*******************************************************************************
* API
******************************************************************************/
#if defined(__cplusplus)
extern "C" {
#endif
/*!
* @name eDMA transactional
* @{
*/
/*!
* @brief Initializes the UART handle which is used in transactional functions.
*
* @param base Pointer to FLEXIO_UART_Type.
* @param handle Pointer to flexio_uart_edma_handle_t structure.
* @param callback The callback function.
* @param userData The parameter of the callback function.
* @param rxEdmaHandle User requested DMA handle for RX DMA transfer.
* @param txEdmaHandle User requested DMA handle for TX DMA transfer.
* @retval kStatus_Success Successfully create the handle.
* @retval kStatus_OutOfRange The FlexIO SPI eDMA type/handle table out of range.
*/
status_t FLEXIO_UART_TransferCreateHandleEDMA(FLEXIO_UART_Type *base,
flexio_uart_edma_handle_t *handle,
flexio_uart_edma_transfer_callback_t callback,
void *userData,
edma_handle_t *txEdmaHandle,
edma_handle_t *rxEdmaHandle);
/*!
* @brief Sends data using eDMA.
*
* This function sends data using eDMA. This is a non-blocking function, which returns
* right away. When all data is sent out, the send callback function is called.
*
* @param base Pointer to FLEXIO_UART_Type
* @param handle UART handle pointer.
* @param xfer UART eDMA transfer structure, see #flexio_uart_transfer_t.
* @retval kStatus_Success if succeed, others failed.
* @retval kStatus_FLEXIO_UART_TxBusy Previous transfer on going.
*/
status_t FLEXIO_UART_TransferSendEDMA(FLEXIO_UART_Type *base,
flexio_uart_edma_handle_t *handle,
flexio_uart_transfer_t *xfer);
/*!
* @brief Receives data using eDMA.
*
* This function receives data using eDMA. This is a non-blocking function, which returns
* right away. When all data is received, the receive callback function is called.
*
* @param base Pointer to FLEXIO_UART_Type
* @param handle Pointer to flexio_uart_edma_handle_t structure
* @param xfer UART eDMA transfer structure, see #flexio_uart_transfer_t.
* @retval kStatus_Success if succeed, others failed.
* @retval kStatus_UART_RxBusy Previous transfer on going.
*/
status_t FLEXIO_UART_TransferReceiveEDMA(FLEXIO_UART_Type *base,
flexio_uart_edma_handle_t *handle,
flexio_uart_transfer_t *xfer);
/*!
* @brief Aborts the sent data which using eDMA.
*
* This function aborts sent data which using eDMA.
*
* @param base Pointer to FLEXIO_UART_Type
* @param handle Pointer to flexio_uart_edma_handle_t structure
*/
void FLEXIO_UART_TransferAbortSendEDMA(FLEXIO_UART_Type *base, flexio_uart_edma_handle_t *handle);
/*!
* @brief Aborts the receive data which using eDMA.
*
* This function aborts the receive data which using eDMA.
*
* @param base Pointer to FLEXIO_UART_Type
* @param handle Pointer to flexio_uart_edma_handle_t structure
*/
void FLEXIO_UART_TransferAbortReceiveEDMA(FLEXIO_UART_Type *base, flexio_uart_edma_handle_t *handle);
/*!
* @brief Gets the number of bytes sent out.
*
* This function gets the number of bytes sent out.
*
* @param base Pointer to FLEXIO_UART_Type
* @param handle Pointer to flexio_uart_edma_handle_t structure
* @param count Number of bytes sent so far by the non-blocking transaction.
* @retval kStatus_NoTransferInProgress transfer has finished or no transfer in progress.
* @retval kStatus_Success Successfully return the count.
*/
status_t FLEXIO_UART_TransferGetSendCountEDMA(FLEXIO_UART_Type *base, flexio_uart_edma_handle_t *handle, size_t *count);
/*!
* @brief Gets the number of bytes received.
*
* This function gets the number of bytes received.
*
* @param base Pointer to FLEXIO_UART_Type
* @param handle Pointer to flexio_uart_edma_handle_t structure
* @param count Number of bytes received so far by the non-blocking transaction.
* @retval kStatus_NoTransferInProgress transfer has finished or no transfer in progress.
* @retval kStatus_Success Successfully return the count.
*/
status_t FLEXIO_UART_TransferGetReceiveCountEDMA(FLEXIO_UART_Type *base,
flexio_uart_edma_handle_t *handle,
size_t *count);
/*@}*/
#if defined(__cplusplus)
}
#endif
/*! @}*/
#endif /* _FSL_UART_EDMA_H_ */

View File

@ -0,0 +1,196 @@
/*
* Copyright (c) 2015, Freescale Semiconductor, Inc.
* Copyright 2016-2017 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include "fsl_gpio.h"
/*******************************************************************************
* Variables
******************************************************************************/
static PORT_Type *const s_portBases[] = PORT_BASE_PTRS;
static GPIO_Type *const s_gpioBases[] = GPIO_BASE_PTRS;
#if defined(FSL_FEATURE_SOC_FGPIO_COUNT) && FSL_FEATURE_SOC_FGPIO_COUNT
#if defined(FSL_FEATURE_PCC_HAS_FGPIO_CLOCK_GATE_CONTROL) && FSL_FEATURE_PCC_HAS_FGPIO_CLOCK_GATE_CONTROL
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
/*! @brief Array to map FGPIO instance number to clock name. */
static const clock_ip_name_t s_fgpioClockName[] = FGPIO_CLOCKS;
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
#endif /* FSL_FEATURE_PCC_HAS_FGPIO_CLOCK_GATE_CONTROL */
#endif /* FSL_FEATURE_SOC_FGPIO_COUNT */
/*******************************************************************************
* Prototypes
******************************************************************************/
/*!
* @brief Gets the GPIO instance according to the GPIO base
*
* @param base GPIO peripheral base pointer(PTA, PTB, PTC, etc.)
* @retval GPIO instance
*/
static uint32_t GPIO_GetInstance(GPIO_Type *base);
/*******************************************************************************
* Code
******************************************************************************/
static uint32_t GPIO_GetInstance(GPIO_Type *base)
{
uint32_t instance;
/* Find the instance index from base address mappings. */
for (instance = 0; instance < ARRAY_SIZE(s_gpioBases); instance++)
{
if (s_gpioBases[instance] == base)
{
break;
}
}
assert(instance < ARRAY_SIZE(s_gpioBases));
return instance;
}
void GPIO_PinInit(GPIO_Type *base, uint32_t pin, const gpio_pin_config_t *config)
{
assert(config);
if (config->pinDirection == kGPIO_DigitalInput)
{
base->PDDR &= ~(1U << pin);
}
else
{
GPIO_WritePinOutput(base, pin, config->outputLogic);
base->PDDR |= (1U << pin);
}
}
uint32_t GPIO_GetPinsInterruptFlags(GPIO_Type *base)
{
uint8_t instance;
PORT_Type *portBase;
instance = GPIO_GetInstance(base);
portBase = s_portBases[instance];
return portBase->ISFR;
}
void GPIO_ClearPinsInterruptFlags(GPIO_Type *base, uint32_t mask)
{
uint8_t instance;
PORT_Type *portBase;
instance = GPIO_GetInstance(base);
portBase = s_portBases[instance];
portBase->ISFR = mask;
}
#if defined(FSL_FEATURE_GPIO_HAS_ATTRIBUTE_CHECKER) && FSL_FEATURE_GPIO_HAS_ATTRIBUTE_CHECKER
void GPIO_CheckAttributeBytes(GPIO_Type *base, gpio_checker_attribute_t attribute)
{
base->GACR = ((uint32_t)attribute << GPIO_GACR_ACB0_SHIFT) | ((uint32_t)attribute << GPIO_GACR_ACB1_SHIFT) |
((uint32_t)attribute << GPIO_GACR_ACB2_SHIFT) | ((uint32_t)attribute << GPIO_GACR_ACB3_SHIFT);
}
#endif
#if defined(FSL_FEATURE_SOC_FGPIO_COUNT) && FSL_FEATURE_SOC_FGPIO_COUNT
/*******************************************************************************
* Variables
******************************************************************************/
static FGPIO_Type *const s_fgpioBases[] = FGPIO_BASE_PTRS;
/*******************************************************************************
* Prototypes
******************************************************************************/
/*!
* @brief Gets the FGPIO instance according to the GPIO base
*
* @param base FGPIO peripheral base pointer(PTA, PTB, PTC, etc.)
* @retval FGPIO instance
*/
static uint32_t FGPIO_GetInstance(FGPIO_Type *base);
/*******************************************************************************
* Code
******************************************************************************/
static uint32_t FGPIO_GetInstance(FGPIO_Type *base)
{
uint32_t instance;
/* Find the instance index from base address mappings. */
for (instance = 0; instance < ARRAY_SIZE(s_fgpioBases); instance++)
{
if (s_fgpioBases[instance] == base)
{
break;
}
}
assert(instance < ARRAY_SIZE(s_fgpioBases));
return instance;
}
#if defined(FSL_FEATURE_PCC_HAS_FGPIO_CLOCK_GATE_CONTROL) && FSL_FEATURE_PCC_HAS_FGPIO_CLOCK_GATE_CONTROL
void FGPIO_Init(FGPIO_Type *base)
{
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
/* Ungate FGPIO periphral clock */
CLOCK_EnableClock(s_fgpioClockName[FGPIO_GetInstance(base)]);
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
}
#endif /* FSL_FEATURE_PCC_HAS_FGPIO_CLOCK_GATE_CONTROL */
void FGPIO_PinInit(FGPIO_Type *base, uint32_t pin, const gpio_pin_config_t *config)
{
assert(config);
if (config->pinDirection == kGPIO_DigitalInput)
{
base->PDDR &= ~(1U << pin);
}
else
{
FGPIO_WritePinOutput(base, pin, config->outputLogic);
base->PDDR |= (1U << pin);
}
}
uint32_t FGPIO_GetPinsInterruptFlags(FGPIO_Type *base)
{
uint8_t instance;
instance = FGPIO_GetInstance(base);
PORT_Type *portBase;
portBase = s_portBases[instance];
return portBase->ISFR;
}
void FGPIO_ClearPinsInterruptFlags(FGPIO_Type *base, uint32_t mask)
{
uint8_t instance;
instance = FGPIO_GetInstance(base);
PORT_Type *portBase;
portBase = s_portBases[instance];
portBase->ISFR = mask;
}
#if defined(FSL_FEATURE_FGPIO_HAS_ATTRIBUTE_CHECKER) && FSL_FEATURE_FGPIO_HAS_ATTRIBUTE_CHECKER
void FGPIO_CheckAttributeBytes(FGPIO_Type *base, gpio_checker_attribute_t attribute)
{
base->GACR = (attribute << FGPIO_GACR_ACB0_SHIFT) | (attribute << FGPIO_GACR_ACB1_SHIFT) |
(attribute << FGPIO_GACR_ACB2_SHIFT) | (attribute << FGPIO_GACR_ACB3_SHIFT);
}
#endif
#endif /* FSL_FEATURE_SOC_FGPIO_COUNT */

View File

@ -0,0 +1,427 @@
/*
* Copyright (c) 2015, Freescale Semiconductor, Inc.
* Copyright 2016-2017 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef _FSL_GPIO_H_
#define _FSL_GPIO_H_
#include "fsl_common.h"
/*!
* @addtogroup gpio
* @{
*/
/*******************************************************************************
* Definitions
******************************************************************************/
/*! @name Driver version */
/*@{*/
/*! @brief GPIO driver version 2.2.0. */
#define FSL_GPIO_DRIVER_VERSION (MAKE_VERSION(2, 2, 0))
/*@}*/
/*! @brief GPIO direction definition */
typedef enum _gpio_pin_direction
{
kGPIO_DigitalInput = 0U, /*!< Set current pin as digital input*/
kGPIO_DigitalOutput = 1U, /*!< Set current pin as digital output*/
} gpio_pin_direction_t;
#if defined(FSL_FEATURE_GPIO_HAS_ATTRIBUTE_CHECKER) && FSL_FEATURE_GPIO_HAS_ATTRIBUTE_CHECKER
/*! @brief GPIO checker attribute */
typedef enum _gpio_checker_attribute
{
kGPIO_UsernonsecureRWUsersecureRWPrivilegedsecureRW =
0x00U, /*!< User nonsecure:Read+Write; User Secure:Read+Write; Privileged Secure:Read+Write */
kGPIO_UsernonsecureRUsersecureRWPrivilegedsecureRW =
0x01U, /*!< User nonsecure:Read; User Secure:Read+Write; Privileged Secure:Read+Write */
kGPIO_UsernonsecureNUsersecureRWPrivilegedsecureRW =
0x02U, /*!< User nonsecure:None; User Secure:Read+Write; Privileged Secure:Read+Write */
kGPIO_UsernonsecureRUsersecureRPrivilegedsecureRW =
0x03U, /*!< User nonsecure:Read; User Secure:Read; Privileged Secure:Read+Write */
kGPIO_UsernonsecureNUsersecureRPrivilegedsecureRW =
0x04U, /*!< User nonsecure:None; User Secure:Read; Privileged Secure:Read+Write */
kGPIO_UsernonsecureNUsersecureNPrivilegedsecureRW =
0x05U, /*!< User nonsecure:None; User Secure:None; Privileged Secure:Read+Write */
kGPIO_UsernonsecureNUsersecureNPrivilegedsecureR =
0x06U, /*!< User nonsecure:None; User Secure:None; Privileged Secure:Read */
kGPIO_UsernonsecureNUsersecureNPrivilegedsecureN =
0x07U, /*!< User nonsecure:None; User Secure:None; Privileged Secure:None */
kGPIO_IgnoreAttributeCheck = 0x80U, /*!< Ignores the attribute check */
} gpio_checker_attribute_t;
#endif
/*!
* @brief The GPIO pin configuration structure.
*
* Each pin can only be configured as either an output pin or an input pin at a time.
* If configured as an input pin, leave the outputConfig unused.
* Note that in some use cases, the corresponding port property should be configured in advance
* with the PORT_SetPinConfig().
*/
typedef struct _gpio_pin_config
{
gpio_pin_direction_t pinDirection; /*!< GPIO direction, input or output */
/* Output configurations; ignore if configured as an input pin */
uint8_t outputLogic; /*!< Set a default output logic, which has no use in input */
} gpio_pin_config_t;
/*! @} */
/*******************************************************************************
* API
******************************************************************************/
#if defined(__cplusplus)
extern "C" {
#endif
/*!
* @addtogroup gpio_driver
* @{
*/
/*! @name GPIO Configuration */
/*@{*/
/*!
* @brief Initializes a GPIO pin used by the board.
*
* To initialize the GPIO, define a pin configuration, as either input or output, in the user file.
* Then, call the GPIO_PinInit() function.
*
* This is an example to define an input pin or an output pin configuration.
* @code
* // Define a digital input pin configuration,
* gpio_pin_config_t config =
* {
* kGPIO_DigitalInput,
* 0,
* }
* //Define a digital output pin configuration,
* gpio_pin_config_t config =
* {
* kGPIO_DigitalOutput,
* 0,
* }
* @endcode
*
* @param base GPIO peripheral base pointer (GPIOA, GPIOB, GPIOC, and so on.)
* @param pin GPIO port pin number
* @param config GPIO pin configuration pointer
*/
void GPIO_PinInit(GPIO_Type *base, uint32_t pin, const gpio_pin_config_t *config);
/*@}*/
/*! @name GPIO Output Operations */
/*@{*/
/*!
* @brief Sets the output level of the multiple GPIO pins to the logic 1 or 0.
*
* @param base GPIO peripheral base pointer (GPIOA, GPIOB, GPIOC, and so on.)
* @param pin GPIO pin number
* @param output GPIO pin output logic level.
* - 0: corresponding pin output low-logic level.
* - 1: corresponding pin output high-logic level.
*/
static inline void GPIO_WritePinOutput(GPIO_Type *base, uint32_t pin, uint8_t output)
{
if (output == 0U)
{
base->PCOR = 1U << pin;
}
else
{
base->PSOR = 1U << pin;
}
}
/*!
* @brief Sets the output level of the multiple GPIO pins to the logic 1.
*
* @param base GPIO peripheral base pointer (GPIOA, GPIOB, GPIOC, and so on.)
* @param mask GPIO pin number macro
*/
static inline void GPIO_SetPinsOutput(GPIO_Type *base, uint32_t mask)
{
base->PSOR = mask;
}
/*!
* @brief Sets the output level of the multiple GPIO pins to the logic 0.
*
* @param base GPIO peripheral base pointer (GPIOA, GPIOB, GPIOC, and so on.)
* @param mask GPIO pin number macro
*/
static inline void GPIO_ClearPinsOutput(GPIO_Type *base, uint32_t mask)
{
base->PCOR = mask;
}
/*!
* @brief Reverses the current output logic of the multiple GPIO pins.
*
* @param base GPIO peripheral base pointer (GPIOA, GPIOB, GPIOC, and so on.)
* @param mask GPIO pin number macro
*/
static inline void GPIO_TogglePinsOutput(GPIO_Type *base, uint32_t mask)
{
base->PTOR = mask;
}
/*@}*/
/*! @name GPIO Input Operations */
/*@{*/
/*!
* @brief Reads the current input value of the GPIO port.
*
* @param base GPIO peripheral base pointer (GPIOA, GPIOB, GPIOC, and so on.)
* @param pin GPIO pin number
* @retval GPIO port input value
* - 0: corresponding pin input low-logic level.
* - 1: corresponding pin input high-logic level.
*/
static inline uint32_t GPIO_ReadPinInput(GPIO_Type *base, uint32_t pin)
{
return (((base->PDIR) >> pin) & 0x01U);
}
/*@}*/
/*! @name GPIO Interrupt */
/*@{*/
/*!
* @brief Reads the GPIO port interrupt status flag.
*
* If a pin is configured to generate the DMA request, the corresponding flag
* is cleared automatically at the completion of the requested DMA transfer.
* Otherwise, the flag remains set until a logic one is written to that flag.
* If configured for a level sensitive interrupt that remains asserted, the flag
* is set again immediately.
*
* @param base GPIO peripheral base pointer (GPIOA, GPIOB, GPIOC, and so on.)
* @retval The current GPIO port interrupt status flag, for example, 0x00010001 means the
* pin 0 and 17 have the interrupt.
*/
uint32_t GPIO_GetPinsInterruptFlags(GPIO_Type *base);
/*!
* @brief Clears multiple GPIO pin interrupt status flags.
*
* @param base GPIO peripheral base pointer (GPIOA, GPIOB, GPIOC, and so on.)
* @param mask GPIO pin number macro
*/
void GPIO_ClearPinsInterruptFlags(GPIO_Type *base, uint32_t mask);
#if defined(FSL_FEATURE_GPIO_HAS_ATTRIBUTE_CHECKER) && FSL_FEATURE_GPIO_HAS_ATTRIBUTE_CHECKER
/*!
* @brief The GPIO module supports a device-specific number of data ports, organized as 32-bit
* words. Each 32-bit data port includes a GACR register, which defines the byte-level
* attributes required for a successful access to the GPIO programming model. The attribute controls for the 4 data
* bytes in the GACR follow a standard little endian
* data convention.
*
* @param base GPIO peripheral base pointer (GPIOA, GPIOB, GPIOC, and so on.)
* @param mask GPIO pin number macro
*/
void GPIO_CheckAttributeBytes(GPIO_Type *base, gpio_checker_attribute_t attribute);
#endif
/*@}*/
/*! @} */
/*!
* @addtogroup fgpio_driver
* @{
*/
/*
* Introduces the FGPIO feature.
*
* The FGPIO features are only support on some Kinetis MCUs. The FGPIO registers are aliased to the IOPORT
* interface. Accesses via the IOPORT interface occur in parallel with any instruction fetches and
* complete in a single cycle. This aliased Fast GPIO memory map is called FGPIO.
*/
#if defined(FSL_FEATURE_SOC_FGPIO_COUNT) && FSL_FEATURE_SOC_FGPIO_COUNT
/*! @name FGPIO Configuration */
/*@{*/
/*!
* @brief Initializes the FGPIO peripheral.
*
* This function ungates the FGPIO clock.
*
* @param base FGPIO peripheral base pointer (FGPIOA, FGPIOB, FGPIOC, and so on.)
*/
void FGPIO_Init(FGPIO_Type *base);
/*!
* @brief Initializes a FGPIO pin used by the board.
*
* To initialize the FGPIO driver, define a pin configuration, as either input or output, in the user file.
* Then, call the FGPIO_PinInit() function.
*
* This is an example to define an input pin or an output pin configuration:
* @code
* // Define a digital input pin configuration,
* gpio_pin_config_t config =
* {
* kGPIO_DigitalInput,
* 0,
* }
* //Define a digital output pin configuration,
* gpio_pin_config_t config =
* {
* kGPIO_DigitalOutput,
* 0,
* }
* @endcode
*
* @param base FGPIO peripheral base pointer (FGPIOA, FGPIOB, FGPIOC, and so on.)
* @param pin FGPIO port pin number
* @param config FGPIO pin configuration pointer
*/
void FGPIO_PinInit(FGPIO_Type *base, uint32_t pin, const gpio_pin_config_t *config);
/*@}*/
/*! @name FGPIO Output Operations */
/*@{*/
/*!
* @brief Sets the output level of the multiple FGPIO pins to the logic 1 or 0.
*
* @param base FGPIO peripheral base pointer (FGPIOA, FGPIOB, FGPIOC, and so on.)
* @param pin FGPIO pin number
* @param output FGPIOpin output logic level.
* - 0: corresponding pin output low-logic level.
* - 1: corresponding pin output high-logic level.
*/
static inline void FGPIO_WritePinOutput(FGPIO_Type *base, uint32_t pin, uint8_t output)
{
if (output == 0U)
{
base->PCOR = 1 << pin;
}
else
{
base->PSOR = 1 << pin;
}
}
/*!
* @brief Sets the output level of the multiple FGPIO pins to the logic 1.
*
* @param base FGPIO peripheral base pointer (FGPIOA, FGPIOB, FGPIOC, and so on.)
* @param mask FGPIO pin number macro
*/
static inline void FGPIO_SetPinsOutput(FGPIO_Type *base, uint32_t mask)
{
base->PSOR = mask;
}
/*!
* @brief Sets the output level of the multiple FGPIO pins to the logic 0.
*
* @param base FGPIO peripheral base pointer (FGPIOA, FGPIOB, FGPIOC, and so on.)
* @param mask FGPIO pin number macro
*/
static inline void FGPIO_ClearPinsOutput(FGPIO_Type *base, uint32_t mask)
{
base->PCOR = mask;
}
/*!
* @brief Reverses the current output logic of the multiple FGPIO pins.
*
* @param base FGPIO peripheral base pointer (FGPIOA, FGPIOB, FGPIOC, and so on.)
* @param mask FGPIO pin number macro
*/
static inline void FGPIO_TogglePinsOutput(FGPIO_Type *base, uint32_t mask)
{
base->PTOR = mask;
}
/*@}*/
/*! @name FGPIO Input Operations */
/*@{*/
/*!
* @brief Reads the current input value of the FGPIO port.
*
* @param base FGPIO peripheral base pointer (FGPIOA, FGPIOB, FGPIOC, and so on.)
* @param pin FGPIO pin number
* @retval FGPIO port input value
* - 0: corresponding pin input low-logic level.
* - 1: corresponding pin input high-logic level.
*/
static inline uint32_t FGPIO_ReadPinInput(FGPIO_Type *base, uint32_t pin)
{
return (((base->PDIR) >> pin) & 0x01U);
}
/*@}*/
/*! @name FGPIO Interrupt */
/*@{*/
/*!
* @brief Reads the FGPIO port interrupt status flag.
*
* If a pin is configured to generate the DMA request, the corresponding flag
* is cleared automatically at the completion of the requested DMA transfer.
* Otherwise, the flag remains set until a logic one is written to that flag.
* If configured for a level-sensitive interrupt that remains asserted, the flag
* is set again immediately.
*
* @param base FGPIO peripheral base pointer (FGPIOA, FGPIOB, FGPIOC, and so on.)
* @retval The current FGPIO port interrupt status flags, for example, 0x00010001 means the
* pin 0 and 17 have the interrupt.
*/
uint32_t FGPIO_GetPinsInterruptFlags(FGPIO_Type *base);
/*!
* @brief Clears the multiple FGPIO pin interrupt status flag.
*
* @param base FGPIO peripheral base pointer (FGPIOA, FGPIOB, FGPIOC, and so on.)
* @param mask FGPIO pin number macro
*/
void FGPIO_ClearPinsInterruptFlags(FGPIO_Type *base, uint32_t mask);
#if defined(FSL_FEATURE_GPIO_HAS_ATTRIBUTE_CHECKER) && FSL_FEATURE_GPIO_HAS_ATTRIBUTE_CHECKER
/*!
* @brief The FGPIO module supports a device-specific number of data ports, organized as 32-bit
* words. Each 32-bit data port includes a GACR register, which defines the byte-level
* attributes required for a successful access to the GPIO programming model. The attribute controls for the 4 data
* bytes in the GACR follow a standard little endian
* data convention.
*
* @param base FGPIO peripheral base pointer (FGPIOA, FGPIOB, FGPIOC, and so on.)
* @param mask FGPIO pin number macro
*/
void FGPIO_CheckAttributeBytes(FGPIO_Type *base, gpio_checker_attribute_t attribute);
#endif
/*@}*/
#endif /* FSL_FEATURE_SOC_FGPIO_COUNT */
#if defined(__cplusplus)
}
#endif
/*!
* @}
*/
#endif /* _FSL_GPIO_H_*/

View File

@ -0,0 +1,226 @@
/*
* Copyright (c) 2015, Freescale Semiconductor, Inc.
* Copyright 2016-2017 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include "fsl_intmux.h"
/*******************************************************************************
* Definitions
******************************************************************************/
/*******************************************************************************
* Prototypes
******************************************************************************/
/*!
* @brief Get instance number for INTMUX.
*
* @param base INTMUX peripheral base address.
*/
static uint32_t INTMUX_GetInstance(INTMUX_Type *base);
#if !(defined(FSL_FEATURE_INTMUX_DIRECTION_OUT) && FSL_FEATURE_INTMUX_DIRECTION_OUT)
/*!
* @brief Handle INTMUX all channels IRQ.
*
* The handler reads the INTMUX channel's active vector register. This returns the offset
* from the start of the vector table to the vector for the INTMUX channel's highest priority
* pending source interrupt. After a check for spurious interrupts (an offset of 0), the
* function address at the vector offset is read and jumped to.
*
* @param base INTMUX peripheral base address.
* @param channel INTMUX channel number.
*/
static void INTMUX_CommonIRQHandler(INTMUX_Type *intmuxBase, uint32_t channel);
#endif
/*******************************************************************************
* Variables
******************************************************************************/
/*! @brief Array to map INTMUX instance number to base pointer. */
static INTMUX_Type *const s_intmuxBases[] = INTMUX_BASE_PTRS;
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
/*! @brief Array to map INTMUX instance number to clock name. */
static const clock_ip_name_t s_intmuxClockName[] = INTMUX_CLOCKS;
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
#if !(defined(FSL_FEATURE_INTMUX_DIRECTION_OUT) && FSL_FEATURE_INTMUX_DIRECTION_OUT)
/*! @brief Array to map INTMUX instance number to IRQ number. */
static const IRQn_Type s_intmuxIRQNumber[][FSL_FEATURE_INTMUX_CHANNEL_COUNT] = INTMUX_IRQS;
#endif /* FSL_FEATURE_INTMUX_DIRECTION_OUT */
/*******************************************************************************
* Code
******************************************************************************/
static uint32_t INTMUX_GetInstance(INTMUX_Type *base)
{
uint32_t instance;
/* Find the instance index from base address mappings. */
for (instance = 0; instance < ARRAY_SIZE(s_intmuxBases); instance++)
{
if (s_intmuxBases[instance] == base)
{
break;
}
}
assert(instance < ARRAY_SIZE(s_intmuxBases));
return instance;
}
#if !(defined(FSL_FEATURE_INTMUX_DIRECTION_OUT) && FSL_FEATURE_INTMUX_DIRECTION_OUT)
static void INTMUX_CommonIRQHandler(INTMUX_Type *intmuxBase, uint32_t channel)
{
uint32_t pendingIrqOffset;
pendingIrqOffset = intmuxBase->CHANNEL[channel].CHn_VEC;
if (pendingIrqOffset)
{
#if defined(__riscv)
extern uint32_t __user_vector[];
uint32_t isr = __user_vector[pendingIrqOffset / 4 - 48 + 32];
#else
uint32_t isr = *(uint32_t *)(SCB->VTOR + pendingIrqOffset);
#endif
((void (*)(void))isr)();
}
}
#endif /* FSL_FEATURE_INTMUX_DIRECTION_OUT */
void INTMUX_Init(INTMUX_Type *base)
{
uint32_t channel;
uint32_t instance = INTMUX_GetInstance(base);
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
/* Enable clock gate. */
CLOCK_EnableClock(s_intmuxClockName[instance]);
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
/* Reset all channels and enable NVIC vectors for all INTMUX channels. */
for (channel = 0; channel < FSL_FEATURE_INTMUX_CHANNEL_COUNT; channel++)
{
INTMUX_ResetChannel(base, channel);
#if !(defined(FSL_FEATURE_INTMUX_DIRECTION_OUT) && FSL_FEATURE_INTMUX_DIRECTION_OUT)
EnableIRQ(s_intmuxIRQNumber[instance][channel]);
#endif /* FSL_FEATURE_INTMUX_DIRECTION_OUT */
}
}
void INTMUX_Deinit(INTMUX_Type *base)
{
uint32_t channel;
uint32_t instance = INTMUX_GetInstance(base);
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
/* Disable clock gate. */
CLOCK_DisableClock(s_intmuxClockName[instance]);
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
/* Disable NVIC vectors for all of the INTMUX channels. */
for (channel = 0; channel < FSL_FEATURE_INTMUX_CHANNEL_COUNT; channel++)
{
#if !(defined(FSL_FEATURE_INTMUX_DIRECTION_OUT) && FSL_FEATURE_INTMUX_DIRECTION_OUT)
DisableIRQ(s_intmuxIRQNumber[instance][channel]);
#endif /* FSL_FEATURE_INTMUX_DIRECTION_OUT */
}
}
#if !(defined(FSL_FEATURE_INTMUX_DIRECTION_OUT) && FSL_FEATURE_INTMUX_DIRECTION_OUT)
#if defined(INTMUX0)
void INTMUX0_0_DriverIRQHandler(void)
{
INTMUX_CommonIRQHandler(INTMUX0, 0);
}
void INTMUX0_1_DriverIRQHandler(void)
{
INTMUX_CommonIRQHandler(INTMUX0, 1);
}
void INTMUX0_2_DriverIRQHandler(void)
{
INTMUX_CommonIRQHandler(INTMUX0, 2);
}
void INTMUX0_3_DriverIRQHandler(void)
{
INTMUX_CommonIRQHandler(INTMUX0, 3);
}
#if defined(FSL_FEATURE_INTMUX_CHANNEL_COUNT) && (FSL_FEATURE_INTMUX_CHANNEL_COUNT > 4U)
void INTMUX0_4_DriverIRQHandler(void)
{
INTMUX_CommonIRQHandler(INTMUX0, 4);
}
void INTMUX0_5_DriverIRQHandler(void)
{
INTMUX_CommonIRQHandler(INTMUX0, 5);
}
void INTMUX0_6_DriverIRQHandler(void)
{
INTMUX_CommonIRQHandler(INTMUX0, 6);
}
void INTMUX0_7_DriverIRQHandler(void)
{
INTMUX_CommonIRQHandler(INTMUX0, 7);
}
#endif /* FSL_FEATURE_INTMUX_CHANNEL_COUNT */
#endif
#if defined(INTMUX1)
void INTMUX1_0_DriverIRQHandler(void)
{
INTMUX_CommonIRQHandler(INTMUX1, 0);
}
void INTMUX1_1_DriverIRQHandler(void)
{
INTMUX_CommonIRQHandler(INTMUX1, 1);
}
void INTMUX1_2_DriverIRQHandler(void)
{
INTMUX_CommonIRQHandler(INTMUX1, 2);
}
void INTMUX1_3_DriverIRQHandler(void)
{
INTMUX_CommonIRQHandler(INTMUX1, 3);
}
#if defined(FSL_FEATURE_INTMUX_CHANNEL_COUNT) && (FSL_FEATURE_INTMUX_CHANNEL_COUNT > 4U)
void INTMUX1_4_DriverIRQHandler(void)
{
INTMUX_CommonIRQHandler(INTMUX1, 4);
}
void INTMUX1_5_DriverIRQHandler(void)
{
INTMUX_CommonIRQHandler(INTMUX1, 5);
}
void INTMUX1_6_DriverIRQHandler(void)
{
INTMUX_CommonIRQHandler(INTMUX1, 6);
}
void INTMUX1_7_DriverIRQHandler(void)
{
INTMUX_CommonIRQHandler(INTMUX1, 7);
}
#endif /* FSL_FEATURE_INTMUX_CHANNEL_COUNT */
#endif /* INTMUX1 */
#endif /* FSL_FEATURE_INTMUX_DIRECTION_OUT */

View File

@ -0,0 +1,164 @@
/*
* Copyright (c) 2015, Freescale Semiconductor, Inc.
* Copyright 2016-2017 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef _FSL_INTMUX_H_
#define _FSL_INTMUX_H_
#include "fsl_common.h"
/*!
* @addtogroup intmux
* @{
*/
/*******************************************************************************
* Definitions
******************************************************************************/
/*! @name Driver version */
/*@{*/
/*!< Version 2.0.1. */
#define FSL_INTMUX_DRIVER_VERSION (MAKE_VERSION(2, 0, 1))
/*@}*/
/*! @brief INTMUX channel logic mode. */
typedef enum _intmux_channel_logic_mode
{
kINTMUX_ChannelLogicOR = 0x0U, /*!< Logic OR all enabled interrupt inputs */
kINTMUX_ChannelLogicAND, /*!< Logic AND all enabled interrupt inputs */
} intmux_channel_logic_mode_t;
/*******************************************************************************
* API
******************************************************************************/
#if defined(__cplusplus)
extern "C" {
#endif
/*! @name Initialization and deinitialization */
/*@{*/
/*!
* @brief Initializes the INTMUX module.
*
* This function enables the clock gate for the specified INTMUX. It then resets all channels, so that no
* interrupt sources are routed and the logic mode is set to default of #kINTMUX_ChannelLogicOR.
* Finally, the NVIC vectors for all the INTMUX output channels are enabled.
*
* @param base INTMUX peripheral base address.
*/
void INTMUX_Init(INTMUX_Type *base);
/*!
* @brief Deinitializes an INTMUX instance for operation.
*
* The clock gate for the specified INTMUX is disabled and the NVIC vectors for all channels are disabled.
*
* @param base INTMUX peripheral base address.
*/
void INTMUX_Deinit(INTMUX_Type *base);
/*!
* @brief Resets an INTMUX channel.
*
* Sets all register values in the specified channel to their reset value. This function disables all interrupt
* sources for the channel.
*
* @param base INTMUX peripheral base address.
* @param channel The INTMUX channel number.
*/
static inline void INTMUX_ResetChannel(INTMUX_Type *base, uint32_t channel)
{
assert(channel < FSL_FEATURE_INTMUX_CHANNEL_COUNT);
base->CHANNEL[channel].CHn_CSR |= INTMUX_CHn_CSR_RST_MASK;
}
/*!
* @brief Sets the logic mode for an INTMUX channel.
*
* INTMUX channels can be configured to use one of the two logic modes that control how pending interrupt sources
* on the channel trigger the output interrupt.
* - #kINTMUX_ChannelLogicOR means any source pending triggers the output interrupt.
* - #kINTMUX_ChannelLogicAND means all selected sources on the channel must be pending before the channel
* output interrupt triggers.
*
* @param base INTMUX peripheral base address.
* @param channel The INTMUX channel number.
* @param logic The INTMUX channel logic mode.
*/
static inline void INTMUX_SetChannelMode(INTMUX_Type *base, uint32_t channel, intmux_channel_logic_mode_t logic)
{
assert(channel < FSL_FEATURE_INTMUX_CHANNEL_COUNT);
base->CHANNEL[channel].CHn_CSR = INTMUX_CHn_CSR_AND(logic);
}
/*@}*/
/*! @name Sources */
/*@{*/
/*!
* @brief Enables an interrupt source on an INTMUX channel.
*
* @param base INTMUX peripheral base address.
* @param channel Index of the INTMUX channel on which the specified interrupt is enabled.
* @param irq Interrupt to route to the specified INTMUX channel. The interrupt must be an INTMUX source.
*/
static inline void INTMUX_EnableInterrupt(INTMUX_Type *base, uint32_t channel, IRQn_Type irq)
{
assert(channel < FSL_FEATURE_INTMUX_CHANNEL_COUNT);
assert(irq >= FSL_FEATURE_INTMUX_IRQ_START_INDEX);
base->CHANNEL[channel].CHn_IER_31_0 |= (1U << ((uint32_t)irq - FSL_FEATURE_INTMUX_IRQ_START_INDEX));
}
/*!
* @brief Disables an interrupt source on an INTMUX channel.
*
* @param base INTMUX peripheral base address.
* @param channel Index of the INTMUX channel on which the specified interrupt is disabled.
* @param irq Interrupt number. The interrupt must be an INTMUX source.
*/
static inline void INTMUX_DisableInterrupt(INTMUX_Type *base, uint32_t channel, IRQn_Type irq)
{
assert(channel < FSL_FEATURE_INTMUX_CHANNEL_COUNT);
assert(irq >= FSL_FEATURE_INTMUX_IRQ_START_INDEX);
base->CHANNEL[channel].CHn_IER_31_0 &= ~(1U << ((uint32_t)irq - FSL_FEATURE_INTMUX_IRQ_START_INDEX));
}
/*@}*/
/*! @name Status */
/*@{*/
/*!
* @brief Gets INTMUX pending interrupt sources for a specific channel.
*
* @param base INTMUX peripheral base address.
* @param channel The INTMUX channel number.
* @return The mask of pending interrupt bits. Bit[n] set means INTMUX source n is pending.
*/
static inline uint32_t INTMUX_GetChannelPendingSources(INTMUX_Type *base, uint32_t channel)
{
assert(channel < FSL_FEATURE_INTMUX_CHANNEL_COUNT);
return base->CHANNEL[channel].CHn_IPR_31_0;
}
/*@}*/
#if defined(__cplusplus)
}
#endif
/*! @} */
#endif /* _FSL_INTMUX_H_ */

View File

@ -0,0 +1,380 @@
/*
* Copyright (c) 2015, Freescale Semiconductor, Inc.
* Copyright 2016-2017 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include "fsl_llwu.h"
#if (defined(FSL_FEATURE_LLWU_HAS_EXTERNAL_PIN) && FSL_FEATURE_LLWU_HAS_EXTERNAL_PIN)
void LLWU_SetExternalWakeupPinMode(LLWU_Type *base, uint32_t pinIndex, llwu_external_pin_mode_t pinMode)
{
#if (defined(FSL_FEATURE_LLWU_REG_BITWIDTH) && (FSL_FEATURE_LLWU_REG_BITWIDTH == 32))
volatile uint32_t *regBase;
uint32_t regOffset;
uint32_t reg;
switch (pinIndex >> 4U)
{
case 0U:
regBase = &base->PE1;
break;
#if (defined(FSL_FEATURE_LLWU_HAS_EXTERNAL_PIN) && (FSL_FEATURE_LLWU_HAS_EXTERNAL_PIN > 16))
case 1U:
regBase = &base->PE2;
break;
#endif
default:
regBase = NULL;
break;
}
#else
volatile uint8_t *regBase;
uint8_t regOffset;
uint8_t reg;
switch (pinIndex >> 2U)
{
case 0U:
regBase = &base->PE1;
break;
case 1U:
regBase = &base->PE2;
break;
#if (defined(FSL_FEATURE_LLWU_HAS_EXTERNAL_PIN) && (FSL_FEATURE_LLWU_HAS_EXTERNAL_PIN > 8))
case 2U:
regBase = &base->PE3;
break;
#endif
#if (defined(FSL_FEATURE_LLWU_HAS_EXTERNAL_PIN) && (FSL_FEATURE_LLWU_HAS_EXTERNAL_PIN > 12))
case 3U:
regBase = &base->PE4;
break;
#endif
#if (defined(FSL_FEATURE_LLWU_HAS_EXTERNAL_PIN) && (FSL_FEATURE_LLWU_HAS_EXTERNAL_PIN > 16))
case 4U:
regBase = &base->PE5;
break;
#endif
#if (defined(FSL_FEATURE_LLWU_HAS_EXTERNAL_PIN) && (FSL_FEATURE_LLWU_HAS_EXTERNAL_PIN > 20))
case 5U:
regBase = &base->PE6;
break;
#endif
#if (defined(FSL_FEATURE_LLWU_HAS_EXTERNAL_PIN) && (FSL_FEATURE_LLWU_HAS_EXTERNAL_PIN > 24))
case 6U:
regBase = &base->PE7;
break;
#endif
#if (defined(FSL_FEATURE_LLWU_HAS_EXTERNAL_PIN) && (FSL_FEATURE_LLWU_HAS_EXTERNAL_PIN > 28))
case 7U:
regBase = &base->PE8;
break;
#endif
default:
regBase = NULL;
break;
}
#endif /* FSL_FEATURE_LLWU_REG_BITWIDTH == 32 */
if (regBase)
{
reg = *regBase;
#if (defined(FSL_FEATURE_LLWU_REG_BITWIDTH) && (FSL_FEATURE_LLWU_REG_BITWIDTH == 32))
regOffset = ((pinIndex & 0x0FU) << 1U);
#else
regOffset = ((pinIndex & 0x03U) << 1U);
#endif
reg &= ~(0x3U << regOffset);
reg |= ((uint32_t)pinMode << regOffset);
*regBase = reg;
}
}
bool LLWU_GetExternalWakeupPinFlag(LLWU_Type *base, uint32_t pinIndex)
{
#if (defined(FSL_FEATURE_LLWU_REG_BITWIDTH) && (FSL_FEATURE_LLWU_REG_BITWIDTH == 32))
return (bool)(base->PF & (1U << pinIndex));
#else
volatile uint8_t *regBase;
switch (pinIndex >> 3U)
{
#if (defined(FSL_FEATURE_LLWU_HAS_PF) && FSL_FEATURE_LLWU_HAS_PF)
case 0U:
regBase = &base->PF1;
break;
#if (defined(FSL_FEATURE_LLWU_HAS_EXTERNAL_PIN) && (FSL_FEATURE_LLWU_HAS_EXTERNAL_PIN > 8))
case 1U:
regBase = &base->PF2;
break;
#endif /* FSL_FEATURE_LLWU_HAS_EXTERNAL_PIN */
#if (defined(FSL_FEATURE_LLWU_HAS_EXTERNAL_PIN) && (FSL_FEATURE_LLWU_HAS_EXTERNAL_PIN > 16))
case 2U:
regBase = &base->PF3;
break;
#endif /* FSL_FEATURE_LLWU_HAS_EXTERNAL_PIN */
#if (defined(FSL_FEATURE_LLWU_HAS_EXTERNAL_PIN) && (FSL_FEATURE_LLWU_HAS_EXTERNAL_PIN > 24))
case 3U:
regBase = &base->PF4;
break;
#endif /* FSL_FEATURE_LLWU_HAS_EXTERNAL_PIN */
#else
case 0U:
regBase = &base->F1;
break;
#if (defined(FSL_FEATURE_LLWU_HAS_EXTERNAL_PIN) && (FSL_FEATURE_LLWU_HAS_EXTERNAL_PIN > 8))
case 1U:
regBase = &base->F2;
break;
#endif /* FSL_FEATURE_LLWU_HAS_EXTERNAL_PIN */
#if (defined(FSL_FEATURE_LLWU_HAS_EXTERNAL_PIN) && (FSL_FEATURE_LLWU_HAS_EXTERNAL_PIN > 16))
case 2U:
regBase = &base->F3;
break;
#endif /* FSL_FEATURE_LLWU_HAS_EXTERNAL_PIN */
#if (defined(FSL_FEATURE_LLWU_HAS_EXTERNAL_PIN) && (FSL_FEATURE_LLWU_HAS_EXTERNAL_PIN > 24))
case 3U:
regBase = &base->F4;
break;
#endif /* FSL_FEATURE_LLWU_HAS_EXTERNAL_PIN */
#endif /* FSL_FEATURE_LLWU_HAS_PF */
default:
regBase = NULL;
break;
}
if (regBase)
{
return (bool)(*regBase & (1U << pinIndex % 8));
}
else
{
return false;
}
#endif /* FSL_FEATURE_LLWU_REG_BITWIDTH */
}
void LLWU_ClearExternalWakeupPinFlag(LLWU_Type *base, uint32_t pinIndex)
{
#if (defined(FSL_FEATURE_LLWU_REG_BITWIDTH) && (FSL_FEATURE_LLWU_REG_BITWIDTH == 32))
base->PF = (1U << pinIndex);
#else
volatile uint8_t *regBase;
switch (pinIndex >> 3U)
{
#if (defined(FSL_FEATURE_LLWU_HAS_PF) && FSL_FEATURE_LLWU_HAS_PF)
case 0U:
regBase = &base->PF1;
break;
#if (defined(FSL_FEATURE_LLWU_HAS_EXTERNAL_PIN) && (FSL_FEATURE_LLWU_HAS_EXTERNAL_PIN > 8))
case 1U:
regBase = &base->PF2;
break;
#endif /* FSL_FEATURE_LLWU_HAS_EXTERNAL_PIN */
#if (defined(FSL_FEATURE_LLWU_HAS_EXTERNAL_PIN) && (FSL_FEATURE_LLWU_HAS_EXTERNAL_PIN > 16))
case 2U:
regBase = &base->PF3;
break;
#endif /* FSL_FEATURE_LLWU_HAS_EXTERNAL_PIN */
#if (defined(FSL_FEATURE_LLWU_HAS_EXTERNAL_PIN) && (FSL_FEATURE_LLWU_HAS_EXTERNAL_PIN > 24))
case 3U:
regBase = &base->PF4;
break;
#endif /* FSL_FEATURE_LLWU_HAS_EXTERNAL_PIN */
#else
case 0U:
regBase = &base->F1;
break;
#if (defined(FSL_FEATURE_LLWU_HAS_EXTERNAL_PIN) && (FSL_FEATURE_LLWU_HAS_EXTERNAL_PIN > 8))
case 1U:
regBase = &base->F2;
break;
#endif /* FSL_FEATURE_LLWU_HAS_EXTERNAL_PIN */
#if (defined(FSL_FEATURE_LLWU_HAS_EXTERNAL_PIN) && (FSL_FEATURE_LLWU_HAS_EXTERNAL_PIN > 16))
case 2U:
regBase = &base->F3;
break;
#endif /* FSL_FEATURE_LLWU_HAS_EXTERNAL_PIN */
#if (defined(FSL_FEATURE_LLWU_HAS_EXTERNAL_PIN) && (FSL_FEATURE_LLWU_HAS_EXTERNAL_PIN > 24))
case 3U:
regBase = &base->F4;
break;
#endif /* FSL_FEATURE_LLWU_HAS_EXTERNAL_PIN */
#endif /* FSL_FEATURE_LLWU_HAS_PF */
default:
regBase = NULL;
break;
}
if (regBase)
{
*regBase = (1U << pinIndex % 8U);
}
#endif /* FSL_FEATURE_LLWU_REG_BITWIDTH */
}
#endif /* FSL_FEATURE_LLWU_HAS_EXTERNAL_PIN */
#if (defined(FSL_FEATURE_LLWU_HAS_PIN_FILTER) && FSL_FEATURE_LLWU_HAS_PIN_FILTER)
void LLWU_SetPinFilterMode(LLWU_Type *base, uint32_t filterIndex, llwu_external_pin_filter_mode_t filterMode)
{
#if (defined(FSL_FEATURE_LLWU_REG_BITWIDTH) && (FSL_FEATURE_LLWU_REG_BITWIDTH == 32))
base->FILT = ((base->FILT) & ~((LLWU_FILT_FILTSEL1_MASK | LLWU_FILT_FILTE1_MASK) << ((filterIndex - 1U) * 8U))) |
((LLWU_FILT_FILTSEL1(filterMode.pinIndex) | LLWU_FILT_FILTE1(filterMode.filterMode))
<< ((filterIndex - 1U) * 8U)) |
LLWU_FILT_FILTF1_MASK /* W1C to clear the FILTF flag bit. */
;
#else
volatile uint8_t *regBase;
switch (filterIndex)
{
case 1U:
regBase = &base->FILT1;
break;
#if (defined(FSL_FEATURE_LLWU_HAS_PIN_FILTER) && (FSL_FEATURE_LLWU_HAS_PIN_FILTER > 1))
case 2U:
regBase = &base->FILT2;
break;
#endif /* FSL_FEATURE_LLWU_HAS_PIN_FILTER */
#if (defined(FSL_FEATURE_LLWU_HAS_PIN_FILTER) && (FSL_FEATURE_LLWU_HAS_PIN_FILTER > 2))
case 3U:
regBase = &base->FILT3;
break;
#endif /* FSL_FEATURE_LLWU_HAS_PIN_FILTER */
#if (defined(FSL_FEATURE_LLWU_HAS_PIN_FILTER) && (FSL_FEATURE_LLWU_HAS_PIN_FILTER > 3))
case 4U:
regBase = &base->FILT4;
break;
#endif /* FSL_FEATURE_LLWU_HAS_PIN_FILTER */
default:
regBase = NULL;
break;
}
if (NULL != regBase)
{
*regBase = (*regBase & ~(LLWU_FILT1_FILTSEL_MASK | LLWU_FILT1_FILTE_MASK)) |
LLWU_FILT1_FILTSEL(filterMode.pinIndex) | LLWU_FILT1_FILTE(filterMode.filterMode) |
LLWU_FILT1_FILTF_MASK /* W1C to clear the FILTF flag bit. */
;
}
#endif /* FSL_FEATURE_LLWU_REG_BITWIDTH */
}
bool LLWU_GetPinFilterFlag(LLWU_Type *base, uint32_t filterIndex)
{
#if (defined(FSL_FEATURE_LLWU_REG_BITWIDTH) && (FSL_FEATURE_LLWU_REG_BITWIDTH == 32))
return (bool)(base->FILT & (1U << (filterIndex * 8U - 1)));
#else
bool status = false;
switch (filterIndex)
{
case 1:
status = (base->FILT1 & LLWU_FILT1_FILTF_MASK);
break;
#if (defined(FSL_FEATURE_LLWU_HAS_PIN_FILTER) && (FSL_FEATURE_LLWU_HAS_PIN_FILTER > 1))
case 2:
status = (base->FILT2 & LLWU_FILT2_FILTF_MASK);
break;
#endif /* FSL_FEATURE_LLWU_HAS_PIN_FILTER */
#if (defined(FSL_FEATURE_LLWU_HAS_PIN_FILTER) && (FSL_FEATURE_LLWU_HAS_PIN_FILTER > 2))
case 3:
status = (base->FILT3 & LLWU_FILT3_FILTF_MASK);
break;
#endif /* FSL_FEATURE_LLWU_HAS_PIN_FILTER */
#if (defined(FSL_FEATURE_LLWU_HAS_PIN_FILTER) && (FSL_FEATURE_LLWU_HAS_PIN_FILTER > 3))
case 4:
status = (base->FILT4 & LLWU_FILT4_FILTF_MASK);
break;
#endif /* FSL_FEATURE_LLWU_HAS_PIN_FILTER */
default:
break;
}
return status;
#endif /* FSL_FEATURE_LLWU_REG_BITWIDTH */
}
void LLWU_ClearPinFilterFlag(LLWU_Type *base, uint32_t filterIndex)
{
#if (defined(FSL_FEATURE_LLWU_REG_BITWIDTH) && (FSL_FEATURE_LLWU_REG_BITWIDTH == 32))
uint32_t reg;
reg = base->FILT;
switch (filterIndex)
{
case 1:
reg |= LLWU_FILT_FILTF1_MASK;
break;
#if (defined(FSL_FEATURE_LLWU_HAS_PIN_FILTER) && (FSL_FEATURE_LLWU_HAS_PIN_FILTER > 1))
case 2:
reg |= LLWU_FILT_FILTF2_MASK;
break;
#endif /* FSL_FEATURE_LLWU_HAS_PIN_FILTER > 1 */
#if (defined(FSL_FEATURE_LLWU_HAS_PIN_FILTER) && (FSL_FEATURE_LLWU_HAS_PIN_FILTER > 2))
case 3:
reg |= LLWU_FILT_FILTF3_MASK;
break;
#endif /* FSL_FEATURE_LLWU_HAS_PIN_FILTER > 2 */
#if (defined(FSL_FEATURE_LLWU_HAS_PIN_FILTER) && (FSL_FEATURE_LLWU_HAS_PIN_FILTER > 3))
case 4:
reg |= LLWU_FILT_FILTF4_MASK;
break;
#endif /* FSL_FEATURE_LLWU_HAS_PIN_FILTER > 3 */
default:
break;
}
base->FILT = reg;
#else
volatile uint8_t *regBase;
uint8_t reg;
switch (filterIndex)
{
case 1:
regBase = &base->FILT1;
break;
#if (defined(FSL_FEATURE_LLWU_HAS_PIN_FILTER) && (FSL_FEATURE_LLWU_HAS_PIN_FILTER > 1))
case 2:
regBase = &base->FILT2;
break;
#endif /* FSL_FEATURE_LLWU_HAS_PIN_FILTER */
#if (defined(FSL_FEATURE_LLWU_HAS_PIN_FILTER) && (FSL_FEATURE_LLWU_HAS_PIN_FILTER > 2))
case 3:
regBase = &base->FILT3;
break;
#endif /* FSL_FEATURE_LLWU_HAS_PIN_FILTER */
#if (defined(FSL_FEATURE_LLWU_HAS_PIN_FILTER) && (FSL_FEATURE_LLWU_HAS_PIN_FILTER > 3))
case 4:
regBase = &base->FILT4;
break;
#endif /* FSL_FEATURE_LLWU_HAS_PIN_FILTER */
default:
regBase = NULL;
break;
}
if (regBase)
{
reg = *regBase;
reg |= LLWU_FILT1_FILTF_MASK;
*regBase = reg;
}
#endif /* FSL_FEATURE_LLWU_REG_BITWIDTH */
}
#endif /* FSL_FEATURE_LLWU_HAS_PIN_FILTER */
#if (defined(FSL_FEATURE_LLWU_HAS_RESET_ENABLE) && FSL_FEATURE_LLWU_HAS_RESET_ENABLE)
void LLWU_SetResetPinMode(LLWU_Type *base, bool pinEnable, bool enableInLowLeakageMode)
{
uint8_t reg;
reg = base->RST;
reg &= ~(LLWU_RST_LLRSTE_MASK | LLWU_RST_RSTFILT_MASK);
reg |=
(((uint32_t)pinEnable << LLWU_RST_LLRSTE_SHIFT) | ((uint32_t)enableInLowLeakageMode << LLWU_RST_RSTFILT_SHIFT));
base->RST = reg;
}
#endif /* FSL_FEATURE_LLWU_HAS_RESET_ENABLE */

View File

@ -0,0 +1,303 @@
/*
* Copyright (c) 2015, Freescale Semiconductor, Inc.
* Copyright 2016-2017 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef _FSL_LLWU_H_
#define _FSL_LLWU_H_
#include "fsl_common.h"
/*! @addtogroup llwu */
/*! @{ */
/*******************************************************************************
* Definitions
******************************************************************************/
/*! @name Driver version */
/*@{*/
/*! @brief LLWU driver version 2.0.1. */
#define FSL_LLWU_DRIVER_VERSION (MAKE_VERSION(2, 0, 1))
/*@}*/
/*!
* @brief External input pin control modes
*/
typedef enum _llwu_external_pin_mode
{
kLLWU_ExternalPinDisable = 0U, /*!< Pin disabled as a wakeup input. */
kLLWU_ExternalPinRisingEdge = 1U, /*!< Pin enabled with the rising edge detection. */
kLLWU_ExternalPinFallingEdge = 2U, /*!< Pin enabled with the falling edge detection.*/
kLLWU_ExternalPinAnyEdge = 3U /*!< Pin enabled with any change detection. */
} llwu_external_pin_mode_t;
/*!
* @brief Digital filter control modes
*/
typedef enum _llwu_pin_filter_mode
{
kLLWU_PinFilterDisable = 0U, /*!< Filter disabled. */
kLLWU_PinFilterRisingEdge = 1U, /*!< Filter positive edge detection.*/
kLLWU_PinFilterFallingEdge = 2U, /*!< Filter negative edge detection.*/
kLLWU_PinFilterAnyEdge = 3U /*!< Filter any edge detection. */
} llwu_pin_filter_mode_t;
#if (defined(FSL_FEATURE_LLWU_HAS_VERID) && FSL_FEATURE_LLWU_HAS_VERID)
/*!
* @brief IP version ID definition.
*/
typedef struct _llwu_version_id
{
uint16_t feature; /*!< A feature specification number. */
uint8_t minor; /*!< The minor version number. */
uint8_t major; /*!< The major version number. */
} llwu_version_id_t;
#endif /* FSL_FEATURE_LLWU_HAS_VERID */
#if (defined(FSL_FEATURE_LLWU_HAS_PARAM) && FSL_FEATURE_LLWU_HAS_PARAM)
/*!
* @brief IP parameter definition.
*/
typedef struct _llwu_param
{
uint8_t filters; /*!< A number of the pin filter. */
uint8_t dmas; /*!< A number of the wakeup DMA. */
uint8_t modules; /*!< A number of the wakeup module. */
uint8_t pins; /*!< A number of the wake up pin. */
} llwu_param_t;
#endif /* FSL_FEATURE_LLWU_HAS_PARAM */
#if (defined(FSL_FEATURE_LLWU_HAS_PIN_FILTER) && FSL_FEATURE_LLWU_HAS_PIN_FILTER)
/*!
* @brief An external input pin filter control structure
*/
typedef struct _llwu_external_pin_filter_mode
{
uint32_t pinIndex; /*!< A pin number */
llwu_pin_filter_mode_t filterMode; /*!< Filter mode */
} llwu_external_pin_filter_mode_t;
#endif /* FSL_FEATURE_LLWU_HAS_PIN_FILTER */
/*******************************************************************************
* API
******************************************************************************/
#if defined(__cplusplus)
extern "C" {
#endif
/*!
* @name Low-Leakage Wakeup Unit Control APIs
* @{
*/
#if (defined(FSL_FEATURE_LLWU_HAS_VERID) && FSL_FEATURE_LLWU_HAS_VERID)
/*!
* @brief Gets the LLWU version ID.
*
* This function gets the LLWU version ID, including the major version number,
* the minor version number, and the feature specification number.
*
* @param base LLWU peripheral base address.
* @param versionId A pointer to the version ID structure.
*/
static inline void LLWU_GetVersionId(LLWU_Type *base, llwu_version_id_t *versionId)
{
*((uint32_t *)versionId) = base->VERID;
}
#endif /* FSL_FEATURE_LLWU_HAS_VERID */
#if (defined(FSL_FEATURE_LLWU_HAS_PARAM) && FSL_FEATURE_LLWU_HAS_PARAM)
/*!
* @brief Gets the LLWU parameter.
*
* This function gets the LLWU parameter, including a wakeup pin number, a module
* number, a DMA number, and a pin filter number.
*
* @param base LLWU peripheral base address.
* @param param A pointer to the LLWU parameter structure.
*/
static inline void LLWU_GetParam(LLWU_Type *base, llwu_param_t *param)
{
*((uint32_t *)param) = base->PARAM;
}
#endif /* FSL_FEATURE_LLWU_HAS_PARAM */
#if (defined(FSL_FEATURE_LLWU_HAS_EXTERNAL_PIN) && FSL_FEATURE_LLWU_HAS_EXTERNAL_PIN)
/*!
* @brief Sets the external input pin source mode.
*
* This function sets the external input pin source mode that is used
* as a wake up source.
*
* @param base LLWU peripheral base address.
* @param pinIndex A pin index to be enabled as an external wakeup source starting from 1.
* @param pinMode A pin configuration mode defined in the llwu_external_pin_modes_t.
*/
void LLWU_SetExternalWakeupPinMode(LLWU_Type *base, uint32_t pinIndex, llwu_external_pin_mode_t pinMode);
/*!
* @brief Gets the external wakeup source flag.
*
* This function checks the external pin flag to detect whether the MCU is
* woken up by the specific pin.
*
* @param base LLWU peripheral base address.
* @param pinIndex A pin index, which starts from 1.
* @return True if the specific pin is a wakeup source.
*/
bool LLWU_GetExternalWakeupPinFlag(LLWU_Type *base, uint32_t pinIndex);
/*!
* @brief Clears the external wakeup source flag.
*
* This function clears the external wakeup source flag for a specific pin.
*
* @param base LLWU peripheral base address.
* @param pinIndex A pin index, which starts from 1.
*/
void LLWU_ClearExternalWakeupPinFlag(LLWU_Type *base, uint32_t pinIndex);
#endif /* FSL_FEATURE_LLWU_HAS_EXTERNAL_PIN */
#if (defined(FSL_FEATURE_LLWU_HAS_INTERNAL_MODULE) && FSL_FEATURE_LLWU_HAS_INTERNAL_MODULE)
/*!
* @brief Enables/disables the internal module source.
*
* This function enables/disables the internal module source mode that is used
* as a wake up source.
*
* @param base LLWU peripheral base address.
* @param moduleIndex A module index to be enabled as an internal wakeup source starting from 1.
* @param enable An enable or a disable setting
*/
static inline void LLWU_EnableInternalModuleInterruptWakup(LLWU_Type *base, uint32_t moduleIndex, bool enable)
{
if (enable)
{
base->ME |= 1U << moduleIndex;
}
else
{
base->ME &= ~(1U << moduleIndex);
}
}
#if (!(defined(FSL_FEATURE_LLWU_HAS_NO_INTERNAL_MODULE_WAKEUP_FLAG_REG) && \
FSL_FEATURE_LLWU_HAS_NO_INTERNAL_MODULE_WAKEUP_FLAG_REG))
/* Re-define the register which includes the internal wakeup module flag. */
#if (defined(FSL_FEATURE_LLWU_REG_BITWIDTH) && (FSL_FEATURE_LLWU_REG_BITWIDTH == 32)) /* 32-bit LLWU. */
#if (defined(FSL_FEATURE_LLWU_HAS_MF) && FSL_FEATURE_LLWU_HAS_MF)
#define INTERNAL_WAKEUP_MODULE_FLAG_REG MF
#else
#error "Unsupported internal module flag register."
#endif
#else /* 8-bit LLUW. */
#if (defined(FSL_FEATURE_LLWU_HAS_MF) && FSL_FEATURE_LLWU_HAS_MF)
#define INTERNAL_WAKEUP_MODULE_FLAG_REG MF5
#elif(defined(FSL_FEATURE_LLWU_HAS_PF) && FSL_FEATURE_LLWU_HAS_PF)
#define INTERNAL_WAKEUP_MODULE_FLAG_REG PF3
#elif(!(defined(FSL_FEATURE_LLWU_HAS_EXTERNAL_PIN) && (FSL_FEATURE_LLWU_HAS_EXTERNAL_PIN > 16)))
#define INTERNAL_WAKEUP_MODULE_FLAG_REG F3
#else
#error "Unsupported internal module flag register."
#endif
#endif /* FSL_FEATURE_LLWU_REG_BITWIDTH */
/*!
* @brief Gets the external wakeup source flag.
*
* This function checks the external pin flag to detect whether the system is
* woken up by the specific pin.
*
* @param base LLWU peripheral base address.
* @param moduleIndex A module index, which starts from 1.
* @return True if the specific pin is a wake up source.
*/
static inline bool LLWU_GetInternalWakeupModuleFlag(LLWU_Type *base, uint32_t moduleIndex)
{
return ((1U << moduleIndex) == (base->INTERNAL_WAKEUP_MODULE_FLAG_REG & (1U << moduleIndex)));
}
#endif /* FSL_FEATURE_LLWU_HAS_NO_INTERNAL_MODULE_WAKEUP_FLAG_REG */
#endif /* FSL_FEATURE_LLWU_HAS_INTERNAL_MODULE */
#if (defined(FSL_FEATURE_LLWU_HAS_DMA_ENABLE_REG) && FSL_FEATURE_LLWU_HAS_DMA_ENABLE_REG)
/*!
* @brief Enables/disables the internal module DMA wakeup source.
*
* This function enables/disables the internal DMA that is used as a wake up source.
*
* @param base LLWU peripheral base address.
* @param moduleIndex An internal module index which is used as a DMA request source, starting from 1.
* @param enable Enable or disable the DMA request source
*/
static inline void LLWU_EnableInternalModuleDmaRequestWakup(LLWU_Type *base, uint32_t moduleIndex, bool enable)
{
if (enable)
{
base->DE |= 1U << moduleIndex;
}
else
{
base->DE &= ~(1U << moduleIndex);
}
}
#endif /* FSL_FEATURE_LLWU_HAS_DMA_ENABLE_REG */
#if (defined(FSL_FEATURE_LLWU_HAS_PIN_FILTER) && FSL_FEATURE_LLWU_HAS_PIN_FILTER)
/*!
* @brief Sets the pin filter configuration.
*
* This function sets the pin filter configuration.
*
* @param base LLWU peripheral base address.
* @param filterIndex A pin filter index used to enable/disable the digital filter, starting from 1.
* @param filterMode A filter mode configuration
*/
void LLWU_SetPinFilterMode(LLWU_Type *base, uint32_t filterIndex, llwu_external_pin_filter_mode_t filterMode);
/*!
* @brief Gets the pin filter configuration.
*
* This function gets the pin filter flag.
*
* @param base LLWU peripheral base address.
* @param filterIndex A pin filter index, which starts from 1.
* @return True if the flag is a source of the existing low-leakage power mode.
*/
bool LLWU_GetPinFilterFlag(LLWU_Type *base, uint32_t filterIndex);
/*!
* @brief Clears the pin filter configuration.
*
* This function clears the pin filter flag.
*
* @param base LLWU peripheral base address.
* @param filterIndex A pin filter index to clear the flag, starting from 1.
*/
void LLWU_ClearPinFilterFlag(LLWU_Type *base, uint32_t filterIndex);
#endif /* FSL_FEATURE_LLWU_HAS_PIN_FILTER */
#if (defined(FSL_FEATURE_LLWU_HAS_RESET_ENABLE) && FSL_FEATURE_LLWU_HAS_RESET_ENABLE)
/*!
* @brief Sets the reset pin mode.
*
* This function determines how the reset pin is used as a low leakage mode exit source.
*
* @param pinEnable Enable reset the pin filter
* @param pinFilterEnable Specify whether the pin filter is enabled in Low-Leakage power mode.
*/
void LLWU_SetResetPinMode(LLWU_Type *base, bool pinEnable, bool enableInLowLeakageMode);
#endif /* FSL_FEATURE_LLWU_HAS_RESET_ENABLE */
/*@}*/
#if defined(__cplusplus)
}
#endif
/*! @}*/
#endif /* _FSL_LLWU_H_*/

View File

@ -0,0 +1,338 @@
/*
* Copyright (c) 2016, Freescale Semiconductor, Inc.
* Copyright 2016-2017 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include "fsl_lpadc.h"
/*******************************************************************************
* Prototypes
******************************************************************************/
/*!
* @brief Get instance number for LPADC module.
*
* @param base LPADC peripheral base address
*/
static uint32_t LPADC_GetInstance(ADC_Type *base);
/*******************************************************************************
* Variables
******************************************************************************/
/*! @brief Pointers to LPADC bases for each instance. */
static ADC_Type *const s_lpadcBases[] = ADC_BASE_PTRS;
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
/*! @brief Pointers to LPADC clocks for each instance. */
static const clock_ip_name_t s_lpadcClocks[] = LPADC_CLOCKS;
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
/*******************************************************************************
* Code
******************************************************************************/
static uint32_t LPADC_GetInstance(ADC_Type *base)
{
uint32_t instance;
/* Find the instance index from base address mappings. */
for (instance = 0; instance < ARRAY_SIZE(s_lpadcBases); instance++)
{
if (s_lpadcBases[instance] == base)
{
break;
}
}
assert(instance < ARRAY_SIZE(s_lpadcBases));
return instance;
}
void LPADC_Init(ADC_Type *base, const lpadc_config_t *config)
{
/* Check if the pointer is available. */
assert(config != NULL);
uint32_t tmp32 = 0U;
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
/* Enable the clock for LPADC instance. */
CLOCK_EnableClock(s_lpadcClocks[LPADC_GetInstance(base)]);
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
/* Reset the module. */
LPADC_DoResetConfig(base);
LPADC_DoResetFIFO(base);
/* Disable the module before setting configuration. */
LPADC_Enable(base, false);
/* Configure the module generally. */
if (config->enableInDozeMode)
{
base->CTRL &= ~ADC_CTRL_DOZEN_MASK;
}
else
{
base->CTRL |= ADC_CTRL_DOZEN_MASK;
}
/* ADCx_CFG. */
#if defined(FSL_FEATURE_LPADC_HAS_CFG_ADCKEN) && FSL_FEATURE_LPADC_HAS_CFG_ADCKEN
if (config->enableInternalClock)
{
tmp32 |= ADC_CFG_ADCKEN_MASK;
}
#endif /* FSL_FEATURE_LPADC_HAS_CFG_ADCKEN */
#if defined(FSL_FEATURE_LPADC_HAS_CFG_VREF1RNG) && FSL_FEATURE_LPADC_HAS_CFG_VREF1RNG
if (config->enableVref1LowVoltage)
{
tmp32 |= ADC_CFG_VREF1RNG_MASK;
}
#endif /* FSL_FEATURE_LPADC_HAS_CFG_VREF1RNG */
if (config->enableAnalogPreliminary)
{
tmp32 |= ADC_CFG_PWREN_MASK;
}
tmp32 |= ADC_CFG_PUDLY(config->powerUpDelay) /* Power up delay. */
| ADC_CFG_REFSEL(config->referenceVoltageSource) /* Reference voltage. */
| ADC_CFG_TPRICTRL(config->triggerPrioirtyPolicy); /* Trigger priority policy. */
base->CFG = tmp32;
/* ADCx_PAUSE. */
if (config->enableConvPause)
{
base->PAUSE = ADC_PAUSE_PAUSEEN_MASK | ADC_PAUSE_PAUSEDLY(config->convPauseDelay);
}
else
{
base->PAUSE = 0U;
}
/* ADCx_FCTRL. */
base->FCTRL = ADC_FCTRL_FWMARK(config->FIFOWatermark);
/* Enable the module after setting configuration. */
LPADC_Enable(base, true);
}
void LPADC_GetDefaultConfig(lpadc_config_t *config)
{
#if defined(FSL_FEATURE_LPADC_HAS_CFG_ADCKEN) && FSL_FEATURE_LPADC_HAS_CFG_ADCKEN
config->enableInternalClock = false;
#endif /* FSL_FEATURE_LPADC_HAS_CFG_ADCKEN */
#if defined(FSL_FEATURE_LPADC_HAS_CFG_VREF1RNG) && FSL_FEATURE_LPADC_HAS_CFG_VREF1RNG
config->enableVref1LowVoltage = false;
#endif /* FSL_FEATURE_LPADC_HAS_CFG_VREF1RNG */
config->enableInDozeMode = true;
config->enableAnalogPreliminary = false;
config->powerUpDelay = 0x80;
config->referenceVoltageSource = kLPADC_ReferenceVoltageAlt1;
config->powerLevelMode = kLPADC_PowerLevelAlt1;
config->triggerPrioirtyPolicy = kLPADC_TriggerPriorityPreemptImmediately;
config->enableConvPause = false;
config->convPauseDelay = 0U;
config->FIFOWatermark = 0U;
}
void LPADC_Deinit(ADC_Type *base)
{
/* Disable the module. */
LPADC_Enable(base, false);
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
/* Gate the clock. */
CLOCK_DisableClock(s_lpadcClocks[LPADC_GetInstance(base)]);
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
}
bool LPADC_GetConvResult(ADC_Type *base, lpadc_conv_result_t *result)
{
assert(result != NULL); /* Check if the input pointer is available. */
uint32_t tmp32;
tmp32 = base->RESFIFO;
if (0U == (ADC_RESFIFO_VALID_MASK & tmp32))
{
return false; /* FIFO is empty. Discard any read from RESFIFO. */
}
result->commandIdSource = (tmp32 & ADC_RESFIFO_CMDSRC_MASK) >> ADC_RESFIFO_CMDSRC_SHIFT;
result->loopCountIndex = (tmp32 & ADC_RESFIFO_LOOPCNT_MASK) >> ADC_RESFIFO_LOOPCNT_SHIFT;
result->triggerIdSource = (tmp32 & ADC_RESFIFO_TSRC_MASK) >> ADC_RESFIFO_TSRC_SHIFT;
result->convValue = (uint16_t)(tmp32 & ADC_RESFIFO_D_MASK);
return true;
}
void LPADC_SetConvTriggerConfig(ADC_Type *base, uint32_t triggerId, const lpadc_conv_trigger_config_t *config)
{
assert(triggerId < ADC_TCTRL_COUNT); /* Check if the triggerId is available in this device. */
assert(config != NULL); /* Check if the input pointer is available. */
uint32_t tmp32;
tmp32 = ADC_TCTRL_TCMD(config->targetCommandId) /* Trigger command select. */
| ADC_TCTRL_TDLY(config->delayPower) /* Trigger delay select. */
| ADC_TCTRL_TPRI(config->priority); /* Trigger priority setting. */
if (config->enableHardwareTrigger)
{
tmp32 |= ADC_TCTRL_HTEN_MASK;
}
base->TCTRL[triggerId] = tmp32;
}
void LPADC_GetDefaultConvTriggerConfig(lpadc_conv_trigger_config_t *config)
{
assert(config != NULL); /* Check if the input pointer is available. */
config->targetCommandId = 0U;
config->delayPower = 0U;
config->priority = 0U;
config->enableHardwareTrigger = false;
}
void LPADC_SetConvCommandConfig(ADC_Type *base, uint32_t commandId, const lpadc_conv_command_config_t *config)
{
assert(commandId < (ADC_CMDL_COUNT + 1U)); /* Check if the commandId is available on this device. */
assert(config != NULL); /* Check if the input pointer is available. */
uint32_t tmp32;
commandId--; /* The available command number are 1-15, while the index of register group are 0-14. */
/* ADCx_CMDL. */
tmp32 = ADC_CMDL_ADCH(config->channelNumber); /* Channel number. */
#if defined(FSL_FEATURE_LPADC_HAS_CMDL_CSCALE) && FSL_FEATURE_LPADC_HAS_CMDL_CSCALE
tmp32 |= ADC_CMDL_CSCALE(config->sampleScaleMode); /* Full/Part scale input voltage. */
#endif /* FSL_FEATURE_LPADC_HAS_CMDL_CSCALE */
switch (config->sampleChannelMode) /* Sample input. */
{
case kLPADC_SampleChannelSingleEndSideB:
tmp32 |= ADC_CMDL_ABSEL_MASK;
break;
#if defined(FSL_FEATURE_LPADC_HAS_CMDL_DIFF) && FSL_FEATURE_LPADC_HAS_CMDL_DIFF
case kLPADC_SampleChannelDiffBothSideAB:
tmp32 |= ADC_CMDL_DIFF_MASK;
break;
case kLPADC_SampleChannelDiffBothSideBA:
tmp32 |= ADC_CMDL_ABSEL_MASK | ADC_CMDL_DIFF_MASK;
break;
#endif /* FSL_FEATURE_LPADC_HAS_CMDL_DIFF */
default: /* kLPADC_SampleChannelSingleEndSideA. */
break;
}
base->CMD[commandId].CMDL = tmp32;
/* ADCx_CMDH. */
tmp32 = ADC_CMDH_NEXT(config->chainedNextCommandNumber) /* Next Command Select. */
| ADC_CMDH_LOOP(config->loopCount) /* Loop Count Select. */
| ADC_CMDH_AVGS(config->hardwareAverageMode) /* Hardware Average Select. */
| ADC_CMDH_STS(config->sampleTimeMode) /* Sample Time Select. */
| ADC_CMDH_CMPEN(config->hardwareCompareMode); /* Hardware compare enable. */
if (config->enableAutoChannelIncrement)
{
tmp32 |= ADC_CMDH_LWI_MASK;
}
base->CMD[commandId].CMDH = tmp32;
/* Hardware compare settings.
* Not all Command Buffers have an associated Compare Value register. The compare function is only available on
* Command Buffers that have a corresponding Compare Value register.
*/
if (kLPADC_HardwareCompareDisabled != config->hardwareCompareMode)
{
/* Check if the hardware compare feature is available for indicated command buffer. */
assert(commandId < ADC_CV_COUNT);
/* Set CV register. */
base->CV[commandId] = ADC_CV_CVH(config->hardwareCompareValueHigh) /* Compare value high. */
| ADC_CV_CVL(config->hardwareCompareValueLow); /* Compare value low. */
}
}
void LPADC_GetDefaultConvCommandConfig(lpadc_conv_command_config_t *config)
{
assert(config != NULL); /* Check if the input pointer is available. */
#if defined(FSL_FEATURE_LPADC_HAS_CMDL_CSCALE) && FSL_FEATURE_LPADC_HAS_CMDL_CSCALE
config->sampleScaleMode = kLPADC_SampleFullScale;
#endif /* FSL_FEATURE_LPADC_HAS_CMDL_CSCALE */
config->sampleChannelMode = kLPADC_SampleChannelSingleEndSideA;
config->channelNumber = 0U;
config->chainedNextCommandNumber = 0U; /* No next command defined. */
config->enableAutoChannelIncrement = false;
config->loopCount = 0U;
config->hardwareAverageMode = kLPADC_HardwareAverageCount1;
config->sampleTimeMode = kLPADC_SampleTimeADCK3;
config->hardwareCompareMode = kLPADC_HardwareCompareDisabled;
config->hardwareCompareValueHigh = 0U; /* No used. */
config->hardwareCompareValueLow = 0U; /* No used. */
}
#if defined(FSL_FEATURE_LPADC_HAS_CFG_CALOFS) && FSL_FEATURE_LPADC_HAS_CFG_CALOFS
void LPADC_EnableCalibration(ADC_Type *base, bool enable)
{
LPADC_Enable(base, false);
if (enable)
{
base->CFG |= ADC_CFG_CALOFS_MASK;
}
else
{
base->CFG &= ~ADC_CFG_CALOFS_MASK;
}
LPADC_Enable(base, true);
}
#if defined(FSL_FEATURE_LPADC_HAS_OFSTRIM) && FSL_FEATURE_LPADC_HAS_OFSTRIM
void LPADC_DoAutoCalibration(ADC_Type *base)
{
assert(0u == LPADC_GetConvResultCount(base));
uint32_t mLpadcCMDL;
uint32_t mLpadcCMDH;
uint32_t mLpadcTrigger;
lpadc_conv_trigger_config_t mLpadcTriggerConfigStruct;
lpadc_conv_command_config_t mLpadcCommandConfigStruct;
lpadc_conv_result_t mLpadcResultConfigStruct;
/* Enable the calibration function. */
LPADC_EnableCalibration(base, true);
/* Keep the CMD and TRG state here and restore it later if the calibration completes.*/
mLpadcCMDL = base->CMD[0].CMDL; /* CMD1L. */
mLpadcCMDH = base->CMD[0].CMDH; /* CMD1H. */
mLpadcTrigger = base->TCTRL[0]; /* Trigger0. */
/* Set trigger0 configuration - for software trigger. */
LPADC_GetDefaultConvTriggerConfig(&mLpadcTriggerConfigStruct);
mLpadcTriggerConfigStruct.targetCommandId = 1U; /* CMD1 is executed. */
LPADC_SetConvTriggerConfig(base, 0U, &mLpadcTriggerConfigStruct); /* Configurate the trigger0. */
/* Set conversion CMD configuration. */
LPADC_GetDefaultConvCommandConfig(&mLpadcCommandConfigStruct);
mLpadcCommandConfigStruct.hardwareAverageMode = kLPADC_HardwareAverageCount128;
LPADC_SetConvCommandConfig(base, 1U, &mLpadcCommandConfigStruct); /* Set CMD1 configuration. */
/* Do calibration. */
LPADC_DoSoftwareTrigger(base, 1U); /* 1U is trigger0 mask. */
while (!LPADC_GetConvResult(base, &mLpadcResultConfigStruct))
{
}
/* The valid bits of data are bits 14:3 in the RESFIFO register. */
LPADC_SetOffsetValue(base, (mLpadcResultConfigStruct.convValue) >> 3U);
/* Disable the calibration function. */
LPADC_EnableCalibration(base, false);
/* restore CMD and TRG registers. */
base->CMD[0].CMDL = mLpadcCMDL; /* CMD1L. */
base->CMD[0].CMDH = mLpadcCMDH; /* CMD1H. */
base->TCTRL[0] = mLpadcTrigger; /* Trigger0. */
}
#endif /* FSL_FEATURE_LPADC_HAS_OFSTRIM */
#endif /* FSL_FEATURE_LPADC_HAS_CFG_CALOFS */

View File

@ -0,0 +1,611 @@
/*
* Copyright (c) 2016, Freescale Semiconductor, Inc.
* Copyright 2016-2017 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef _FSL_LPADC_H_
#define _FSL_LPADC_H_
#include "fsl_common.h"
/*!
* @addtogroup lpadc
* @{
*/
/*! @file */
/*******************************************************************************
* Definitions
******************************************************************************/
/*! @name Driver version */
/*@{*/
/*! @brief LPADC driver version 2.0.0. */
#define FSL_LPADC_DRIVER_VERSION (MAKE_VERSION(2, 0, 0))
/*@}*/
/*!
* @brief Define the MACRO function to get command status from status value.
*
* The statusVal is the return value from LPADC_GetStatusFlags().
*/
#define LPADC_GET_ACTIVE_COMMAND_STATUS(statusVal) ((statusVal & ADC_STAT_CMDACT_MASK) >> ADC_STAT_CMDACT_SHIFT)
/*!
* @brief Define the MACRO function to get trigger status from status value.
*
* The statusVal is the return value from LPADC_GetStatusFlags().
*/
#define LPADC_GET_ACTIVE_TRIGGER_STATUE(statusVal) ((statusVal & ADC_STAT_TRGACT_MASK) >> ADC_STAT_TRGACT_SHIFT)
/*!
* @brief Define hardware flags of the module.
*/
enum _lpadc_status_flags
{
kLPADC_ResultFIFOOverflowFlag = ADC_STAT_FOF_MASK, /*!< Indicates that more data has been written to the Result FIFO
than it can hold. */
kLPADC_ResultFIFOReadyFlag = ADC_STAT_RDY_MASK, /*!< Indicates when the number of valid datawords in the result FIFO
is greater than the setting watermark level. */
};
/*!
* @brief Define interrupt switchers of the module.
*/
enum _lpadc_interrupt_enable
{
kLPADC_ResultFIFOOverflowInterruptEnable = ADC_IE_FOFIE_MASK, /*!< Configures ADC to generate overflow interrupt
requests when FOF flag is asserted. */
kLPADC_FIFOWatermarkInterruptEnable = ADC_IE_FWMIE_MASK, /*!< Configures ADC to generate watermark interrupt
requests when RDY flag is asserted. */
};
/*!
* @brief Define enumeration of sample scale mode.
*
* The sample scale mode is used to reduce the selected ADC analog channel input voltage level by a factor. The maximum
* possible voltage on the ADC channel input should be considered when selecting a scale mode to ensure that the
* reducing factor always results voltage level at or below the VREFH reference. This reducing capability allows
* conversion of analog inputs higher than VREFH. A-side and B-side channel inputs are both scaled using the scale mode.
*/
typedef enum _lpadc_sample_scale_mode
{
kLPADC_SamplePartScale = 0U, /*!< Use divided input voltage signal. (Factor of 30/64). */
kLPADC_SampleFullScale = 1U, /*!< Full scale (Factor of 1). */
} lpadc_sample_scale_mode_t;
/*!
* @brief Define enumeration of channel sample mode.
*
* The channel sample mode configures the channel with single end/differential, side A/B.
*/
typedef enum _lpadc_sample_channel_mode
{
kLPADC_SampleChannelSingleEndSideA = 0U, /*!< Single end mode, using side A. */
kLPADC_SampleChannelSingleEndSideB = 1U, /*!< Single end mode, using side B. */
#if defined(FSL_FEATURE_LPADC_HAS_CMDL_DIFF) && FSL_FEATURE_LPADC_HAS_CMDL_DIFF
kLPADC_SampleChannelDiffBothSideAB = 2U, /*!< Differential mode, using A as plus side and B as minue side. */
kLPADC_SampleChannelDiffBothSideBA = 3U, /*!< Differential mode, using B as plus side and A as minue side. */
#endif /* FSL_FEATURE_LPADC_HAS_CMDL_DIFF */
} lpadc_sample_channel_mode_t;
/*!
* @brief Define enumeration of hardware average selection.
*
* It Selects how many ADC conversions are averaged to create the ADC result. An internal storage buffer is used to
* capture temporary results while the averaging iterations are executed.
*/
typedef enum _lpadc_hardware_average_mode
{
kLPADC_HardwareAverageCount1 = 0U, /*!< Single conversion. */
kLPADC_HardwareAverageCount2 = 1U, /*!< 2 conversions averaged. */
kLPADC_HardwareAverageCount4 = 2U, /*!< 4 conversions averaged. */
kLPADC_HardwareAverageCount8 = 3U, /*!< 8 conversions averaged. */
kLPADC_HardwareAverageCount16 = 4U, /*!< 16 conversions averaged. */
kLPADC_HardwareAverageCount32 = 5U, /*!< 32 conversions averaged. */
kLPADC_HardwareAverageCount64 = 6U, /*!< 64 conversions averaged. */
kLPADC_HardwareAverageCount128 = 7U, /*!< 128 conversions averaged. */
} lpadc_hardware_average_mode_t;
/*!
* @brief Define enumeration of sample time selection.
*
* The shortest sample time maximizes conversion speed for lower impedance inputs. Extending sample time allows higher
* impedance inputs to be accurately sampled. Longer sample times can also be used to lower overall power consumption
* when command looping and sequencing is configured and high conversion rates are not required.
*/
typedef enum _lpadc_sample_time_mode
{
kLPADC_SampleTimeADCK3 = 0U, /*!< 3 ADCK cycles total sample time. */
kLPADC_SampleTimeADCK5 = 1U, /*!< 5 ADCK cycles total sample time. */
kLPADC_SampleTimeADCK7 = 2U, /*!< 7 ADCK cycles total sample time. */
kLPADC_SampleTimeADCK11 = 3U, /*!< 11 ADCK cycles total sample time. */
kLPADC_SampleTimeADCK19 = 4U, /*!< 19 ADCK cycles total sample time. */
kLPADC_SampleTimeADCK35 = 5U, /*!< 35 ADCK cycles total sample time. */
kLPADC_SampleTimeADCK67 = 6U, /*!< 69 ADCK cycles total sample time. */
kLPADC_SampleTimeADCK131 = 7U, /*!< 131 ADCK cycles total sample time. */
} lpadc_sample_time_mode_t;
/*!
* @brief Define enumeration of hardware compare mode.
*
* After an ADC channel input is sampled and converted and any averaging iterations are performed, this mode setting
* guides operation of the automatic compare function to optionally only store when the compare operation is true.
* When compare is enabled, the conversion result is compared to the compare values.
*/
typedef enum _lpadc_hardware_compare_mode
{
kLPADC_HardwareCompareDisabled = 0U, /*!< Compare disabled. */
kLPADC_HardwareCompareStoreOnTrue = 2U, /*!< Compare enabled. Store on true. */
kLPADC_HardwareCompareRepeatUntilTrue = 3U, /*!< Compare enabled. Repeat channel acquisition until true. */
} lpadc_hardware_compare_mode_t;
/*!
* @brief Define enumeration of reference voltage source.
*
* For detail information, need to check the SoC's specification.
*/
typedef enum _lpadc_reference_voltage_mode
{
kLPADC_ReferenceVoltageAlt1 = 0U, /*!< Option 1 setting. */
kLPADC_ReferenceVoltageAlt2 = 1U, /*!< Option 2 setting. */
kLPADC_ReferenceVoltageAlt3 = 2U, /*!< Option 3 setting. */
} lpadc_reference_voltage_source_t;
/*!
* @brief Define enumeration of power configuration.
*
* Configures the ADC for power and performance. In the highest power setting the highest conversion rates will be
* possible. Refer to the device data sheet for power and performance capabilities for each setting.
*/
typedef enum _lpadc_power_level_mode
{
kLPADC_PowerLevelAlt1 = 0U, /*!< Lowest power setting. */
kLPADC_PowerLevelAlt2 = 1U, /*!< Next lowest power setting. */
kLPADC_PowerLevelAlt3 = 2U, /*!< ... */
kLPADC_PowerLevelAlt4 = 3U, /*!< Highest power setting. */
} lpadc_power_level_mode_t;
/*!
* @brief Define enumeration of trigger priority policy.
*
* This selection controls how higher priority triggers are handled.
*/
typedef enum _lpadc_trigger_priority_policy
{
kLPADC_TriggerPriorityPreemptImmediately = 0U, /*!< If a higher priority trigger is detected during command
processing, the current conversion is aborted and the new
command specified by the trigger is started. */
kLPADC_TriggerPriorityPreemptSoftly = 1U, /*!< If a higher priority trigger is received during command processing,
the current conversion is completed (including averaging iterations
and compare function if enabled) and stored to the result FIFO
before the higher priority trigger/command is initiated. */
} lpadc_trigger_priority_policy_t;
/*!
* @beief LPADC global configuration.
*
* This structure would used to keep the settings for initialization.
*/
typedef struct
{
#if defined(FSL_FEATURE_LPADC_HAS_CFG_ADCKEN) && FSL_FEATURE_LPADC_HAS_CFG_ADCKEN
bool enableInternalClock; /*!< Enables the internally generated clock source. The clock source is used in clock
selection logic at the chip level and is optionally used for the ADC clock source. */
#endif /* FSL_FEATURE_LPADC_HAS_CFG_ADCKEN */
#if defined(FSL_FEATURE_LPADC_HAS_CFG_VREF1RNG) && FSL_FEATURE_LPADC_HAS_CFG_VREF1RNG
bool enableVref1LowVoltage; /*!< If voltage reference option1 input is below 1.8V, it should be "true".
If voltage reference option1 input is above 1.8V, it should be "false". */
#endif /* FSL_FEATURE_LPADC_HAS_CFG_VREF1RNG */
bool enableInDozeMode; /*!< Control system transition to Stop and Wait power modes while ADC is converting. When
enabled in Doze mode, immediate entries to Wait or Stop are allowed. When disabled, the
ADC will wait for the current averaging iteration/FIFO storage to complete before
acknowledging stop or wait mode entry. */
bool enableAnalogPreliminary; /*!< ADC analog circuits are pre-enabled and ready to execute conversions without
startup delays(at the cost of higher DC current consumption). */
uint32_t powerUpDelay; /*!< When the analog circuits are not pre-enabled, the ADC analog circuits are only powered
while the ADC is active and there is a counted delay defined by this field after an
initial trigger transitions the ADC from its Idle state to allow time for the analog
circuits to stabilize. The startup delay count of (powerUpDelay * 4) ADCK cycles must
result in a longer delay than the analog startup time. */
lpadc_reference_voltage_source_t referenceVoltageSource; /*!< Selects the voltage reference high used for
conversions.*/
lpadc_power_level_mode_t powerLevelMode; /*!< Power Configuration Selection. */
lpadc_trigger_priority_policy_t triggerPrioirtyPolicy; /*!< Control how higher priority triggers are handled, see to
#lpadc_trigger_priority_policy_mode_t. */
bool enableConvPause; /*!< Enables the ADC pausing function. When enabled, a programmable delay is inserted during
command execution sequencing between LOOP iterations, between commands in a sequence, and
between conversions when command is executing in "Compare Until True" configuration. */
uint32_t convPauseDelay; /*!< Controls the duration of pausing during command execution sequencing. The pause delay
is a count of (convPauseDelay*4) ADCK cycles. Only available when ADC pausing
function is enabled. The available value range is in 9-bit. */
/* for FIFO. */
uint32_t FIFOWatermark; /*!< FIFOWatermark is a programmable threshold setting. When the number of datawords stored
in the ADC Result FIFO is greater than the value in this field, the ready flag would be
asserted to indicate stored data has reached the programmable threshold. */
} lpadc_config_t;
/*!
* @brief Define structure to keep the configuration for conversion command.
*/
typedef struct
{
#if defined(FSL_FEATURE_LPADC_HAS_CMDL_CSCALE) && FSL_FEATURE_LPADC_HAS_CMDL_CSCALE
lpadc_sample_scale_mode_t sampleScaleMode; /*!< Sample scale mode. */
#endif /* FSL_FEATURE_LPADC_HAS_CMDL_CSCALE */
lpadc_sample_channel_mode_t sampleChannelMode; /*!< Channel sample mode. */
uint32_t channelNumber; /*!< Channel number, select the channel or channel pair. */
uint32_t chainedNextCommandNumber; /*!< Selects the next command to be executed after this command completes.
1-15 is available, 0 is to terminate the chain after this command. */
bool enableAutoChannelIncrement; /*!< Loop with increment: when disabled, the "loopCount" field selects the number
of times the selected channel is converted consecutively; when enabled, the
"loopCount" field defines how many consecutive channels are converted as part
of the command execution. */
uint32_t loopCount; /*!< Selects how many times this command executes before finish and transition to the next
command or Idle state. Command executes LOOP+1 times. 0-15 is available. */
lpadc_hardware_average_mode_t hardwareAverageMode; /*!< Hardware average selection. */
lpadc_sample_time_mode_t sampleTimeMode; /*!< Sample time selection. */
lpadc_hardware_compare_mode_t hardwareCompareMode; /*!< Hardware compare selection. */
uint32_t hardwareCompareValueHigh; /*!< Compare Value High. The available value range is in 16-bit. */
uint32_t hardwareCompareValueLow; /*!< Compare Value Low. The available value range is in 16-bit. */
} lpadc_conv_command_config_t;
/*!
* @brief Define structure to keep the configuration for conversion trigger.
*/
typedef struct
{
uint32_t targetCommandId; /*!< Select the command from command buffer to execute upon detect of the associated
trigger event. */
uint32_t delayPower; /*!< Select the trigger delay duration to wait at the start of servicing a trigger event.
When this field is clear, then no delay is incurred. When this field is set to a non-zero
value, the duration for the delay is 2^delayPower ADCK cycles. The available value range
is 4-bit. */
uint32_t priority; /*!< Sets the priority of the associated trigger source. If two or more triggers have the same
priority level setting, the lower order trigger event has the higher priority. The lower
value for this field is for the higher priority, the available value range is 1-bit. */
bool enableHardwareTrigger; /*!< Enable hardware trigger source to initiate conversion on the rising edge of the
input trigger source or not. THe software trigger is always available. */
} lpadc_conv_trigger_config_t;
/*!
* @brief Define the structure to keep the conversion result.
*/
typedef struct
{
uint32_t commandIdSource; /*!< Indicate the command buffer being executed that generated this result. */
uint32_t loopCountIndex; /*!< Indicate the loop count value during command execution that generated this result. */
uint32_t triggerIdSource; /*!< Indicate the trigger source that initiated a conversion and generated this result. */
uint16_t convValue; /*!< Data result. */
} lpadc_conv_result_t;
#if defined(__cplusplus)
extern "C" {
#endif
/*******************************************************************************
* API
******************************************************************************/
/*!
* @name Initialization & de-initialization.
* @{
*/
/*!
* @brief Initializes the LPADC module.
*
* @param base LPADC peripheral base address.
* @param config Pointer to configuration structure. See "lpadc_config_t".
*/
void LPADC_Init(ADC_Type *base, const lpadc_config_t *config);
/*!
* @brief Gets an available pre-defined settings for initial configuration.
*
* This function initializes the converter configuration structure with an available settings. The default values are:
* @code
* config->enableInDozeMode = true;
* config->enableAnalogPreliminary = false;
* config->powerUpDelay = 0x80;
* config->referenceVoltageSource = kLPADC_ReferenceVoltageAlt1;
* config->powerLevelMode = kLPADC_PowerLevelAlt1;
* config->triggerPrioirtyPolicy = kLPADC_TriggerPriorityPreemptImmediately;
* config->enableConvPause = false;
* config->convPauseDelay = 0U;
* config->FIFOWatermark = 0U;
* @endcode
* @param config Pointer to configuration structure.
*/
void LPADC_GetDefaultConfig(lpadc_config_t *config);
/*!
* @brief De-initializes the LPADC module.
*
* @param base LPADC peripheral base address.
*/
void LPADC_Deinit(ADC_Type *base);
/*!
* @brief Switch on/off the LPADC module.
*
* @param base LPADC peripheral base address.
* @param enable switcher to the module.
*/
static inline void LPADC_Enable(ADC_Type *base, bool enable)
{
if (enable)
{
base->CTRL |= ADC_CTRL_ADCEN_MASK;
}
else
{
base->CTRL &= ~ADC_CTRL_ADCEN_MASK;
}
}
/*!
* @brief Do reset the conversion FIFO.
*
* @param base LPADC peripheral base address.
*/
static inline void LPADC_DoResetFIFO(ADC_Type *base)
{
base->CTRL |= ADC_CTRL_RSTFIFO_MASK;
}
/*!
* @brief Do reset the module's configuration.
*
* Reset all ADC internal logic and registers, except the Control Register (ADCx_CTRL).
*
* @param base LPADC peripheral base address.
*/
static inline void LPADC_DoResetConfig(ADC_Type *base)
{
base->CTRL |= ADC_CTRL_RST_MASK;
base->CTRL &= ~ADC_CTRL_RST_MASK;
}
/* @} */
/*!
* @name Status
* @{
*/
/*!
* @brief Get status flags.
*
* @param base LPADC peripheral base address.
* @return status flags' mask. See to #_lpadc_status_flags.
*/
static inline uint32_t LPADC_GetStatusFlags(ADC_Type *base)
{
return base->STAT;
}
/*!
* @brief Clear status flags.
*
* Only the flags can be cleared by writing ADCx_STATUS register would be cleared by this API.
*
* @param base LPADC peripheral base address.
* @param mask Mask value for flags to be cleared. See to #_lpadc_status_flags.
*/
static inline void LPADC_ClearStatusFlags(ADC_Type *base, uint32_t mask)
{
base->STAT = mask;
}
/* @} */
/*!
* @name Interrupts
* @{
*/
/*!
* @brief Enable interrupts.
*
* @param base LPADC peripheral base address.
* @mask Mask value for interrupt events. See to #_lpadc_interrupt_enable.
*/
static inline void LPADC_EnableInterrupts(ADC_Type *base, uint32_t mask)
{
base->IE |= mask;
}
/*!
* @brief Disable interrupts.
*
* @param base LPADC peripheral base address.
* @param mask Mask value for interrupt events. See to #_lpadc_interrupt_enable.
*/
static inline void LPADC_DisableInterrupts(ADC_Type *base, uint32_t mask)
{
base->IE &= ~mask;
}
/*!
* @name DMA Control
* @{
*/
/*!
* @brief Switch on/off the DMA trigger for FIFO watermark event.
*
* @param base LPADC peripheral base address.
* @param enable Switcher to the event.
*/
static inline void LPADC_EnableFIFOWatermarkDMA(ADC_Type *base, bool enable)
{
if (enable)
{
base->DE |= ADC_DE_FWMDE_MASK;
}
else
{
base->DE &= ~ADC_DE_FWMDE_MASK;
}
}
/* @} */
/*!
* @name Trigger and conversion with FIFO.
* @{
*/
/*!
* @brief Get the count of result kept in conversion FIFO.
*
* @param base LPADC peripheral base address.
* @return The count of result kept in conversion FIFO.
*/
static inline uint32_t LPADC_GetConvResultCount(ADC_Type *base)
{
return (ADC_FCTRL_FCOUNT_MASK & base->FCTRL) >> ADC_FCTRL_FCOUNT_SHIFT;
}
/*!
* @brief Get the result in conversion FIFO.
*
* @param base LPADC peripheral base address.
* @param result Pointer to structure variable that keeps the conversion result in conversion FIFO.
*
* @return Status whether FIFO entry is valid.
*/
bool LPADC_GetConvResult(ADC_Type *base, lpadc_conv_result_t *result);
/*!
* @brief Configure the conversion trigger source.
*
* Each programmable trigger can launch the conversion command in command buffer.
*
* @param base LPADC peripheral base address.
* @param triggerId ID for each trigger. Typically, the available value range is from 0.
* @param config Pointer to configuration structure. See to #lpadc_conv_trigger_config_t.
*/
void LPADC_SetConvTriggerConfig(ADC_Type *base, uint32_t triggerId, const lpadc_conv_trigger_config_t *config);
/*!
* @brief Gets an available pre-defined settings for trigger's configuration.
*
* This function initializes the trigger's configuration structure with an available settings. The default values are:
* @code
* config->commandIdSource = 0U;
* config->loopCountIndex = 0U;
* config->triggerIdSource = 0U;
* config->enableHardwareTrigger = false;
* @endcode
* @param config Pointer to configuration structure.
*/
void LPADC_GetDefaultConvTriggerConfig(lpadc_conv_trigger_config_t *config);
/*!
* @brief Do software trigger to conversion command.
*
* @param base LPADC peripheral base address.
* @param triggerIdMask Mask value for software trigger indexes, which count from zero.
*/
static inline void LPADC_DoSoftwareTrigger(ADC_Type *base, uint32_t triggerIdMask)
{
/* Writes to ADCx_SWTRIG register are ignored while ADCx_CTRL[ADCEN] is clear. */
base->SWTRIG = triggerIdMask;
}
/*!
* @brief Configure conversion command.
*
* @param base LPADC peripheral base address.
* @param commandId ID for command in command buffer. Typically, the available value range is 1 - 15.
* @param config Pointer to configuration structure. See to #lpadc_conv_command_config_t.
*/
void LPADC_SetConvCommandConfig(ADC_Type *base, uint32_t commandId, const lpadc_conv_command_config_t *config);
/*!
* @brief Gets an available pre-defined settings for conversion command's configuration.
*
* This function initializes the conversion command's configuration structure with an available settings. The default
* values are:
* @code
* config->sampleScaleMode = kLPADC_SampleFullScale;
* config->channelSampleMode = kLPADC_SampleChannelSingleEndSideA;
* config->channelNumber = 0U;
* config->chainedNextCmdNumber = 0U;
* config->enableAutoChannelIncrement = false;
* config->loopCount = 0U;
* config->hardwareAverageMode = kLPADC_HardwareAverageCount1;
* config->sampleTimeMode = kLPADC_SampleTimeADCK3;
* config->hardwareCompareMode = kLPADC_HardwareCompareDisabled;
* config->hardwareCompareValueHigh = 0U;
* config->hardwareCompareValueLow = 0U;
* @endcode
* @param config Pointer to configuration structure.
*/
void LPADC_GetDefaultConvCommandConfig(lpadc_conv_command_config_t *config);
#if defined(FSL_FEATURE_LPADC_HAS_CFG_CALOFS) && FSL_FEATURE_LPADC_HAS_CFG_CALOFS
/*!
* @brief Enable the calibration function.
*
* When CALOFS is set, the ADC is configured to perform a calibration function anytime the ADC executes
* a conversion. Any channel selected is ignored and the value returned in the RESFIFO is a signed value
* between -31 and 31. -32 is not a valid and is never a returned value. Software should copy the lower 6-
* bits of the conversion result stored in the RESFIFO after a completed calibration conversion to the
* OFSTRIM field. The OFSTRIM field is used in normal operation for offset correction.
*
* @param base LPADC peripheral base address.
* @bool enable switcher to the calibration function.
*/
void LPADC_EnableCalibration(ADC_Type *base, bool enable);
#endif /* FSL_FEATURE_LPADC_HAS_CFG_CALOFS */
#if defined(FSL_FEATURE_LPADC_HAS_OFSTRIM) && FSL_FEATURE_LPADC_HAS_OFSTRIM
/*!
* @brief Set proper offset value to trim ADC.
*
* To minimize the offset during normal operation, software should read the conversion result from
* the RESFIFO calibration operation and write the lower 6 bits to the OFSTRIM register.
*
* @param base LPADC peripheral base address.
* @param value Setting offset value.
*/
static inline void LPADC_SetOffsetValue(ADC_Type *base, uint32_t value)
{
base->OFSTRIM = (value & ADC_OFSTRIM_OFSTRIM_MASK) >> ADC_OFSTRIM_OFSTRIM_SHIFT;
}
#endif /* FSL_FEATURE_LPADC_HAS_OFSTRIM */
#if defined(FSL_FEATURE_LPADC_HAS_CFG_CALOFS) && FSL_FEATURE_LPADC_HAS_CFG_CALOFS
#if defined(FSL_FEATURE_LPADC_HAS_OFSTRIM) && FSL_FEATURE_LPADC_HAS_OFSTRIM
/*!
* @brief Do auto calibration.
*
* Calibration function should be executed before using converter in application. It used the software trigger and a
* dummy conversion, get the offset and write them into the OFSTRIM register. It called some of functional API including:
* -LPADC_EnableCalibration(...)
* -LPADC_LPADC_SetOffsetValue(...)
* -LPADC_SetConvCommandConfig(...)
* -LPADC_SetConvTriggerConfig(...)
*
* @param base LPADC peripheral base address.
*/
void LPADC_DoAutoCalibration(ADC_Type *base);
#endif /* FSL_FEATURE_LPADC_HAS_OFSTRIM */
#endif /* FSL_FEATURE_LPADC_HAS_CFG_CALOFS */
/* @} */
#if defined(__cplusplus)
}
#endif
/*!
* @}
*/
#endif /* _FSL_LPADC_H_ */

View File

@ -0,0 +1,163 @@
/*
* Copyright (c) 2016, Freescale Semiconductor, Inc.
* All rights reserved.
*
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include "fsl_lpcmp.h"
/*******************************************************************************
* Prototypes
******************************************************************************/
#if defined(LPCMP_CLOCKS)
/*!
* @brief Get instance number for LPCMP module.
*
* @param base LPCMP peripheral base address
*/
static uint32_t LPCMP_GetInstance(LPCMP_Type *base);
#endif /* LPCMP_CLOCKS */
/*******************************************************************************
* Variables
******************************************************************************/
#if defined(LPCMP_CLOCKS)
/*! @brief Pointers to LPCMP bases for each instance. */
static LPCMP_Type *const s_lpcmpBases[] = LPCMP_BASE_PTRS;
/*! @brief Pointers to LPCMP clocks for each instance. */
static const clock_ip_name_t s_lpcmpClocks[] = LPCMP_CLOCKS;
#endif /* LPCMP_CLOCKS */
/*******************************************************************************
* Codes
******************************************************************************/
#if defined(LPCMP_CLOCKS)
static uint32_t LPCMP_GetInstance(LPCMP_Type *base)
{
uint32_t instance;
/* Find the instance index from base address mappings. */
for (instance = 0; instance < ARRAY_SIZE(s_lpcmpBases); instance++)
{
if (s_lpcmpBases[instance] == base)
{
break;
}
}
assert(instance < ARRAY_SIZE(s_lpcmpBases));
return instance;
}
#endif /* LPCMP_CLOCKS */
void LPCMP_Init(LPCMP_Type *base, const lpcmp_config_t *config)
{
assert(config != NULL);
uint32_t tmp32;
#if defined(LPCMP_CLOCKS)
/* Enable LPCMP clock. */
CLOCK_EnableClock(s_lpcmpClocks[LPCMP_GetInstance(base)]);
#endif /* LPCMP_CLOCKS */
/* Configure. */
LPCMP_Enable(base, false);
/* CCR0 register. */
if (config->enableStopMode)
{
base->CCR0 |= LPCMP_CCR0_CMP_STOP_EN_MASK;
}
else
{
base->CCR0 &= ~LPCMP_CCR0_CMP_STOP_EN_MASK;
}
/* CCR1 register. */
tmp32 = base->CCR1 & ~(LPCMP_CCR1_COUT_PEN_MASK | LPCMP_CCR1_COUT_SEL_MASK | LPCMP_CCR1_COUT_INV_MASK);
if (config->enableOutputPin)
{
tmp32 |= LPCMP_CCR1_COUT_PEN_MASK;
}
if (config->useUnfilteredOutput)
{
tmp32 |= LPCMP_CCR1_COUT_SEL_MASK;
}
if (config->enableInvertOutput)
{
tmp32 |= LPCMP_CCR1_COUT_INV_MASK;
}
base->CCR1 = tmp32;
/* CCR2 register. */
tmp32 = base->CCR2 & ~(LPCMP_CCR2_HYSTCTR_MASK | LPCMP_CCR2_CMP_NPMD_MASK | LPCMP_CCR2_CMP_HPMD_MASK);
tmp32 |= LPCMP_CCR2_HYSTCTR(config->hysteresisMode);
tmp32 |= ((uint32_t)(config->powerMode) << LPCMP_CCR2_CMP_HPMD_SHIFT);
base->CCR2 = tmp32;
LPCMP_Enable(base, true); /* Enable the LPCMP module. */
}
void LPCMP_Deinit(LPCMP_Type *base)
{
/* Disable the LPCMP module. */
LPCMP_Enable(base, false);
#if defined(LPCMP_CLOCKS)
/* Disable the clock for LPCMP. */
CLOCK_DisableClock(s_lpcmpClocks[LPCMP_GetInstance(base)]);
#endif /* LPCMP_CLOCKS */
}
void LPCMP_GetDefaultConfig(lpcmp_config_t *config)
{
config->enableStopMode = false;
config->enableOutputPin = false;
config->useUnfilteredOutput = false;
config->enableInvertOutput = false;
config->hysteresisMode = kLPCMP_HysteresisLevel0;
config->powerMode = kLPCMP_LowSpeedPowerMode;
}
void LPCMP_SetInputChannels(LPCMP_Type *base, uint32_t positiveChannel, uint32_t negativeChannel)
{
uint32_t tmp32;
tmp32 = base->CCR2 & ~(LPCMP_CCR2_PSEL_MASK | LPCMP_CCR2_MSEL_MASK);
tmp32 |= LPCMP_CCR2_PSEL(positiveChannel) | LPCMP_CCR2_MSEL(negativeChannel);
base->CCR2 = tmp32;
}
void LPCMP_SetFilterConfig(LPCMP_Type *base, const lpcmp_filter_config_t *config)
{
assert(config != NULL);
uint32_t tmp32;
tmp32 = base->CCR1 & ~(LPCMP_CCR1_FILT_PER_MASK | LPCMP_CCR1_FILT_CNT_MASK | LPCMP_CCR1_SAMPLE_EN_MASK);
if (config->enableSample)
{
tmp32 |= LPCMP_CCR1_SAMPLE_EN_MASK;
}
tmp32 |= LPCMP_CCR1_FILT_PER(config->filterSamplePeriod) | LPCMP_CCR1_FILT_CNT(config->filterSampleCount);
base->CCR1 = tmp32;
}
void LPCMP_SetDACConfig(LPCMP_Type *base, const lpcmp_dac_config_t *config)
{
uint32_t tmp32;
if (config == NULL)
{
tmp32 = 0U; /* Disable internal DAC. */
}
else
{
tmp32 = LPCMP_DCR_VRSEL(config->referenceVoltageSource) | LPCMP_DCR_DAC_DATA(config->DACValue);
if (config->enableLowPowerMode)
{
tmp32 |= LPCMP_DCR_DAC_HPMD_MASK;
}
tmp32 |= LPCMP_DCR_DAC_EN_MASK;
}
base->DCR = tmp32;
}

View File

@ -0,0 +1,299 @@
/*
* Copyright (c) 2016, Freescale Semiconductor, Inc.
* All rights reserved.
*
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef _FSL_LPCMP_H_
#define _FSL_LPCMP_H_
#include "fsl_common.h"
/*!
* @addtogroup lpcmp
* @{
*/
/*******************************************************************************
* Definitions
******************************************************************************/
/*! @name Driver version */
/*@{*/
/*! @brief LPCMP driver version 2.0.0. */
#define FSL_LPCMP_DRIVER_VERSION (MAKE_VERSION(2, 0, 0))
/*@}*/
/*!
* @brief LPCMP status falgs mask.
*/
enum _lpcmp_status_flags
{
kLPCMP_OutputRisingEventFlag = LPCMP_CSR_CFR_MASK, /*!< Rising-edge on the comparison output has occurred. */
kLPCMP_OutputFallingEventFlag = LPCMP_CSR_CFF_MASK, /*!< Falling-edge on the comparison output has occurred. */
kLPCMP_OutputAssertEventFlag = LPCMP_CSR_COUT_MASK, /*!< Return the current value of the analog comparator output.
The flag does not support W1C. */
};
/*!
* @brief LPCMP interrupt enable/disable mask.
*/
enum _lpcmp_interrupt_enable
{
kLPCMP_OutputRisingInterruptEnable = LPCMP_IER_CFR_IE_MASK, /*!< Comparator interrupt enable rising. */
kLPCMP_OutputFallingInterruptEnable = LPCMP_IER_CFF_IE_MASK, /*!< Comparator interrupt enable falling. */
};
/*!
* @brief LPCMP hysteresis mode. See chip data sheet to get the actual hystersis
* value with each level
*/
typedef enum _lpcmp_hysteresis_mode
{
kLPCMP_HysteresisLevel0 = 0U, /*!< The hard block output has level 0 hysteresis internally. */
kLPCMP_HysteresisLevel1 = 1U, /*!< The hard block output has level 1 hysteresis internally. */
kLPCMP_HysteresisLevel2 = 2U, /*!< The hard block output has level 2 hysteresis internally. */
kLPCMP_HysteresisLevel3 = 3U, /*!< The hard block output has level 3 hysteresis internally. */
} lpcmp_hysteresis_mode_t;
/*!
* @brief LPCMP nano mode.
*/
typedef enum _lpcmp_power_mode
{
kLPCMP_LowSpeedPowerMode = 0U, /*!< Low speed comparison mode is selected. */
kLPCMP_HighSpeedPowerMode = 1U, /*!< High speed comparison mode is selected. */
kLPCMP_NanoPowerMode = 2U, /*!< Nano power comparator is enabled. */
} lpcmp_power_mode_t;
/*!
* @brief Internal DAC reference voltage source.
*/
typedef enum _lpcmp_dac_reference_voltage_source
{
kLPCMP_VrefSourceVin1 = 0U, /*!< vrefh_int is selected as resistor ladder network supply reference Vin. */
kLPCMP_VrefSourceVin2 = 1U, /*!< vrefh_ext is selected as resistor ladder network supply reference Vin. */
} lpcmp_dac_reference_voltage_source_t;
/*!
* @brief Configure the filter.
*/
typedef struct _lpcmp_filter_config
{
bool enableSample; /*!< Decide whether to use the external SAMPLE as a sampling clock input. */
uint8_t filterSampleCount; /*!< Filter Sample Count. Available range is 1-7; 0 disables the filter. */
uint8_t filterSamplePeriod; /*!< Filter Sample Period. The divider to the bus clock. Available range is 0-255. The
sampling clock must be at least 4 times slower than the system clock to the comparator.
So if enableSample is "false", filterSamplePeriod should be set greater than 4.*/
} lpcmp_filter_config_t;
/*!
* @brief configure the internal DAC.
*/
typedef struct _lpcmp_dac_config
{
bool enableLowPowerMode; /*!< Decide whether to enable DAC low power mode. */
lpcmp_dac_reference_voltage_source_t referenceVoltageSource; /*!< Internal DAC supply voltage reference source. */
uint8_t DACValue; /*!< Value for the DAC Output Voltage. Available range is 0-63.*/
} lpcmp_dac_config_t;
/*!
* @brief Configures the comparator.
*/
typedef struct _lpcmp_config
{
bool enableStopMode; /*!< Decide whether to enable the comparator when in STOP modes. */
bool enableOutputPin; /*!< Decide whether to enable the comparator is available in selected pin. */
bool useUnfilteredOutput; /*!< Decide whether to use unfiltered output. */
bool enableInvertOutput; /*!< Decide whether to inverts the comparator output. */
lpcmp_hysteresis_mode_t hysteresisMode; /*!< LPCMP hysteresis mode. */
lpcmp_power_mode_t powerMode; /*!< LPCMP power mode. */
} lpcmp_config_t;
/*******************************************************************************
* API
******************************************************************************/
/*!
* @name Initialization
* @{
*/
/*!
* @brief Initialize the LPCMP
*
* This function initializes the LPCMP module. The operations included are:
* - Enabling the clock for LPCMP module.
* - Configuring the comparator.
* - Enabling the LPCMP module.
* Note: For some devices, multiple LPCMP instance share the same clock gate. In this case, to enable the clock for
* any instance enables all the LPCMPs. Check the chip reference manual for the clock assignment of the LPCMP.
*
* @param base LPCMP peripheral base address.
* @param config Pointer to "lpcmp_config_t" structure.
*/
void LPCMP_Init(LPCMP_Type *base, const lpcmp_config_t *config);
/*!
* @brief De-initializes the LPCMP module.
*
* This function de-initializes the LPCMP module. The operations included are:
* - Disabling the LPCMP module.
* - Disabling the clock for LPCMP module.
*
* This function disables the clock for the LPCMP.
* Note: For some devices, multiple LPCMP instance shares the same clock gate. In this case, before disabling the
* clock for the LPCMP, ensure that all the LPCMP instances are not used.
*
* @param base LPCMP peripheral base address.
*/
void LPCMP_Deinit(LPCMP_Type *base);
/*!
* @brief Gets an available pre-defined settings for the comparator's configuration.
*
* This function initializes the comparator configuration structure to these default values:
* @code
* config->enableStopMode = false;
* config->enableOutputPin = false;
* config->useUnfilteredOutput = false;
* config->enableInvertOutput = false;
* config->hysteresisMode = kLPCMP_HysteresisLevel0;
* config->powerMode = kLPCMP_LowSpeedPowerMode;
* @endcode
* @param config Pointer to "lpcmp_config_t" structure.
*/
void LPCMP_GetDefaultConfig(lpcmp_config_t *config);
/*!
* @brief Enable/Disable LPCMP module.
*
* @param base LPCMP peripheral base address.
* @param enable "true" means enable the module, and "false" means disable the module.
*/
static inline void LPCMP_Enable(LPCMP_Type *base, bool enable)
{
if (enable)
{
base->CCR0 |= LPCMP_CCR0_CMP_EN_MASK;
}
else
{
base->CCR0 &= ~LPCMP_CCR0_CMP_EN_MASK;
}
}
/*!
* @brief Select the input channels for LPCMP. This function determines which input
* is selected for the negative and positive mux.
*
* @param base LPCMP peripheral base address.
* @param positiveChannel Positive side input channel number. Available range is 0-7.
* @param negativeChannel Negative side input channel number. Available range is 0-7.
*/
void LPCMP_SetInputChannels(LPCMP_Type *base, uint32_t positiveChannel, uint32_t negativeChannel);
/*!
* @brief Enables/disables the DMA request for rising/falling events.
* Normally, the LPCMP generates a CPU interrupt if there is a rising/falling event. When
* DMA support is enabled and the rising/falling interrupt is enabled , the rising/falling
* event forces a DMA transfer request rather than a CPU interrupt instead.
*
* @param base LPCMP peripheral base address.
* @param enable "true" means enable DMA support, and "false" means disable DMA support.
*/
static inline void LPCMP_EnableDMA(LPCMP_Type *base, bool enable)
{
if (enable)
{
base->CCR1 |= LPCMP_CCR1_DMA_EN_MASK;
}
else
{
base->CCR1 &= ~LPCMP_CCR1_DMA_EN_MASK;
}
}
/*!
* @brief Enable/Disable window mode.When any windowed mode is active, COUTA is clocked by
* the bus clock whenever WINDOW = 1. The last latched value is held when WINDOW = 0.
* The optionally inverted comparator output COUT_RAW is sampled on every bus clock
* when WINDOW=1 to generate COUTA.
*
* @param base LPCMP peripheral base address.
* @param enable "true" means enable window mode, and "false" means disable window mode.
*/
static inline void LPCMP_EnableWindowMode(LPCMP_Type *base, bool enable)
{
if (enable)
{
base->CCR1 |= LPCMP_CCR1_WINDOW_EN_MASK;
}
else
{
base->CCR1 &= ~LPCMP_CCR1_WINDOW_EN_MASK;
}
}
/*!
* @brief Configures the filter.
*
* @param base LPCMP peripheral base address.
* @param config Pointer to "lpcmp_filter_config_t" structure.
*/
void LPCMP_SetFilterConfig(LPCMP_Type *base, const lpcmp_filter_config_t *config);
/*!
* @brief Configure the internal DAC module.
*
* @param base LPCMP peripheral base address.
* @param config Pointer to "lpcmp_dac_config_t" structure. If config is "NULL", disable internal DAC.
*/
void LPCMP_SetDACConfig(LPCMP_Type *base, const lpcmp_dac_config_t *config);
/*!
* @brief Enable the interrupts.
*
* @param base LPCMP peripheral base address.
* @param mask Mask value for interrupts. See "_lpcmp_interrupt_enable".
*/
static inline void LPCMP_EnableInterrupts(LPCMP_Type *base, uint32_t mask)
{
base->IER |= mask;
}
/*!
* @brief Disable the interrupts.
*
* @param base LPCMP peripheral base address.
* @param mask Mask value for interrupts. See "_lpcmp_interrupt_enable".
*/
static inline void LPCMP_DisableInterrupts(LPCMP_Type *base, uint32_t mask)
{
base->IER &= ~mask;
}
/*!
* @brief Get the LPCMP status flags.
*
* @param LPCMP peripheral base address.
*
* @return Mask value for the asserted flags. See "_lpcmp_status_flags".
*/
static inline uint32_t LPCMP_GetStatusFlags(LPCMP_Type *base)
{
return base->CSR;
}
/*!
* @brief Clear the LPCMP status flags
*
* @param base LPCMP peripheral base address.
* @param mask Mask value for the flags. See "_lpcmp_status_flags".
*/
static inline void LPCMP_ClearStatusFlags(LPCMP_Type *base, uint32_t mask)
{
base->CSR = mask;
}
#endif /* _FSL_LPCMP_H_ */

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,443 @@
/*
* Copyright (c) 2015, Freescale Semiconductor, Inc.
* Copyright 2016-2017 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include "fsl_lpi2c_edma.h"
#include <stdlib.h>
#include <string.h>
/*******************************************************************************
* Definitions
******************************************************************************/
/* @brief Mask to align an address to 32 bytes. */
#define ALIGN_32_MASK (0x1fU)
/*! @brief Common sets of flags used by the driver. */
enum _lpi2c_flag_constants
{
/*! All flags which are cleared by the driver upon starting a transfer. */
kMasterClearFlags = kLPI2C_MasterEndOfPacketFlag | kLPI2C_MasterStopDetectFlag | kLPI2C_MasterNackDetectFlag |
kLPI2C_MasterArbitrationLostFlag | kLPI2C_MasterFifoErrFlag | kLPI2C_MasterPinLowTimeoutFlag |
kLPI2C_MasterDataMatchFlag,
/*! IRQ sources enabled by the non-blocking transactional API. */
kMasterIrqFlags = kLPI2C_MasterArbitrationLostFlag | kLPI2C_MasterTxReadyFlag | kLPI2C_MasterRxReadyFlag |
kLPI2C_MasterStopDetectFlag | kLPI2C_MasterNackDetectFlag | kLPI2C_MasterPinLowTimeoutFlag |
kLPI2C_MasterFifoErrFlag,
/*! Errors to check for. */
kMasterErrorFlags = kLPI2C_MasterNackDetectFlag | kLPI2C_MasterArbitrationLostFlag | kLPI2C_MasterFifoErrFlag |
kLPI2C_MasterPinLowTimeoutFlag,
/*! All flags which are cleared by the driver upon starting a transfer. */
kSlaveClearFlags = kLPI2C_SlaveRepeatedStartDetectFlag | kLPI2C_SlaveStopDetectFlag | kLPI2C_SlaveBitErrFlag |
kLPI2C_SlaveFifoErrFlag,
/*! IRQ sources enabled by the non-blocking transactional API. */
kSlaveIrqFlags = kLPI2C_SlaveTxReadyFlag | kLPI2C_SlaveRxReadyFlag | kLPI2C_SlaveStopDetectFlag |
kLPI2C_SlaveRepeatedStartDetectFlag | kLPI2C_SlaveFifoErrFlag | kLPI2C_SlaveBitErrFlag |
kLPI2C_SlaveTransmitAckFlag | kLPI2C_SlaveAddressValidFlag,
/*! Errors to check for. */
kSlaveErrorFlags = kLPI2C_SlaveFifoErrFlag | kLPI2C_SlaveBitErrFlag,
};
/* ! @brief LPI2C master fifo commands. */
enum _lpi2c_master_fifo_cmd
{
kTxDataCmd = LPI2C_MTDR_CMD(0x0U), /*!< Transmit DATA[7:0] */
kRxDataCmd = LPI2C_MTDR_CMD(0X1U), /*!< Receive (DATA[7:0] + 1) bytes */
kStopCmd = LPI2C_MTDR_CMD(0x2U), /*!< Generate STOP condition */
kStartCmd = LPI2C_MTDR_CMD(0x4U), /*!< Generate(repeated) START and transmit address in DATA[[7:0] */
};
/*! @brief States for the state machine used by transactional APIs. */
enum _lpi2c_transfer_states
{
kIdleState = 0,
kSendCommandState,
kIssueReadCommandState,
kTransferDataState,
kStopState,
kWaitForCompletionState,
};
/*! @brief Typedef for interrupt handler. */
typedef void (*lpi2c_isr_t)(LPI2C_Type *base, void *handle);
/*******************************************************************************
* Prototypes
******************************************************************************/
/* Defined in fsl_lpi2c.c. */
extern status_t LPI2C_CheckForBusyBus(LPI2C_Type *base);
/* Defined in fsl_lpi2c.c. */
extern status_t LPI2C_MasterCheckAndClearError(LPI2C_Type *base, uint32_t status);
static uint32_t LPI2C_GenerateCommands(lpi2c_master_edma_handle_t *handle);
static void LPI2C_MasterEDMACallback(edma_handle_t *dmaHandle, void *userData, bool isTransferDone, uint32_t tcds);
/*******************************************************************************
* Code
******************************************************************************/
void LPI2C_MasterCreateEDMAHandle(LPI2C_Type *base,
lpi2c_master_edma_handle_t *handle,
edma_handle_t *rxDmaHandle,
edma_handle_t *txDmaHandle,
lpi2c_master_edma_transfer_callback_t callback,
void *userData)
{
assert(handle);
assert(rxDmaHandle);
assert(txDmaHandle);
/* Clear out the handle. */
memset(handle, 0, sizeof(*handle));
/* Set up the handle. For combined rx/tx DMA requests, the tx channel handle is set to the rx handle */
/* in order to make the transfer API code simpler. */
handle->base = base;
handle->completionCallback = callback;
handle->userData = userData;
handle->rx = rxDmaHandle;
handle->tx = FSL_FEATURE_LPI2C_HAS_SEPARATE_DMA_RX_TX_REQn(base) ? txDmaHandle : rxDmaHandle;
/* Set DMA channel completion callbacks. */
EDMA_SetCallback(handle->rx, LPI2C_MasterEDMACallback, handle);
if (FSL_FEATURE_LPI2C_HAS_SEPARATE_DMA_RX_TX_REQn(base))
{
EDMA_SetCallback(handle->tx, LPI2C_MasterEDMACallback, handle);
}
}
/*!
* @brief Prepares the command buffer with the sequence of commands needed to send the requested transaction.
* @param handle Master DMA driver handle.
* @return Number of command words.
*/
static uint32_t LPI2C_GenerateCommands(lpi2c_master_edma_handle_t *handle)
{
lpi2c_master_transfer_t *xfer = &handle->transfer;
uint16_t *cmd = (uint16_t *)&handle->commandBuffer;
uint32_t cmdCount = 0;
/* Handle no start option. */
if (xfer->flags & kLPI2C_TransferNoStartFlag)
{
if (xfer->direction == kLPI2C_Read)
{
/* Need to issue read command first. */
cmd[cmdCount++] = kRxDataCmd | LPI2C_MTDR_DATA(xfer->dataSize - 1);
}
}
else
{
/*
* Initial direction depends on whether a subaddress was provided, and of course the actual
* data transfer direction.
*/
lpi2c_direction_t direction = xfer->subaddressSize ? kLPI2C_Write : xfer->direction;
/* Start command. */
cmd[cmdCount++] =
(uint16_t)kStartCmd | (uint16_t)((uint16_t)((uint16_t)xfer->slaveAddress << 1U) | (uint16_t)direction);
/* Subaddress, MSB first. */
if (xfer->subaddressSize)
{
uint32_t subaddressRemaining = xfer->subaddressSize;
while (subaddressRemaining--)
{
uint8_t subaddressByte = (xfer->subaddress >> (8 * subaddressRemaining)) & 0xff;
cmd[cmdCount++] = subaddressByte;
}
}
/* Reads need special handling because we have to issue a read command and maybe a repeated start. */
if ((xfer->dataSize) && (xfer->direction == kLPI2C_Read))
{
/* Need to send repeated start if switching directions to read. */
if (direction == kLPI2C_Write)
{
cmd[cmdCount++] = (uint16_t)kStartCmd |
(uint16_t)((uint16_t)((uint16_t)xfer->slaveAddress << 1U) | (uint16_t)kLPI2C_Read);
}
/* Read command. */
cmd[cmdCount++] = kRxDataCmd | LPI2C_MTDR_DATA(xfer->dataSize - 1);
}
}
return cmdCount;
}
status_t LPI2C_MasterTransferEDMA(LPI2C_Type *base,
lpi2c_master_edma_handle_t *handle,
lpi2c_master_transfer_t *transfer)
{
status_t result;
assert(handle);
assert(transfer);
assert(transfer->subaddressSize <= sizeof(transfer->subaddress));
/* Return busy if another transaction is in progress. */
if (handle->isBusy)
{
return kStatus_LPI2C_Busy;
}
/* Return an error if the bus is already in use not by us. */
result = LPI2C_CheckForBusyBus(base);
if (result)
{
return result;
}
/* We're now busy. */
handle->isBusy = true;
/* Disable LPI2C IRQ and DMA sources while we configure stuff. */
LPI2C_MasterDisableInterrupts(base, kMasterIrqFlags);
LPI2C_MasterEnableDMA(base, false, false);
/* Clear all flags. */
LPI2C_MasterClearStatusFlags(base, kMasterClearFlags);
/* Save transfer into handle. */
handle->transfer = *transfer;
/* Generate commands to send. */
uint32_t commandCount = LPI2C_GenerateCommands(handle);
/* If the user is transmitting no data with no start or stop, then just go ahead and invoke the callback. */
if ((!commandCount) && (transfer->dataSize == 0))
{
if (handle->completionCallback)
{
handle->completionCallback(base, handle, kStatus_Success, handle->userData);
}
return kStatus_Success;
}
/* Reset DMA channels. */
EDMA_ResetChannel(handle->rx->base, handle->rx->channel);
if (FSL_FEATURE_LPI2C_HAS_SEPARATE_DMA_RX_TX_REQn(base))
{
EDMA_ResetChannel(handle->tx->base, handle->tx->channel);
}
/* Get a 32-byte aligned TCD pointer. */
edma_tcd_t *tcd = (edma_tcd_t *)((uint32_t)(&handle->tcds[1]) & (~ALIGN_32_MASK));
bool hasSendData = (transfer->direction == kLPI2C_Write) && (transfer->dataSize);
bool hasReceiveData = (transfer->direction == kLPI2C_Read) && (transfer->dataSize);
edma_transfer_config_t transferConfig;
edma_tcd_t *linkTcd = NULL;
/* Set up data transmit. */
if (hasSendData)
{
transferConfig.srcAddr = (uint32_t)transfer->data;
transferConfig.destAddr = (uint32_t)LPI2C_MasterGetTxFifoAddress(base);
transferConfig.srcTransferSize = kEDMA_TransferSize1Bytes;
transferConfig.destTransferSize = kEDMA_TransferSize1Bytes;
transferConfig.srcOffset = sizeof(uint8_t);
transferConfig.destOffset = 0;
transferConfig.minorLoopBytes = sizeof(uint8_t); /* TODO optimize to fill fifo */
transferConfig.majorLoopCounts = transfer->dataSize;
/* Store the initially configured eDMA minor byte transfer count into the LPI2C handle */
handle->nbytes = transferConfig.minorLoopBytes;
if (commandCount)
{
/* Create a software TCD, which will be chained after the commands. */
EDMA_TcdReset(tcd);
EDMA_TcdSetTransferConfig(tcd, &transferConfig, NULL);
EDMA_TcdEnableInterrupts(tcd, kEDMA_MajorInterruptEnable);
linkTcd = tcd;
}
else
{
/* User is only transmitting data with no required commands, so this transfer can stand alone. */
EDMA_SetTransferConfig(handle->tx->base, handle->tx->channel, &transferConfig, NULL);
EDMA_EnableChannelInterrupts(handle->tx->base, handle->tx->channel, kEDMA_MajorInterruptEnable);
}
}
else if (hasReceiveData)
{
/* Set up data receive. */
transferConfig.srcAddr = (uint32_t)LPI2C_MasterGetRxFifoAddress(base);
transferConfig.destAddr = (uint32_t)transfer->data;
transferConfig.srcTransferSize = kEDMA_TransferSize1Bytes;
transferConfig.destTransferSize = kEDMA_TransferSize1Bytes;
transferConfig.srcOffset = 0;
transferConfig.destOffset = sizeof(uint8_t);
transferConfig.minorLoopBytes = sizeof(uint8_t); /* TODO optimize to empty fifo */
transferConfig.majorLoopCounts = transfer->dataSize;
/* Store the initially configured eDMA minor byte transfer count into the LPI2C handle */
handle->nbytes = transferConfig.minorLoopBytes;
if (FSL_FEATURE_LPI2C_HAS_SEPARATE_DMA_RX_TX_REQn(base) || (!commandCount))
{
/* We can put this receive transfer on its own DMA channel. */
EDMA_SetTransferConfig(handle->rx->base, handle->rx->channel, &transferConfig, NULL);
EDMA_EnableChannelInterrupts(handle->rx->base, handle->rx->channel, kEDMA_MajorInterruptEnable);
}
else
{
/* For shared rx/tx DMA requests when there are commands, create a software TCD which will be */
/* chained onto the commands transfer. */
EDMA_TcdReset(tcd);
EDMA_TcdSetTransferConfig(tcd, &transferConfig, NULL);
EDMA_TcdEnableInterrupts(tcd, kEDMA_MajorInterruptEnable);
linkTcd = tcd;
}
}
else
{
/* No data to send */
}
/* Set up commands transfer. */
if (commandCount)
{
transferConfig.srcAddr = (uint32_t)handle->commandBuffer;
transferConfig.destAddr = (uint32_t)LPI2C_MasterGetTxFifoAddress(base);
transferConfig.srcTransferSize = kEDMA_TransferSize2Bytes;
transferConfig.destTransferSize = kEDMA_TransferSize2Bytes;
transferConfig.srcOffset = sizeof(uint16_t);
transferConfig.destOffset = 0;
transferConfig.minorLoopBytes = sizeof(uint16_t); /* TODO optimize to fill fifo */
transferConfig.majorLoopCounts = commandCount;
EDMA_SetTransferConfig(handle->tx->base, handle->tx->channel, &transferConfig, linkTcd);
}
/* Start DMA transfer. */
if (hasReceiveData || !FSL_FEATURE_LPI2C_HAS_SEPARATE_DMA_RX_TX_REQn(base))
{
EDMA_StartTransfer(handle->rx);
}
if ((hasSendData || commandCount) && FSL_FEATURE_LPI2C_HAS_SEPARATE_DMA_RX_TX_REQn(base))
{
EDMA_StartTransfer(handle->tx);
}
/* Enable DMA in both directions. This actually kicks of the transfer. */
LPI2C_MasterEnableDMA(base, true, true);
return result;
}
status_t LPI2C_MasterTransferGetCountEDMA(LPI2C_Type *base, lpi2c_master_edma_handle_t *handle, size_t *count)
{
assert(handle);
if (!count)
{
return kStatus_InvalidArgument;
}
/* Catch when there is not an active transfer. */
if (!handle->isBusy)
{
*count = 0;
return kStatus_NoTransferInProgress;
}
uint32_t remaining = handle->transfer.dataSize;
/* If the DMA is still on a commands transfer that chains to the actual data transfer, */
/* we do nothing and return the number of transferred bytes as zero. */
if (handle->tx->base->TCD[handle->tx->channel].DLAST_SGA == 0)
{
if (handle->transfer.direction == kLPI2C_Write)
{
remaining =
(uint32_t)handle->nbytes * EDMA_GetRemainingMajorLoopCount(handle->tx->base, handle->tx->channel);
}
else
{
remaining =
(uint32_t)handle->nbytes * EDMA_GetRemainingMajorLoopCount(handle->rx->base, handle->rx->channel);
}
}
*count = handle->transfer.dataSize - remaining;
return kStatus_Success;
}
status_t LPI2C_MasterTransferAbortEDMA(LPI2C_Type *base, lpi2c_master_edma_handle_t *handle)
{
/* Catch when there is not an active transfer. */
if (!handle->isBusy)
{
return kStatus_LPI2C_Idle;
}
/* Terminate DMA transfers. */
EDMA_AbortTransfer(handle->rx);
if (FSL_FEATURE_LPI2C_HAS_SEPARATE_DMA_RX_TX_REQn(base))
{
EDMA_AbortTransfer(handle->tx);
}
/* Reset fifos. */
base->MCR |= LPI2C_MCR_RRF_MASK | LPI2C_MCR_RTF_MASK;
/* Send a stop command to finalize the transfer. */
base->MTDR = kStopCmd;
/* Reset handle. */
handle->isBusy = false;
return kStatus_Success;
}
/*!
* @brief DMA completion callback.
* @param dmaHandle DMA channel handle for the channel that completed.
* @param userData User data associated with the channel handle. For this callback, the user data is the
* LPI2C DMA driver handle.
* @param isTransferDone Whether the DMA transfer has completed.
* @param tcds Number of TCDs that completed.
*/
static void LPI2C_MasterEDMACallback(edma_handle_t *dmaHandle, void *userData, bool isTransferDone, uint32_t tcds)
{
lpi2c_master_edma_handle_t *handle = (lpi2c_master_edma_handle_t *)userData;
if (!handle)
{
return;
}
/* Check for errors. */
status_t result = LPI2C_MasterCheckAndClearError(handle->base, LPI2C_MasterGetStatusFlags(handle->base));
/* Done with this transaction. */
handle->isBusy = false;
if (!(handle->transfer.flags & kLPI2C_TransferNoStopFlag))
{
/* Send a stop command to finalize the transfer. */
handle->base->MTDR = kStopCmd;
}
/* Invoke callback. */
if (handle->completionCallback)
{
handle->completionCallback(handle->base, handle, result, handle->userData);
}
}

View File

@ -0,0 +1,151 @@
/*
* Copyright (c) 2015, Freescale Semiconductor, Inc.
* Copyright 2016-2017 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef _FSL_LPI2C_EDMA_H_
#define _FSL_LPI2C_EDMA_H_
#include "fsl_lpi2c.h"
#include "fsl_edma.h"
/*******************************************************************************
* Definitions
******************************************************************************/
/*!
* @addtogroup lpi2c_master_edma_driver
* @{
*/
/* Forward declaration of the transfer descriptor and handle typedefs. */
typedef struct _lpi2c_master_edma_handle lpi2c_master_edma_handle_t;
/*!
* @brief Master DMA completion callback function pointer type.
*
* This callback is used only for the non-blocking master transfer API. Specify the callback you wish to use
* in the call to LPI2C_MasterCreateEDMAHandle().
*
* @param base The LPI2C peripheral base address.
* @param handle Handle associated with the completed transfer.
* @param completionStatus Either #kStatus_Success or an error code describing how the transfer completed.
* @param userData Arbitrary pointer-sized value passed from the application.
*/
typedef void (*lpi2c_master_edma_transfer_callback_t)(LPI2C_Type *base,
lpi2c_master_edma_handle_t *handle,
status_t completionStatus,
void *userData);
/*!
* @brief Driver handle for master DMA APIs.
* @note The contents of this structure are private and subject to change.
*/
struct _lpi2c_master_edma_handle
{
LPI2C_Type *base; /*!< LPI2C base pointer. */
bool isBusy; /*!< Transfer state machine current state. */
uint8_t nbytes; /*!< eDMA minor byte transfer count initially configured. */
uint16_t commandBuffer[7]; /*!< LPI2C command sequence. */
lpi2c_master_transfer_t transfer; /*!< Copy of the current transfer info. */
lpi2c_master_edma_transfer_callback_t completionCallback; /*!< Callback function pointer. */
void *userData; /*!< Application data passed to callback. */
edma_handle_t *rx; /*!< Handle for receive DMA channel. */
edma_handle_t *tx; /*!< Handle for transmit DMA channel. */
edma_tcd_t tcds[2]; /*!< Software TCD. Two are allocated to provide enough room to align to 32-bytes. */
};
/*! @} */
/*******************************************************************************
* API
******************************************************************************/
#if defined(__cplusplus)
extern "C" {
#endif
/*!
* @addtogroup lpi2c_master_edma_driver
* @{
*/
/*! @name Master DMA */
/*@{*/
/*!
* @brief Create a new handle for the LPI2C master DMA APIs.
*
* The creation of a handle is for use with the DMA APIs. Once a handle
* is created, there is not a corresponding destroy handle. If the user wants to
* terminate a transfer, the LPI2C_MasterTransferAbortEDMA() API shall be called.
*
* For devices where the LPI2C send and receive DMA requests are OR'd together, the @a txDmaHandle
* parameter is ignored and may be set to NULL.
*
* @param base The LPI2C peripheral base address.
* @param[out] handle Pointer to the LPI2C master driver handle.
* @param rxDmaHandle Handle for the eDMA receive channel. Created by the user prior to calling this function.
* @param txDmaHandle Handle for the eDMA transmit channel. Created by the user prior to calling this function.
* @param callback User provided pointer to the asynchronous callback function.
* @param userData User provided pointer to the application callback data.
*/
void LPI2C_MasterCreateEDMAHandle(LPI2C_Type *base,
lpi2c_master_edma_handle_t *handle,
edma_handle_t *rxDmaHandle,
edma_handle_t *txDmaHandle,
lpi2c_master_edma_transfer_callback_t callback,
void *userData);
/*!
* @brief Performs a non-blocking DMA-based transaction on the I2C bus.
*
* The callback specified when the @a handle was created is invoked when the transaction has
* completed.
*
* @param base The LPI2C peripheral base address.
* @param handle Pointer to the LPI2C master driver handle.
* @param transfer The pointer to the transfer descriptor.
* @retval #kStatus_Success The transaction was started successfully.
* @retval #kStatus_LPI2C_Busy Either another master is currently utilizing the bus, or another DMA
* transaction is already in progress.
*/
status_t LPI2C_MasterTransferEDMA(LPI2C_Type *base,
lpi2c_master_edma_handle_t *handle,
lpi2c_master_transfer_t *transfer);
/*!
* @brief Returns number of bytes transferred so far.
*
* @param base The LPI2C peripheral base address.
* @param handle Pointer to the LPI2C master driver handle.
* @param[out] count Number of bytes transferred so far by the non-blocking transaction.
* @retval #kStatus_Success
* @retval #kStatus_NoTransferInProgress There is not a DMA transaction currently in progress.
*/
status_t LPI2C_MasterTransferGetCountEDMA(LPI2C_Type *base, lpi2c_master_edma_handle_t *handle, size_t *count);
/*!
* @brief Terminates a non-blocking LPI2C master transmission early.
*
* @note It is not safe to call this function from an IRQ handler that has a higher priority than the
* eDMA peripheral's IRQ priority.
*
* @param base The LPI2C peripheral base address.
* @param handle Pointer to the LPI2C master driver handle.
* @retval #kStatus_Success A transaction was successfully aborted.
* @retval #kStatus_LPI2C_Idle There is not a DMA transaction currently in progress.
*/
status_t LPI2C_MasterTransferAbortEDMA(LPI2C_Type *base, lpi2c_master_edma_handle_t *handle);
/*@}*/
/*! @} */
#if defined(__cplusplus)
}
#endif
#endif /* _FSL_LPI2C_EDMA_H_ */

View File

@ -0,0 +1,134 @@
/*
* Copyright (c) 2015, Freescale Semiconductor, Inc.
* Copyright 2016-2017 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include "fsl_lpit.h"
/*******************************************************************************
* Variables
******************************************************************************/
/*! @brief Array to map LPIT instance number to base pointer. */
static LPIT_Type* const s_lpitBases[] = LPIT_BASE_PTRS;
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
/*! @brief Clock array name */
static const clock_ip_name_t s_lpitClock[] = LPIT_CLOCKS;
#if defined(LPIT_PERIPH_CLOCKS)
/* Array of LPIT functional clock name. */
static const clock_ip_name_t s_lpitPeriphClocks[] = LPIT_PERIPH_CLOCKS;
#endif
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
/*******************************************************************************
* Prototypes
******************************************************************************/
/*!
* @brief Get the instance for LPIT module.
*
* @param base LPIT base address
*/
uint32_t LPIT_GetInstance(LPIT_Type* base);
/*******************************************************************************
* Code
******************************************************************************/
uint32_t LPIT_GetInstance(LPIT_Type* base)
{
uint32_t instance;
/* Find the instance index from base address mappings. */
for (instance = 0; instance < ARRAY_SIZE(s_lpitBases); instance++)
{
if (s_lpitBases[instance] == base)
{
break;
}
}
assert(instance < ARRAY_SIZE(s_lpitBases));
return instance;
}
void LPIT_Init(LPIT_Type* base, const lpit_config_t* config)
{
assert(config);
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
uint32_t instance = LPIT_GetInstance(base);
/* Enable the clock */
CLOCK_EnableClock(s_lpitClock[instance]);
#if defined(LPIT_PERIPH_CLOCKS)
CLOCK_EnableClock(s_lpitPeriphClocks[instance]);
#endif
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
/* Reset the timer channels and registers except the MCR register */
LPIT_Reset(base);
/* Setup timer operation in debug and doze modes and enable the module */
base->MCR =
(LPIT_MCR_DBG_EN(config->enableRunInDebug) | LPIT_MCR_DOZE_EN(config->enableRunInDoze) | LPIT_MCR_M_CEN_MASK);
}
void LPIT_Deinit(LPIT_Type* base)
{
/* Disable the module */
base->MCR &= ~LPIT_MCR_M_CEN_MASK;
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
uint32_t instance = LPIT_GetInstance(base);
/* Disable the clock */
CLOCK_DisableClock(s_lpitClock[instance]);
#if defined(LPIT_PERIPH_CLOCKS)
CLOCK_DisableClock(s_lpitPeriphClocks[instance]);
#endif
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
}
void LPIT_GetDefaultConfig(lpit_config_t* config)
{
assert(config);
/* Timers are stopped in debug mode */
config->enableRunInDebug = false;
/* Timers are stopped in doze mode */
config->enableRunInDoze = false;
}
status_t LPIT_SetupChannel(LPIT_Type* base, lpit_chnl_t channel, const lpit_chnl_params_t* chnlSetup)
{
assert(chnlSetup);
uint32_t reg = 0;
/* Cannot assert the chain bit for channel 0 */
if ((channel == kLPIT_Chnl_0) && (chnlSetup->chainChannel == true))
{
return kStatus_Fail;
}
/* Setup the channel counters operation mode, trigger operation, chain mode */
reg = (LPIT_TCTRL_MODE(chnlSetup->timerMode) | LPIT_TCTRL_TRG_SRC(chnlSetup->triggerSource) |
LPIT_TCTRL_TRG_SEL(chnlSetup->triggerSelect) | LPIT_TCTRL_TROT(chnlSetup->enableReloadOnTrigger) |
LPIT_TCTRL_TSOI(chnlSetup->enableStopOnTimeout) | LPIT_TCTRL_TSOT(chnlSetup->enableStartOnTrigger) |
LPIT_TCTRL_CHAIN(chnlSetup->chainChannel));
base->CHANNEL[channel].TCTRL = reg;
return kStatus_Success;
}

View File

@ -0,0 +1,373 @@
/*
* Copyright (c) 2015, Freescale Semiconductor, Inc.
* Copyright 2016-2017 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef _FSL_LPIT_H_
#define _FSL_LPIT_H_
#include "fsl_common.h"
/*!
* @addtogroup lpit
* @{
*/
/*******************************************************************************
* Definitions
******************************************************************************/
/*! @name Driver version */
/*@{*/
#define FSL_LPIT_DRIVER_VERSION (MAKE_VERSION(2, 0, 0)) /*!< Version 2.0.0 */
/*@{*/
/*!
* @brief List of LPIT channels
* @note Actual number of available channels is SoC-dependent
*/
typedef enum _lpit_chnl
{
kLPIT_Chnl_0 = 0U, /*!< LPIT channel number 0*/
kLPIT_Chnl_1, /*!< LPIT channel number 1 */
kLPIT_Chnl_2, /*!< LPIT channel number 2 */
kLPIT_Chnl_3, /*!< LPIT channel number 3 */
} lpit_chnl_t;
/*! @brief Mode options available for the LPIT timer. */
typedef enum _lpit_timer_modes
{
kLPIT_PeriodicCounter = 0U, /*!< Use the all 32-bits, counter loads and decrements to zero */
kLPIT_DualPeriodicCounter, /*!< Counter loads, lower 16-bits decrement to zero, then
upper 16-bits decrement */
kLPIT_TriggerAccumulator, /*!< Counter loads on first trigger and decrements on each trigger */
kLPIT_InputCapture /*!< Counter loads with 0xFFFFFFFF, decrements to zero. It stores
the inverse of the current value when a input trigger is detected */
} lpit_timer_modes_t;
/*!
* @brief Trigger options available.
*
* This is used for both internal and external trigger sources. The actual trigger options
* available is SoC-specific, user should refer to the reference manual.
*/
typedef enum _lpit_trigger_select
{
kLPIT_Trigger_TimerChn0 = 0U, /*!< Channel 0 is selected as a trigger source */
kLPIT_Trigger_TimerChn1, /*!< Channel 1 is selected as a trigger source */
kLPIT_Trigger_TimerChn2, /*!< Channel 2 is selected as a trigger source */
kLPIT_Trigger_TimerChn3, /*!< Channel 3 is selected as a trigger source */
kLPIT_Trigger_TimerChn4, /*!< Channel 4 is selected as a trigger source */
kLPIT_Trigger_TimerChn5, /*!< Channel 5 is selected as a trigger source */
kLPIT_Trigger_TimerChn6, /*!< Channel 6 is selected as a trigger source */
kLPIT_Trigger_TimerChn7, /*!< Channel 7 is selected as a trigger source */
kLPIT_Trigger_TimerChn8, /*!< Channel 8 is selected as a trigger source */
kLPIT_Trigger_TimerChn9, /*!< Channel 9 is selected as a trigger source */
kLPIT_Trigger_TimerChn10, /*!< Channel 10 is selected as a trigger source */
kLPIT_Trigger_TimerChn11, /*!< Channel 11 is selected as a trigger source */
kLPIT_Trigger_TimerChn12, /*!< Channel 12 is selected as a trigger source */
kLPIT_Trigger_TimerChn13, /*!< Channel 13 is selected as a trigger source */
kLPIT_Trigger_TimerChn14, /*!< Channel 14 is selected as a trigger source */
kLPIT_Trigger_TimerChn15 /*!< Channel 15 is selected as a trigger source */
} lpit_trigger_select_t;
/*! @brief Trigger source options available */
typedef enum _lpit_trigger_source
{
kLPIT_TriggerSource_External = 0U, /*!< Use external trigger input */
kLPIT_TriggerSource_Internal /*!< Use internal trigger */
} lpit_trigger_source_t;
/*!
* @brief List of LPIT interrupts.
*
* @note Number of timer channels are SoC-specific. See the SoC Reference Manual.
*/
typedef enum _lpit_interrupt_enable
{
kLPIT_Channel0TimerInterruptEnable = (1U << 0), /*!< Channel 0 Timer interrupt */
kLPIT_Channel1TimerInterruptEnable = (1U << 1), /*!< Channel 1 Timer interrupt */
kLPIT_Channel2TimerInterruptEnable = (1U << 2), /*!< Channel 2 Timer interrupt */
kLPIT_Channel3TimerInterruptEnable = (1U << 3), /*!< Channel 3 Timer interrupt */
} lpit_interrupt_enable_t;
/*!
* @brief List of LPIT status flags
*
* @note Number of timer channels are SoC-specific. See the SoC Reference Manual.
*/
typedef enum _lpit_status_flags
{
kLPIT_Channel0TimerFlag = (1U << 0), /*!< Channel 0 Timer interrupt flag */
kLPIT_Channel1TimerFlag = (1U << 1), /*!< Channel 1 Timer interrupt flag */
kLPIT_Channel2TimerFlag = (1U << 2), /*!< Channel 2 Timer interrupt flag */
kLPIT_Channel3TimerFlag = (1U << 3), /*!< Channel 3 Timer interrupt flag */
} lpit_status_flags_t;
/*! @brief Structure to configure the channel timer. */
typedef struct _lpit_chnl_params
{
bool chainChannel; /*!< true: Timer chained to previous timer;
false: Timer not chained */
lpit_timer_modes_t timerMode; /*!< Timers mode of operation. */
lpit_trigger_select_t triggerSelect; /*!< Trigger selection for the timer */
lpit_trigger_source_t triggerSource; /*!< Decides if we use external or internal trigger. */
bool enableReloadOnTrigger; /*!< true: Timer reloads when a trigger is detected;
false: No effect */
bool enableStopOnTimeout; /*!< true: Timer will stop after timeout;
false: does not stop after timeout */
bool enableStartOnTrigger; /*!< true: Timer starts when a trigger is detected;
false: decrement immediately */
} lpit_chnl_params_t;
/*!
* @brief LPIT configuration structure
*
* This structure holds the configuration settings for the LPIT peripheral. To initialize this
* structure to reasonable defaults, call the LPIT_GetDefaultConfig() function and pass a
* pointer to the configuration structure instance.
*
* The configuration structure can be made constant so as to reside in flash.
*/
typedef struct _lpit_config
{
bool enableRunInDebug; /*!< true: Timers run in debug mode; false: Timers stop in debug mode */
bool enableRunInDoze; /*!< true: Timers run in doze mode; false: Timers stop in doze mode */
} lpit_config_t;
/*******************************************************************************
* API
******************************************************************************/
#if defined(__cplusplus)
extern "C" {
#endif
/*!
* @name Initialization and deinitialization
* @{
*/
/*!
* @brief Ungates the LPIT clock and configures the peripheral for a basic operation.
*
* This function issues a software reset to reset all channels and registers except the Module
* Control register.
*
* @note This API should be called at the beginning of the application using the LPIT driver.
*
* @param base LPIT peripheral base address.
* @param config Pointer to the user configuration structure.
*/
void LPIT_Init(LPIT_Type* base, const lpit_config_t* config);
/*!
* @brief Disables the module and gates the LPIT clock.
*
* @param base LPIT peripheral base address.
*/
void LPIT_Deinit(LPIT_Type* base);
/*!
* @brief Fills in the LPIT configuration structure with default settings.
*
* The default values are:
* @code
* config->enableRunInDebug = false;
* config->enableRunInDoze = false;
* @endcode
* @param config Pointer to the user configuration structure.
*/
void LPIT_GetDefaultConfig(lpit_config_t* config);
/*!
* @brief Sets up an LPIT channel based on the user's preference.
*
* This function sets up the operation mode to one of the options available in the
* enumeration ::lpit_timer_modes_t. It sets the trigger source as either internal or external,
* trigger selection and the timers behaviour when a timeout occurs. It also chains
* the timer if a prior timer if requested by the user.
*
* @param base LPIT peripheral base address.
* @param channel Channel that is being configured.
* @param chnlSetup Configuration parameters.
*/
status_t LPIT_SetupChannel(LPIT_Type* base, lpit_chnl_t channel, const lpit_chnl_params_t* chnlSetup);
/*! @}*/
/*!
* @name Interrupt Interface
* @{
*/
/*!
* @brief Enables the selected PIT interrupts.
*
* @param base LPIT peripheral base address.
* @param mask The interrupts to enable. This is a logical OR of members of the
* enumeration ::lpit_interrupt_enable_t
*/
static inline void LPIT_EnableInterrupts(LPIT_Type* base, uint32_t mask)
{
base->MIER |= mask;
}
/*!
* @brief Disables the selected PIT interrupts.
*
* @param base LPIT peripheral base address.
* @param mask The interrupts to enable. This is a logical OR of members of the
* enumeration ::lpit_interrupt_enable_t
*/
static inline void LPIT_DisableInterrupts(LPIT_Type* base, uint32_t mask)
{
base->MIER &= ~mask;
}
/*!
* @brief Gets the enabled LPIT interrupts.
*
* @param base LPIT peripheral base address.
*
* @return The enabled interrupts. This is the logical OR of members of the
* enumeration ::lpit_interrupt_enable_t
*/
static inline uint32_t LPIT_GetEnabledInterrupts(LPIT_Type* base)
{
return base->MIER;
}
/*! @}*/
/*!
* @name Status Interface
* @{
*/
/*!
* @brief Gets the LPIT status flags.
*
* @param base LPIT peripheral base address.
*
* @return The status flags. This is the logical OR of members of the
* enumeration ::lpit_status_flags_t
*/
static inline uint32_t LPIT_GetStatusFlags(LPIT_Type* base)
{
return base->MSR;
}
/*!
* @brief Clears the LPIT status flags.
*
* @param base LPIT peripheral base address.
* @param mask The status flags to clear. This is a logical OR of members of the
* enumeration ::lpit_status_flags_t
*/
static inline void LPIT_ClearStatusFlags(LPIT_Type* base, uint32_t mask)
{
/* Writing a 1 to the status bit will clear the flag */
base->MSR = mask;
}
/*! @}*/
/*!
* @name Read and Write the timer period
* @{
*/
/*!
* @brief Sets the timer period in units of count.
*
* Timers begin counting down from the value set by this function until it reaches 0, at which point
* it generates an interrupt and loads this register value again.
* Writing a new value to this register does not restart the timer. Instead, the value
* is loaded after the timer expires.
*
* @note User can call the utility macros provided in fsl_common.h to convert to ticks.
*
* @param base LPIT peripheral base address.
* @param channel Timer channel number.
* @param ticks Timer period in units of ticks.
*/
static inline void LPIT_SetTimerPeriod(LPIT_Type* base, lpit_chnl_t channel, uint32_t ticks)
{
base->CHANNEL[channel].TVAL = ticks;
}
/*!
* @brief Reads the current timer counting value.
*
* This function returns the real-time timer counting value, in a range from 0 to a
* timer period.
*
* @note User can call the utility macros provided in fsl_common.h to convert ticks to microseconds or milliseconds.
*
* @param base LPIT peripheral base address.
* @param channel Timer channel number.
*
* @return Current timer counting value in ticks.
*/
static inline uint32_t LPIT_GetCurrentTimerCount(LPIT_Type* base, lpit_chnl_t channel)
{
return base->CHANNEL[channel].CVAL;
}
/*! @}*/
/*!
* @name Timer Start and Stop
* @{
*/
/*!
* @brief Starts the timer counting.
*
* After calling this function, timers load the period value and count down to 0. When the timer
* reaches 0, it generates a trigger pulse and sets the timeout interrupt flag.
*
* @param base LPIT peripheral base address.
* @param channel Timer channel number.
*/
static inline void LPIT_StartTimer(LPIT_Type* base, lpit_chnl_t channel)
{
base->SETTEN |= (LPIT_SETTEN_SET_T_EN_0_MASK << channel);
}
/*!
* @brief Stops the timer counting.
*
* @param base LPIT peripheral base address.
* @param channel Timer channel number.
*/
static inline void LPIT_StopTimer(LPIT_Type* base, lpit_chnl_t channel)
{
base->CLRTEN |= (LPIT_CLRTEN_CLR_T_EN_0_MASK << channel);
}
/*! @}*/
/*!
* @brief Performs a software reset on the LPIT module.
*
* This resets all channels and registers except the Module Control Register.
*
* @param base LPIT peripheral base address.
*/
static inline void LPIT_Reset(LPIT_Type* base)
{
base->MCR |= LPIT_MCR_SW_RST_MASK;
base->MCR &= ~LPIT_MCR_SW_RST_MASK;
}
#if defined(__cplusplus)
}
#endif
/*! @}*/
#endif /* __FSL_LPIT_H__ */

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,297 @@
/*
* Copyright (c) 2015, Freescale Semiconductor, Inc.
* Copyright 2016-2017 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef _FSL_LPSPI_EDMA_H_
#define _FSL_LPSPI_EDMA_H_
#include "fsl_lpspi.h"
#include "fsl_edma.h"
/*!
* @addtogroup lpspi_edma_driver
* @{
*/
/***********************************************************************************************************************
* Definitions
**********************************************************************************************************************/
/*!
* @brief Forward declaration of the _lpspi_master_edma_handle typedefs.
*/
typedef struct _lpspi_master_edma_handle lpspi_master_edma_handle_t;
/*!
* @brief Forward declaration of the _lpspi_slave_edma_handle typedefs.
*/
typedef struct _lpspi_slave_edma_handle lpspi_slave_edma_handle_t;
/*!
* @brief Completion callback function pointer type.
*
* @param base LPSPI peripheral base address.
* @param handle Pointer to the handle for the LPSPI master.
* @param status Success or error code describing whether the transfer completed.
* @param userData Arbitrary pointer-dataSized value passed from the application.
*/
typedef void (*lpspi_master_edma_transfer_callback_t)(LPSPI_Type *base,
lpspi_master_edma_handle_t *handle,
status_t status,
void *userData);
/*!
* @brief Completion callback function pointer type.
*
* @param base LPSPI peripheral base address.
* @param handle Pointer to the handle for the LPSPI slave.
* @param status Success or error code describing whether the transfer completed.
* @param userData Arbitrary pointer-dataSized value passed from the application.
*/
typedef void (*lpspi_slave_edma_transfer_callback_t)(LPSPI_Type *base,
lpspi_slave_edma_handle_t *handle,
status_t status,
void *userData);
/*! @brief LPSPI master eDMA transfer handle structure used for transactional API. */
struct _lpspi_master_edma_handle
{
volatile bool isPcsContinuous; /*!< Is PCS continuous in transfer. */
volatile bool isByteSwap; /*!< A flag that whether should byte swap. */
volatile uint8_t fifoSize; /*!< FIFO dataSize. */
volatile uint8_t rxWatermark; /*!< Rx watermark. */
volatile uint8_t bytesEachWrite; /*!< Bytes for each write TDR . */
volatile uint8_t bytesEachRead; /*!< Bytes for each read RDR . */
volatile uint8_t bytesLastRead; /*!< Bytes for last read RDR . */
volatile uint8_t isThereExtraRxBytes; /*!< Is there extra RX byte. */
uint8_t *volatile txData; /*!< Send buffer. */
uint8_t *volatile rxData; /*!< Receive buffer. */
volatile size_t txRemainingByteCount; /*!< Number of bytes remaining to send.*/
volatile size_t rxRemainingByteCount; /*!< Number of bytes remaining to receive.*/
volatile uint32_t writeRegRemainingTimes; /*!< Write TDR register remaining times. */
volatile uint32_t readRegRemainingTimes; /*!< Read RDR register remaining times. */
uint32_t totalByteCount; /*!< Number of transfer bytes*/
uint32_t txBuffIfNull; /*!< Used if there is not txData for DMA purpose.*/
uint32_t rxBuffIfNull; /*!< Used if there is not rxData for DMA purpose.*/
uint32_t transmitCommand; /*!< Used to write TCR for DMA purpose.*/
volatile uint8_t state; /*!< LPSPI transfer state , _lpspi_transfer_state.*/
uint8_t nbytes; /*!< eDMA minor byte transfer count initially configured. */
lpspi_master_edma_transfer_callback_t callback; /*!< Completion callback. */
void *userData; /*!< Callback user data. */
edma_handle_t *edmaRxRegToRxDataHandle; /*!<edma_handle_t handle point used for RxReg to RxData buff*/
edma_handle_t *edmaTxDataToTxRegHandle; /*!<edma_handle_t handle point used for TxData to TxReg buff*/
edma_tcd_t lpspiSoftwareTCD[3]; /*!<SoftwareTCD , internal used*/
};
/*! @brief LPSPI slave eDMA transfer handle structure used for transactional API.*/
struct _lpspi_slave_edma_handle
{
volatile bool isByteSwap; /*!< A flag that whether should byte swap. */
volatile uint8_t fifoSize; /*!< FIFO dataSize. */
volatile uint8_t rxWatermark; /*!< Rx watermark. */
volatile uint8_t bytesEachWrite; /*!< Bytes for each write TDR . */
volatile uint8_t bytesEachRead; /*!< Bytes for each read RDR . */
volatile uint8_t bytesLastRead; /*!< Bytes for last read RDR . */
volatile uint8_t isThereExtraRxBytes; /*!< Is there extra RX byte. */
uint8_t nbytes; /*!< eDMA minor byte transfer count initially configured. */
uint8_t *volatile txData; /*!< Send buffer. */
uint8_t *volatile rxData; /*!< Receive buffer. */
volatile size_t txRemainingByteCount; /*!< Number of bytes remaining to send.*/
volatile size_t rxRemainingByteCount; /*!< Number of bytes remaining to receive.*/
volatile uint32_t writeRegRemainingTimes; /*!< Write TDR register remaining times . */
volatile uint32_t readRegRemainingTimes; /*!< Read RDR register remaining times . */
uint32_t totalByteCount; /*!< Number of transfer bytes*/
uint32_t txBuffIfNull; /*!< Used if there is not txData for DMA purpose.*/
uint32_t rxBuffIfNull; /*!< Used if there is not rxData for DMA purpose.*/
volatile uint8_t state; /*!< LPSPI transfer state.*/
uint32_t errorCount; /*!< Error count for slave transfer.*/
lpspi_slave_edma_transfer_callback_t callback; /*!< Completion callback. */
void *userData; /*!< Callback user data. */
edma_handle_t *edmaRxRegToRxDataHandle; /*!<edma_handle_t handle point used for RxReg to RxData buff*/
edma_handle_t *edmaTxDataToTxRegHandle; /*!<edma_handle_t handle point used for TxData to TxReg*/
edma_tcd_t lpspiSoftwareTCD[2]; /*!<SoftwareTCD , internal used*/
};
/***********************************************************************************************************************
* API
**********************************************************************************************************************/
#if defined(__cplusplus)
extern "C" {
#endif /*_cplusplus*/
/*Transactional APIs*/
/*!
* @brief Initializes the LPSPI master eDMA handle.
*
* This function initializes the LPSPI eDMA handle which can be used for other LPSPI transactional APIs. Usually, for a
* specified LPSPI instance, call this API once to get the initialized handle.
*
* Note that the LPSPI eDMA has a separated (Rx and Rx as two sources) or shared (Rx and Tx are the same source) DMA
* request source.
* (1) For a separated DMA request source, enable and set the Rx DMAMUX source for edmaRxRegToRxDataHandle and
* Tx DMAMUX source for edmaIntermediaryToTxRegHandle.
* (2) For a shared DMA request source, enable and set the Rx/Rx DMAMUX source for edmaRxRegToRxDataHandle.
*
* @param base LPSPI peripheral base address.
* @param handle LPSPI handle pointer to lpspi_master_edma_handle_t.
* @param callback LPSPI callback.
* @param userData callback function parameter.
* @param edmaRxRegToRxDataHandle edmaRxRegToRxDataHandle pointer to edma_handle_t.
* @param edmaTxDataToTxRegHandle edmaTxDataToTxRegHandle pointer to edma_handle_t.
*/
void LPSPI_MasterTransferCreateHandleEDMA(LPSPI_Type *base,
lpspi_master_edma_handle_t *handle,
lpspi_master_edma_transfer_callback_t callback,
void *userData,
edma_handle_t *edmaRxRegToRxDataHandle,
edma_handle_t *edmaTxDataToTxRegHandle);
/*!
* @brief LPSPI master transfer data using eDMA.
*
* This function transfers data using eDMA. This is a non-blocking function, which returns right away. When all data
* is transferred, the callback function is called.
*
* Note:
* The transfer data size should be an integer multiple of bytesPerFrame if bytesPerFrame is less than or equal to 4.
* For bytesPerFrame greater than 4:
* The transfer data size should be equal to bytesPerFrame if the bytesPerFrame is not an integer multiple of 4.
* Otherwise, the transfer data size can be an integer multiple of bytesPerFrame.
*
* @param base LPSPI peripheral base address.
* @param handle pointer to lpspi_master_edma_handle_t structure which stores the transfer state.
* @param transfer pointer to lpspi_transfer_t structure.
* @return status of status_t.
*/
status_t LPSPI_MasterTransferEDMA(LPSPI_Type *base, lpspi_master_edma_handle_t *handle, lpspi_transfer_t *transfer);
/*!
* @brief LPSPI master aborts a transfer which is using eDMA.
*
* This function aborts a transfer which is using eDMA.
*
* @param base LPSPI peripheral base address.
* @param handle pointer to lpspi_master_edma_handle_t structure which stores the transfer state.
*/
void LPSPI_MasterTransferAbortEDMA(LPSPI_Type *base, lpspi_master_edma_handle_t *handle);
/*!
* @brief Gets the master eDMA transfer remaining bytes.
*
* This function gets the master eDMA transfer remaining bytes.
*
* @param base LPSPI peripheral base address.
* @param handle pointer to lpspi_master_edma_handle_t structure which stores the transfer state.
* @param count Number of bytes transferred so far by the EDMA transaction.
* @return status of status_t.
*/
status_t LPSPI_MasterTransferGetCountEDMA(LPSPI_Type *base, lpspi_master_edma_handle_t *handle, size_t *count);
/*!
* @brief Initializes the LPSPI slave eDMA handle.
*
* This function initializes the LPSPI eDMA handle which can be used for other LPSPI transactional APIs. Usually, for a
* specified LPSPI instance, call this API once to get the initialized handle.
*
* Note that LPSPI eDMA has a separated (Rx and Tx as two sources) or shared (Rx and Tx as the same source) DMA request
* source.
*
* (1) For a separated DMA request source, enable and set the Rx DMAMUX source for edmaRxRegToRxDataHandle and
* Tx DMAMUX source for edmaTxDataToTxRegHandle.
* (2) For a shared DMA request source, enable and set the Rx/Rx DMAMUX source for edmaRxRegToRxDataHandle .
*
* @param base LPSPI peripheral base address.
* @param handle LPSPI handle pointer to lpspi_slave_edma_handle_t.
* @param callback LPSPI callback.
* @param userData callback function parameter.
* @param edmaRxRegToRxDataHandle edmaRxRegToRxDataHandle pointer to edma_handle_t.
* @param edmaTxDataToTxRegHandle edmaTxDataToTxRegHandle pointer to edma_handle_t.
*/
void LPSPI_SlaveTransferCreateHandleEDMA(LPSPI_Type *base,
lpspi_slave_edma_handle_t *handle,
lpspi_slave_edma_transfer_callback_t callback,
void *userData,
edma_handle_t *edmaRxRegToRxDataHandle,
edma_handle_t *edmaTxDataToTxRegHandle);
/*!
* @brief LPSPI slave transfers data using eDMA.
*
* This function transfers data using eDMA. This is a non-blocking function, which return right away. When all data
* is transferred, the callback function is called.
*
* Note:
* The transfer data size should be an integer multiple of bytesPerFrame if bytesPerFrame is less than or equal to 4.
* For bytesPerFrame greater than 4:
* The transfer data size should be equal to bytesPerFrame if the bytesPerFrame is not an integer multiple of 4.
* Otherwise, the transfer data size can be an integer multiple of bytesPerFrame.
*
* @param base LPSPI peripheral base address.
* @param handle pointer to lpspi_slave_edma_handle_t structure which stores the transfer state.
* @param transfer pointer to lpspi_transfer_t structure.
* @return status of status_t.
*/
status_t LPSPI_SlaveTransferEDMA(LPSPI_Type *base, lpspi_slave_edma_handle_t *handle, lpspi_transfer_t *transfer);
/*!
* @brief LPSPI slave aborts a transfer which is using eDMA.
*
* This function aborts a transfer which is using eDMA.
*
* @param base LPSPI peripheral base address.
* @param handle pointer to lpspi_slave_edma_handle_t structure which stores the transfer state.
*/
void LPSPI_SlaveTransferAbortEDMA(LPSPI_Type *base, lpspi_slave_edma_handle_t *handle);
/*!
* @brief Gets the slave eDMA transfer remaining bytes.
*
* This function gets the slave eDMA transfer remaining bytes.
*
* @param base LPSPI peripheral base address.
* @param handle pointer to lpspi_slave_edma_handle_t structure which stores the transfer state.
* @param count Number of bytes transferred so far by the eDMA transaction.
* @return status of status_t.
*/
status_t LPSPI_SlaveTransferGetCountEDMA(LPSPI_Type *base, lpspi_slave_edma_handle_t *handle, size_t *count);
#if defined(__cplusplus)
}
#endif /*_cplusplus*/
/*!
*@}
*/
#endif /*_FSL_LPSPI_EDMA_H_*/

View File

@ -0,0 +1,132 @@
/*
* Copyright (c) 2015, Freescale Semiconductor, Inc.
* Copyright 2016-2017 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include "fsl_lptmr.h"
/*******************************************************************************
* Prototypes
******************************************************************************/
#if defined(LPTMR_CLOCKS)
/*!
* @brief Gets the instance from the base address to be used to gate or ungate the module clock
*
* @param base LPTMR peripheral base address
*
* @return The LPTMR instance
*/
static uint32_t LPTMR_GetInstance(LPTMR_Type *base);
#endif /* LPTMR_CLOCKS */
/*******************************************************************************
* Variables
******************************************************************************/
#if defined(LPTMR_CLOCKS)
/*! @brief Pointers to LPTMR bases for each instance. */
static LPTMR_Type *const s_lptmrBases[] = LPTMR_BASE_PTRS;
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
/*! @brief Pointers to LPTMR clocks for each instance. */
static const clock_ip_name_t s_lptmrClocks[] = LPTMR_CLOCKS;
#if defined(LPTMR_PERIPH_CLOCKS)
/* Array of LPTMR functional clock name. */
static const clock_ip_name_t s_lptmrPeriphClocks[] = LPTMR_PERIPH_CLOCKS;
#endif
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
#endif /* LPTMR_CLOCKS */
/*******************************************************************************
* Code
******************************************************************************/
#if defined(LPTMR_CLOCKS)
static uint32_t LPTMR_GetInstance(LPTMR_Type *base)
{
uint32_t instance;
/* Find the instance index from base address mappings. */
for (instance = 0; instance < ARRAY_SIZE(s_lptmrBases); instance++)
{
if (s_lptmrBases[instance] == base)
{
break;
}
}
assert(instance < ARRAY_SIZE(s_lptmrBases));
return instance;
}
#endif /* LPTMR_CLOCKS */
void LPTMR_Init(LPTMR_Type *base, const lptmr_config_t *config)
{
assert(config);
#if defined(LPTMR_CLOCKS)
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
uint32_t instance = LPTMR_GetInstance(base);
/* Ungate the LPTMR clock*/
CLOCK_EnableClock(s_lptmrClocks[instance]);
#if defined(LPTMR_PERIPH_CLOCKS)
CLOCK_EnableClock(s_lptmrPeriphClocks[instance]);
#endif
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
#endif /* LPTMR_CLOCKS */
/* Configure the timers operation mode and input pin setup */
base->CSR = (LPTMR_CSR_TMS(config->timerMode) | LPTMR_CSR_TFC(config->enableFreeRunning) |
LPTMR_CSR_TPP(config->pinPolarity) | LPTMR_CSR_TPS(config->pinSelect));
/* Configure the prescale value and clock source */
base->PSR = (LPTMR_PSR_PRESCALE(config->value) | LPTMR_PSR_PBYP(config->bypassPrescaler) |
LPTMR_PSR_PCS(config->prescalerClockSource));
}
void LPTMR_Deinit(LPTMR_Type *base)
{
/* Disable the LPTMR and reset the internal logic */
base->CSR &= ~LPTMR_CSR_TEN_MASK;
#if defined(LPTMR_CLOCKS)
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
uint32_t instance = LPTMR_GetInstance(base);
/* Gate the LPTMR clock*/
CLOCK_DisableClock(s_lptmrClocks[instance]);
#if defined(LPTMR_PERIPH_CLOCKS)
CLOCK_DisableClock(s_lptmrPeriphClocks[instance]);
#endif
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
#endif /* LPTMR_CLOCKS */
}
void LPTMR_GetDefaultConfig(lptmr_config_t *config)
{
assert(config);
/* Use time counter mode */
config->timerMode = kLPTMR_TimerModeTimeCounter;
/* Use input 0 as source in pulse counter mode */
config->pinSelect = kLPTMR_PinSelectInput_0;
/* Pulse input pin polarity is active-high */
config->pinPolarity = kLPTMR_PinPolarityActiveHigh;
/* Counter resets whenever TCF flag is set */
config->enableFreeRunning = false;
/* Bypass the prescaler */
config->bypassPrescaler = true;
/* LPTMR clock source */
config->prescalerClockSource = kLPTMR_PrescalerClock_1;
/* Divide the prescaler clock by 2 */
config->value = kLPTMR_Prescale_Glitch_0;
}

View File

@ -0,0 +1,368 @@
/*
* Copyright (c) 2016, Freescale Semiconductor, Inc.
* Copyright 2016-2017 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef _FSL_LPTMR_H_
#define _FSL_LPTMR_H_
#include "fsl_common.h"
/*!
* @addtogroup lptmr
* @{
*/
/*******************************************************************************
* Definitions
******************************************************************************/
/*! @name Driver version */
/*@{*/
#define FSL_LPTMR_DRIVER_VERSION (MAKE_VERSION(2, 0, 1)) /*!< Version 2.0.1 */
/*@}*/
/*! @brief LPTMR pin selection used in pulse counter mode.*/
typedef enum _lptmr_pin_select
{
kLPTMR_PinSelectInput_0 = 0x0U, /*!< Pulse counter input 0 is selected */
kLPTMR_PinSelectInput_1 = 0x1U, /*!< Pulse counter input 1 is selected */
kLPTMR_PinSelectInput_2 = 0x2U, /*!< Pulse counter input 2 is selected */
kLPTMR_PinSelectInput_3 = 0x3U /*!< Pulse counter input 3 is selected */
} lptmr_pin_select_t;
/*! @brief LPTMR pin polarity used in pulse counter mode.*/
typedef enum _lptmr_pin_polarity
{
kLPTMR_PinPolarityActiveHigh = 0x0U, /*!< Pulse Counter input source is active-high */
kLPTMR_PinPolarityActiveLow = 0x1U /*!< Pulse Counter input source is active-low */
} lptmr_pin_polarity_t;
/*! @brief LPTMR timer mode selection.*/
typedef enum _lptmr_timer_mode
{
kLPTMR_TimerModeTimeCounter = 0x0U, /*!< Time Counter mode */
kLPTMR_TimerModePulseCounter = 0x1U /*!< Pulse Counter mode */
} lptmr_timer_mode_t;
/*! @brief LPTMR prescaler/glitch filter values*/
typedef enum _lptmr_prescaler_glitch_value
{
kLPTMR_Prescale_Glitch_0 = 0x0U, /*!< Prescaler divide 2, glitch filter does not support this setting */
kLPTMR_Prescale_Glitch_1 = 0x1U, /*!< Prescaler divide 4, glitch filter 2 */
kLPTMR_Prescale_Glitch_2 = 0x2U, /*!< Prescaler divide 8, glitch filter 4 */
kLPTMR_Prescale_Glitch_3 = 0x3U, /*!< Prescaler divide 16, glitch filter 8 */
kLPTMR_Prescale_Glitch_4 = 0x4U, /*!< Prescaler divide 32, glitch filter 16 */
kLPTMR_Prescale_Glitch_5 = 0x5U, /*!< Prescaler divide 64, glitch filter 32 */
kLPTMR_Prescale_Glitch_6 = 0x6U, /*!< Prescaler divide 128, glitch filter 64 */
kLPTMR_Prescale_Glitch_7 = 0x7U, /*!< Prescaler divide 256, glitch filter 128 */
kLPTMR_Prescale_Glitch_8 = 0x8U, /*!< Prescaler divide 512, glitch filter 256 */
kLPTMR_Prescale_Glitch_9 = 0x9U, /*!< Prescaler divide 1024, glitch filter 512*/
kLPTMR_Prescale_Glitch_10 = 0xAU, /*!< Prescaler divide 2048 glitch filter 1024 */
kLPTMR_Prescale_Glitch_11 = 0xBU, /*!< Prescaler divide 4096, glitch filter 2048 */
kLPTMR_Prescale_Glitch_12 = 0xCU, /*!< Prescaler divide 8192, glitch filter 4096 */
kLPTMR_Prescale_Glitch_13 = 0xDU, /*!< Prescaler divide 16384, glitch filter 8192 */
kLPTMR_Prescale_Glitch_14 = 0xEU, /*!< Prescaler divide 32768, glitch filter 16384 */
kLPTMR_Prescale_Glitch_15 = 0xFU /*!< Prescaler divide 65536, glitch filter 32768 */
} lptmr_prescaler_glitch_value_t;
/*!
* @brief LPTMR prescaler/glitch filter clock select.
* @note Clock connections are SoC-specific
*/
typedef enum _lptmr_prescaler_clock_select
{
kLPTMR_PrescalerClock_0 = 0x0U, /*!< Prescaler/glitch filter clock 0 selected. */
kLPTMR_PrescalerClock_1 = 0x1U, /*!< Prescaler/glitch filter clock 1 selected. */
kLPTMR_PrescalerClock_2 = 0x2U, /*!< Prescaler/glitch filter clock 2 selected. */
kLPTMR_PrescalerClock_3 = 0x3U, /*!< Prescaler/glitch filter clock 3 selected. */
} lptmr_prescaler_clock_select_t;
/*! @brief List of the LPTMR interrupts */
typedef enum _lptmr_interrupt_enable
{
kLPTMR_TimerInterruptEnable = LPTMR_CSR_TIE_MASK, /*!< Timer interrupt enable */
} lptmr_interrupt_enable_t;
/*! @brief List of the LPTMR status flags */
typedef enum _lptmr_status_flags
{
kLPTMR_TimerCompareFlag = LPTMR_CSR_TCF_MASK, /*!< Timer compare flag */
} lptmr_status_flags_t;
/*!
* @brief LPTMR config structure
*
* This structure holds the configuration settings for the LPTMR peripheral. To initialize this
* structure to reasonable defaults, call the LPTMR_GetDefaultConfig() function and pass a
* pointer to your configuration structure instance.
*
* The configuration struct can be made constant so it resides in flash.
*/
typedef struct _lptmr_config
{
lptmr_timer_mode_t timerMode; /*!< Time counter mode or pulse counter mode */
lptmr_pin_select_t pinSelect; /*!< LPTMR pulse input pin select; used only in pulse counter mode */
lptmr_pin_polarity_t pinPolarity; /*!< LPTMR pulse input pin polarity; used only in pulse counter mode */
bool enableFreeRunning; /*!< True: enable free running, counter is reset on overflow
False: counter is reset when the compare flag is set */
bool bypassPrescaler; /*!< True: bypass prescaler; false: use clock from prescaler */
lptmr_prescaler_clock_select_t prescalerClockSource; /*!< LPTMR clock source */
lptmr_prescaler_glitch_value_t value; /*!< Prescaler or glitch filter value */
} lptmr_config_t;
/*******************************************************************************
* API
******************************************************************************/
#if defined(__cplusplus)
extern "C" {
#endif
/*!
* @name Initialization and deinitialization
* @{
*/
/*!
* @brief Ungates the LPTMR clock and configures the peripheral for a basic operation.
*
* @note This API should be called at the beginning of the application using the LPTMR driver.
*
* @param base LPTMR peripheral base address
* @param config A pointer to the LPTMR configuration structure.
*/
void LPTMR_Init(LPTMR_Type *base, const lptmr_config_t *config);
/*!
* @brief Gates the LPTMR clock.
*
* @param base LPTMR peripheral base address
*/
void LPTMR_Deinit(LPTMR_Type *base);
/*!
* @brief Fills in the LPTMR configuration structure with default settings.
*
* The default values are as follows.
* @code
* config->timerMode = kLPTMR_TimerModeTimeCounter;
* config->pinSelect = kLPTMR_PinSelectInput_0;
* config->pinPolarity = kLPTMR_PinPolarityActiveHigh;
* config->enableFreeRunning = false;
* config->bypassPrescaler = true;
* config->prescalerClockSource = kLPTMR_PrescalerClock_1;
* config->value = kLPTMR_Prescale_Glitch_0;
* @endcode
* @param config A pointer to the LPTMR configuration structure.
*/
void LPTMR_GetDefaultConfig(lptmr_config_t *config);
/*! @}*/
/*!
* @name Interrupt Interface
* @{
*/
/*!
* @brief Enables the selected LPTMR interrupts.
*
* @param base LPTMR peripheral base address
* @param mask The interrupts to enable. This is a logical OR of members of the
* enumeration ::lptmr_interrupt_enable_t
*/
static inline void LPTMR_EnableInterrupts(LPTMR_Type *base, uint32_t mask)
{
uint32_t reg = base->CSR;
/* Clear the TCF bit so that we don't clear this w1c bit when writing back */
reg &= ~(LPTMR_CSR_TCF_MASK);
reg |= mask;
base->CSR = reg;
}
/*!
* @brief Disables the selected LPTMR interrupts.
*
* @param base LPTMR peripheral base address
* @param mask The interrupts to disable. This is a logical OR of members of the
* enumeration ::lptmr_interrupt_enable_t.
*/
static inline void LPTMR_DisableInterrupts(LPTMR_Type *base, uint32_t mask)
{
uint32_t reg = base->CSR;
/* Clear the TCF bit so that we don't clear this w1c bit when writing back */
reg &= ~(LPTMR_CSR_TCF_MASK);
reg &= ~mask;
base->CSR = reg;
}
/*!
* @brief Gets the enabled LPTMR interrupts.
*
* @param base LPTMR peripheral base address
*
* @return The enabled interrupts. This is the logical OR of members of the
* enumeration ::lptmr_interrupt_enable_t
*/
static inline uint32_t LPTMR_GetEnabledInterrupts(LPTMR_Type *base)
{
return (base->CSR & LPTMR_CSR_TIE_MASK);
}
/*! @}*/
#if defined(FSL_FEATURE_LPTMR_HAS_CSR_TDRE) && (FSL_FEATURE_LPTMR_HAS_CSR_TDRE)
/*!
* @brief Enable or disable timer DMA request
*
* @param base base LPTMR peripheral base address
* @param enable Switcher of timer DMA feature. "true" means to enable, "false" means to disable.
*/
static inline void LPTMR_EnableTimerDMA(LPTMR_Type *base, bool enable)
{
if(enable)
{
base->CSR |= LPTMR_CSR_TDRE_MASK;
}
else
{
base->CSR &= ~(LPTMR_CSR_TDRE_MASK);
}
}
#endif /* FSL_FEATURE_LPTMR_HAS_CSR_TDRE */
/*!
* @name Status Interface
* @{
*/
/*!
* @brief Gets the LPTMR status flags.
*
* @param base LPTMR peripheral base address
*
* @return The status flags. This is the logical OR of members of the
* enumeration ::lptmr_status_flags_t
*/
static inline uint32_t LPTMR_GetStatusFlags(LPTMR_Type *base)
{
return (base->CSR & LPTMR_CSR_TCF_MASK);
}
/*!
* @brief Clears the LPTMR status flags.
*
* @param base LPTMR peripheral base address
* @param mask The status flags to clear. This is a logical OR of members of the
* enumeration ::lptmr_status_flags_t.
*/
static inline void LPTMR_ClearStatusFlags(LPTMR_Type *base, uint32_t mask)
{
base->CSR |= mask;
}
/*! @}*/
/*!
* @name Read and write the timer period
* @{
*/
/*!
* @brief Sets the timer period in units of count.
*
* Timers counts from 0 until it equals the count value set here. The count value is written to
* the CMR register.
*
* @note
* 1. The TCF flag is set with the CNR equals the count provided here and then increments.
* 2. Call the utility macros provided in the fsl_common.h to convert to ticks.
*
* @param base LPTMR peripheral base address
* @param ticks A timer period in units of ticks, which should be equal or greater than 1.
*/
static inline void LPTMR_SetTimerPeriod(LPTMR_Type *base, uint32_t ticks)
{
assert(ticks > 0);
base->CMR = ticks - 1;
}
/*!
* @brief Reads the current timer counting value.
*
* This function returns the real-time timer counting value in a range from 0 to a
* timer period.
*
* @note Call the utility macros provided in the fsl_common.h to convert ticks to usec or msec.
*
* @param base LPTMR peripheral base address
*
* @return The current counter value in ticks
*/
static inline uint32_t LPTMR_GetCurrentTimerCount(LPTMR_Type *base)
{
/* Must first write any value to the CNR. This synchronizes and registers the current value
* of the CNR into a temporary register which can then be read
*/
base->CNR = 0U;
return (uint32_t)((base->CNR & LPTMR_CNR_COUNTER_MASK) >> LPTMR_CNR_COUNTER_SHIFT);
}
/*! @}*/
/*!
* @name Timer Start and Stop
* @{
*/
/*!
* @brief Starts the timer.
*
* After calling this function, the timer counts up to the CMR register value.
* Each time the timer reaches the CMR value and then increments, it generates a
* trigger pulse and sets the timeout interrupt flag. An interrupt is also
* triggered if the timer interrupt is enabled.
*
* @param base LPTMR peripheral base address
*/
static inline void LPTMR_StartTimer(LPTMR_Type *base)
{
uint32_t reg = base->CSR;
/* Clear the TCF bit to avoid clearing the w1c bit when writing back. */
reg &= ~(LPTMR_CSR_TCF_MASK);
reg |= LPTMR_CSR_TEN_MASK;
base->CSR = reg;
}
/*!
* @brief Stops the timer.
*
* This function stops the timer and resets the timer's counter register.
*
* @param base LPTMR peripheral base address
*/
static inline void LPTMR_StopTimer(LPTMR_Type *base)
{
uint32_t reg = base->CSR;
/* Clear the TCF bit to avoid clearing the w1c bit when writing back. */
reg &= ~(LPTMR_CSR_TCF_MASK);
reg &= ~LPTMR_CSR_TEN_MASK;
base->CSR = reg;
}
/*! @}*/
#if defined(__cplusplus)
}
#endif
/*! @}*/
#endif /* _FSL_LPTMR_H_ */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,842 @@
/*
* Copyright (c) 2015-2016, Freescale Semiconductor, Inc.
* Copyright 2016-2017 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef _FSL_LPUART_H_
#define _FSL_LPUART_H_
#include "fsl_common.h"
/*!
* @addtogroup lpuart_driver
* @{
*/
/*******************************************************************************
* Definitions
******************************************************************************/
/*! @name Driver version */
/*@{*/
/*! @brief LPUART driver version 2.2.3. */
#define FSL_LPUART_DRIVER_VERSION (MAKE_VERSION(2, 2, 4))
/*@}*/
/*! @brief Error codes for the LPUART driver. */
enum _lpuart_status
{
kStatus_LPUART_TxBusy = MAKE_STATUS(kStatusGroup_LPUART, 0), /*!< TX busy */
kStatus_LPUART_RxBusy = MAKE_STATUS(kStatusGroup_LPUART, 1), /*!< RX busy */
kStatus_LPUART_TxIdle = MAKE_STATUS(kStatusGroup_LPUART, 2), /*!< LPUART transmitter is idle. */
kStatus_LPUART_RxIdle = MAKE_STATUS(kStatusGroup_LPUART, 3), /*!< LPUART receiver is idle. */
kStatus_LPUART_TxWatermarkTooLarge = MAKE_STATUS(kStatusGroup_LPUART, 4), /*!< TX FIFO watermark too large */
kStatus_LPUART_RxWatermarkTooLarge = MAKE_STATUS(kStatusGroup_LPUART, 5), /*!< RX FIFO watermark too large */
kStatus_LPUART_FlagCannotClearManually = MAKE_STATUS(kStatusGroup_LPUART, 6), /*!< Some flag can't manually clear */
kStatus_LPUART_Error = MAKE_STATUS(kStatusGroup_LPUART, 7), /*!< Error happens on LPUART. */
kStatus_LPUART_RxRingBufferOverrun =
MAKE_STATUS(kStatusGroup_LPUART, 8), /*!< LPUART RX software ring buffer overrun. */
kStatus_LPUART_RxHardwareOverrun = MAKE_STATUS(kStatusGroup_LPUART, 9), /*!< LPUART RX receiver overrun. */
kStatus_LPUART_NoiseError = MAKE_STATUS(kStatusGroup_LPUART, 10), /*!< LPUART noise error. */
kStatus_LPUART_FramingError = MAKE_STATUS(kStatusGroup_LPUART, 11), /*!< LPUART framing error. */
kStatus_LPUART_ParityError = MAKE_STATUS(kStatusGroup_LPUART, 12), /*!< LPUART parity error. */
kStatus_LPUART_BaudrateNotSupport =
MAKE_STATUS(kStatusGroup_LPUART, 13), /*!< Baudrate is not support in current clock source */
kStatus_LPUART_IdleLineDetected = MAKE_STATUS(kStatusGroup_LPUART, 14), /*!< IDLE flag. */
};
/*! @brief LPUART parity mode. */
typedef enum _lpuart_parity_mode
{
kLPUART_ParityDisabled = 0x0U, /*!< Parity disabled */
kLPUART_ParityEven = 0x2U, /*!< Parity enabled, type even, bit setting: PE|PT = 10 */
kLPUART_ParityOdd = 0x3U, /*!< Parity enabled, type odd, bit setting: PE|PT = 11 */
} lpuart_parity_mode_t;
/*! @brief LPUART data bits count. */
typedef enum _lpuart_data_bits
{
kLPUART_EightDataBits = 0x0U, /*!< Eight data bit */
#if defined(FSL_FEATURE_LPUART_HAS_7BIT_DATA_SUPPORT) && FSL_FEATURE_LPUART_HAS_7BIT_DATA_SUPPORT
kLPUART_SevenDataBits = 0x1U, /*!< Seven data bit */
#endif
} lpuart_data_bits_t;
/*! @brief LPUART stop bit count. */
typedef enum _lpuart_stop_bit_count
{
kLPUART_OneStopBit = 0U, /*!< One stop bit */
kLPUART_TwoStopBit = 1U, /*!< Two stop bits */
} lpuart_stop_bit_count_t;
#if defined(FSL_FEATURE_LPUART_HAS_MODEM_SUPPORT) && FSL_FEATURE_LPUART_HAS_MODEM_SUPPORT
/*! @brief LPUART transmit CTS source. */
typedef enum _lpuart_transmit_cts_source
{
kLPUART_CtsSourcePin = 0U, /*!< CTS resource is the LPUART_CTS pin. */
kLPUART_CtsSourceMatchResult = 1U, /*!< CTS resource is the match result. */
} lpuart_transmit_cts_source_t;
/*! @brief LPUART transmit CTS configure. */
typedef enum _lpuart_transmit_cts_config
{
kLPUART_CtsSampleAtStart = 0U, /*!< CTS input is sampled at the start of each character. */
kLPUART_CtsSampleAtIdle = 1U, /*!< CTS input is sampled when the transmitter is idle */
} lpuart_transmit_cts_config_t;
#endif
/*! @brief LPUART idle flag type defines when the receiver starts counting. */
typedef enum _lpuart_idle_type_select
{
kLPUART_IdleTypeStartBit = 0U, /*!< Start counting after a valid start bit. */
kLPUART_IdleTypeStopBit = 1U, /*!< Start conuting after a stop bit. */
} lpuart_idle_type_select_t;
/*! @brief LPUART idle detected configuration.
* This structure defines the number of idle characters that must be received before
* the IDLE flag is set.
*/
typedef enum _lpuart_idle_config
{
kLPUART_IdleCharacter1 = 0U, /*!< the number of idle characters. */
kLPUART_IdleCharacter2 = 1U, /*!< the number of idle characters. */
kLPUART_IdleCharacter4 = 2U, /*!< the number of idle characters. */
kLPUART_IdleCharacter8 = 3U, /*!< the number of idle characters. */
kLPUART_IdleCharacter16 = 4U, /*!< the number of idle characters. */
kLPUART_IdleCharacter32 = 5U, /*!< the number of idle characters. */
kLPUART_IdleCharacter64 = 6U, /*!< the number of idle characters. */
kLPUART_IdleCharacter128 = 7U, /*!< the number of idle characters. */
} lpuart_idle_config_t;
/*!
* @brief LPUART interrupt configuration structure, default settings all disabled.
*
* This structure contains the settings for all LPUART interrupt configurations.
*/
enum _lpuart_interrupt_enable
{
#if defined(FSL_FEATURE_LPUART_HAS_LIN_BREAK_DETECT) && FSL_FEATURE_LPUART_HAS_LIN_BREAK_DETECT
kLPUART_LinBreakInterruptEnable = (LPUART_BAUD_LBKDIE_MASK >> 8), /*!< LIN break detect. */
#endif
kLPUART_RxActiveEdgeInterruptEnable = (LPUART_BAUD_RXEDGIE_MASK >> 8), /*!< Receive Active Edge. */
kLPUART_TxDataRegEmptyInterruptEnable = (LPUART_CTRL_TIE_MASK), /*!< Transmit data register empty. */
kLPUART_TransmissionCompleteInterruptEnable = (LPUART_CTRL_TCIE_MASK), /*!< Transmission complete. */
kLPUART_RxDataRegFullInterruptEnable = (LPUART_CTRL_RIE_MASK), /*!< Receiver data register full. */
kLPUART_IdleLineInterruptEnable = (LPUART_CTRL_ILIE_MASK), /*!< Idle line. */
kLPUART_RxOverrunInterruptEnable = (LPUART_CTRL_ORIE_MASK), /*!< Receiver Overrun. */
kLPUART_NoiseErrorInterruptEnable = (LPUART_CTRL_NEIE_MASK), /*!< Noise error flag. */
kLPUART_FramingErrorInterruptEnable = (LPUART_CTRL_FEIE_MASK), /*!< Framing error flag. */
kLPUART_ParityErrorInterruptEnable = (LPUART_CTRL_PEIE_MASK), /*!< Parity error flag. */
#if defined(FSL_FEATURE_LPUART_HAS_FIFO) && FSL_FEATURE_LPUART_HAS_FIFO
kLPUART_TxFifoOverflowInterruptEnable = (LPUART_FIFO_TXOFE_MASK >> 8), /*!< Transmit FIFO Overflow. */
kLPUART_RxFifoUnderflowInterruptEnable = (LPUART_FIFO_RXUFE_MASK >> 8), /*!< Receive FIFO Underflow. */
#endif
};
/*!
* @brief LPUART status flags.
*
* This provides constants for the LPUART status flags for use in the LPUART functions.
*/
enum _lpuart_flags
{
kLPUART_TxDataRegEmptyFlag =
(LPUART_STAT_TDRE_MASK), /*!< Transmit data register empty flag, sets when transmit buffer is empty */
kLPUART_TransmissionCompleteFlag =
(LPUART_STAT_TC_MASK), /*!< Transmission complete flag, sets when transmission activity complete */
kLPUART_RxDataRegFullFlag =
(LPUART_STAT_RDRF_MASK), /*!< Receive data register full flag, sets when the receive data buffer is full */
kLPUART_IdleLineFlag = (LPUART_STAT_IDLE_MASK), /*!< Idle line detect flag, sets when idle line detected */
kLPUART_RxOverrunFlag = (LPUART_STAT_OR_MASK), /*!< Receive Overrun, sets when new data is received before data is
read from receive register */
kLPUART_NoiseErrorFlag = (LPUART_STAT_NF_MASK), /*!< Receive takes 3 samples of each received bit. If any of these
samples differ, noise flag sets */
kLPUART_FramingErrorFlag =
(LPUART_STAT_FE_MASK), /*!< Frame error flag, sets if logic 0 was detected where stop bit expected */
kLPUART_ParityErrorFlag = (LPUART_STAT_PF_MASK), /*!< If parity enabled, sets upon parity error detection */
#if defined(FSL_FEATURE_LPUART_HAS_LIN_BREAK_DETECT) && FSL_FEATURE_LPUART_HAS_LIN_BREAK_DETECT
kLPUART_LinBreakFlag = (LPUART_STAT_LBKDIF_MASK), /*!< LIN break detect interrupt flag, sets when LIN break char
detected and LIN circuit enabled */
#endif
kLPUART_RxActiveEdgeFlag =
(LPUART_STAT_RXEDGIF_MASK), /*!< Receive pin active edge interrupt flag, sets when active edge detected */
kLPUART_RxActiveFlag =
(LPUART_STAT_RAF_MASK), /*!< Receiver Active Flag (RAF), sets at beginning of valid start bit */
#if defined(FSL_FEATURE_LPUART_HAS_ADDRESS_MATCHING) && FSL_FEATURE_LPUART_HAS_ADDRESS_MATCHING
kLPUART_DataMatch1Flag = LPUART_STAT_MA1F_MASK, /*!< The next character to be read from LPUART_DATA matches MA1*/
kLPUART_DataMatch2Flag = LPUART_STAT_MA2F_MASK, /*!< The next character to be read from LPUART_DATA matches MA2*/
#endif
#if defined(FSL_FEATURE_LPUART_HAS_EXTENDED_DATA_REGISTER_FLAGS) && FSL_FEATURE_LPUART_HAS_EXTENDED_DATA_REGISTER_FLAGS
kLPUART_NoiseErrorInRxDataRegFlag =
(LPUART_DATA_NOISY_MASK >> 10), /*!< NOISY bit, sets if noise detected in current data word */
kLPUART_ParityErrorInRxDataRegFlag =
(LPUART_DATA_PARITYE_MASK >> 10), /*!< PARITYE bit, sets if noise detected in current data word */
#endif
#if defined(FSL_FEATURE_LPUART_HAS_FIFO) && FSL_FEATURE_LPUART_HAS_FIFO
kLPUART_TxFifoEmptyFlag = (LPUART_FIFO_TXEMPT_MASK >> 16), /*!< TXEMPT bit, sets if transmit buffer is empty */
kLPUART_RxFifoEmptyFlag = (LPUART_FIFO_RXEMPT_MASK >> 16), /*!< RXEMPT bit, sets if receive buffer is empty */
kLPUART_TxFifoOverflowFlag =
(LPUART_FIFO_TXOF_MASK >> 16), /*!< TXOF bit, sets if transmit buffer overflow occurred */
kLPUART_RxFifoUnderflowFlag =
(LPUART_FIFO_RXUF_MASK >> 16), /*!< RXUF bit, sets if receive buffer underflow occurred */
#endif
};
/*! @brief LPUART configuration structure. */
typedef struct _lpuart_config
{
uint32_t baudRate_Bps; /*!< LPUART baud rate */
lpuart_parity_mode_t parityMode; /*!< Parity mode, disabled (default), even, odd */
lpuart_data_bits_t dataBitsCount; /*!< Data bits count, eight (default), seven */
bool isMsb; /*!< Data bits order, LSB (default), MSB */
#if defined(FSL_FEATURE_LPUART_HAS_STOP_BIT_CONFIG_SUPPORT) && FSL_FEATURE_LPUART_HAS_STOP_BIT_CONFIG_SUPPORT
lpuart_stop_bit_count_t stopBitCount; /*!< Number of stop bits, 1 stop bit (default) or 2 stop bits */
#endif
#if defined(FSL_FEATURE_LPUART_HAS_FIFO) && FSL_FEATURE_LPUART_HAS_FIFO
uint8_t txFifoWatermark; /*!< TX FIFO watermark */
uint8_t rxFifoWatermark; /*!< RX FIFO watermark */
#endif
#if defined(FSL_FEATURE_LPUART_HAS_MODEM_SUPPORT) && FSL_FEATURE_LPUART_HAS_MODEM_SUPPORT
bool enableRxRTS; /*!< RX RTS enable */
bool enableTxCTS; /*!< TX CTS enable */
lpuart_transmit_cts_source_t txCtsSource; /*!< TX CTS source */
lpuart_transmit_cts_config_t txCtsConfig; /*!< TX CTS configure */
#endif
lpuart_idle_type_select_t rxIdleType; /*!< RX IDLE type. */
lpuart_idle_config_t rxIdleConfig; /*!< RX IDLE configuration. */
bool enableTx; /*!< Enable TX */
bool enableRx; /*!< Enable RX */
} lpuart_config_t;
/*! @brief LPUART transfer structure. */
typedef struct _lpuart_transfer
{
uint8_t *data; /*!< The buffer of data to be transfer.*/
size_t dataSize; /*!< The byte count to be transfer. */
} lpuart_transfer_t;
/* Forward declaration of the handle typedef. */
typedef struct _lpuart_handle lpuart_handle_t;
/*! @brief LPUART transfer callback function. */
typedef void (*lpuart_transfer_callback_t)(LPUART_Type *base, lpuart_handle_t *handle, status_t status, void *userData);
/*! @brief LPUART handle structure. */
struct _lpuart_handle
{
uint8_t *volatile txData; /*!< Address of remaining data to send. */
volatile size_t txDataSize; /*!< Size of the remaining data to send. */
size_t txDataSizeAll; /*!< Size of the data to send out. */
uint8_t *volatile rxData; /*!< Address of remaining data to receive. */
volatile size_t rxDataSize; /*!< Size of the remaining data to receive. */
size_t rxDataSizeAll; /*!< Size of the data to receive. */
uint8_t *rxRingBuffer; /*!< Start address of the receiver ring buffer. */
size_t rxRingBufferSize; /*!< Size of the ring buffer. */
volatile uint16_t rxRingBufferHead; /*!< Index for the driver to store received data into ring buffer. */
volatile uint16_t rxRingBufferTail; /*!< Index for the user to get data from the ring buffer. */
lpuart_transfer_callback_t callback; /*!< Callback function. */
void *userData; /*!< LPUART callback function parameter.*/
volatile uint8_t txState; /*!< TX transfer state. */
volatile uint8_t rxState; /*!< RX transfer state. */
#if defined(FSL_FEATURE_LPUART_HAS_7BIT_DATA_SUPPORT) && FSL_FEATURE_LPUART_HAS_7BIT_DATA_SUPPORT
bool isSevenDataBits; /*!< Seven data bits flag. */
#endif
};
/*******************************************************************************
* API
******************************************************************************/
#if defined(__cplusplus)
extern "C" {
#endif /* _cplusplus */
#if defined(FSL_FEATURE_LPUART_HAS_GLOBAL) && FSL_FEATURE_LPUART_HAS_GLOBAL
/*!
* @name Software Reset
* @{
*/
/*!
* @brief Resets the LPUART using software.
*
* This function resets all internal logic and registers except the Global Register.
* Remains set until cleared by software.
*
* @param base LPUART peripheral base address.
*/
static inline void LPUART_SoftwareReset(LPUART_Type *base)
{
base->GLOBAL |= LPUART_GLOBAL_RST_MASK;
base->GLOBAL &= ~LPUART_GLOBAL_RST_MASK;
}
/* @} */
#endif /*FSL_FEATURE_LPUART_HAS_GLOBAL*/
/*!
* @name Initialization and deinitialization
* @{
*/
/*!
* @brief Initializes an LPUART instance with the user configuration structure and the peripheral clock.
*
* This function configures the LPUART module with user-defined settings. Call the LPUART_GetDefaultConfig() function
* to configure the configuration structure and get the default configuration.
* The example below shows how to use this API to configure the LPUART.
* @code
* lpuart_config_t lpuartConfig;
* lpuartConfig.baudRate_Bps = 115200U;
* lpuartConfig.parityMode = kLPUART_ParityDisabled;
* lpuartConfig.dataBitsCount = kLPUART_EightDataBits;
* lpuartConfig.isMsb = false;
* lpuartConfig.stopBitCount = kLPUART_OneStopBit;
* lpuartConfig.txFifoWatermark = 0;
* lpuartConfig.rxFifoWatermark = 1;
* LPUART_Init(LPUART1, &lpuartConfig, 20000000U);
* @endcode
*
* @param base LPUART peripheral base address.
* @param config Pointer to a user-defined configuration structure.
* @param srcClock_Hz LPUART clock source frequency in HZ.
* @retval kStatus_LPUART_BaudrateNotSupport Baudrate is not support in current clock source.
* @retval kStatus_Success LPUART initialize succeed
*/
status_t LPUART_Init(LPUART_Type *base, const lpuart_config_t *config, uint32_t srcClock_Hz);
/*!
* @brief Deinitializes a LPUART instance.
*
* This function waits for transmit to complete, disables TX and RX, and disables the LPUART clock.
*
* @param base LPUART peripheral base address.
*/
void LPUART_Deinit(LPUART_Type *base);
/*!
* @brief Gets the default configuration structure.
*
* This function initializes the LPUART configuration structure to a default value. The default
* values are:
* lpuartConfig->baudRate_Bps = 115200U;
* lpuartConfig->parityMode = kLPUART_ParityDisabled;
* lpuartConfig->dataBitsCount = kLPUART_EightDataBits;
* lpuartConfig->isMsb = false;
* lpuartConfig->stopBitCount = kLPUART_OneStopBit;
* lpuartConfig->txFifoWatermark = 0;
* lpuartConfig->rxFifoWatermark = 1;
* lpuartConfig->rxIdleType = kLPUART_IdleTypeStartBit;
* lpuartConfig->rxIdleConfig = kLPUART_IdleCharacter1;
* lpuartConfig->enableTx = false;
* lpuartConfig->enableRx = false;
*
* @param config Pointer to a configuration structure.
*/
void LPUART_GetDefaultConfig(lpuart_config_t *config);
/*!
* @brief Sets the LPUART instance baudrate.
*
* This function configures the LPUART module baudrate. This function is used to update
* the LPUART module baudrate after the LPUART module is initialized by the LPUART_Init.
* @code
* LPUART_SetBaudRate(LPUART1, 115200U, 20000000U);
* @endcode
*
* @param base LPUART peripheral base address.
* @param baudRate_Bps LPUART baudrate to be set.
* @param srcClock_Hz LPUART clock source frequency in HZ.
* @retval kStatus_LPUART_BaudrateNotSupport Baudrate is not supported in the current clock source.
* @retval kStatus_Success Set baudrate succeeded.
*/
status_t LPUART_SetBaudRate(LPUART_Type *base, uint32_t baudRate_Bps, uint32_t srcClock_Hz);
/* @} */
/*!
* @name Status
* @{
*/
/*!
* @brief Gets LPUART status flags.
*
* This function gets all LPUART status flags. The flags are returned as the logical
* OR value of the enumerators @ref _lpuart_flags. To check for a specific status,
* compare the return value with enumerators in the @ref _lpuart_flags.
* For example, to check whether the TX is empty:
* @code
* if (kLPUART_TxDataRegEmptyFlag & LPUART_GetStatusFlags(LPUART1))
* {
* ...
* }
* @endcode
*
* @param base LPUART peripheral base address.
* @return LPUART status flags which are ORed by the enumerators in the _lpuart_flags.
*/
uint32_t LPUART_GetStatusFlags(LPUART_Type *base);
/*!
* @brief Clears status flags with a provided mask.
*
* This function clears LPUART status flags with a provided mask. Automatically cleared flags
* can't be cleared by this function.
* Flags that can only cleared or set by hardware are:
* kLPUART_TxDataRegEmptyFlag, kLPUART_TransmissionCompleteFlag, kLPUART_RxDataRegFullFlag,
* kLPUART_RxActiveFlag, kLPUART_NoiseErrorInRxDataRegFlag, kLPUART_ParityErrorInRxDataRegFlag,
* kLPUART_TxFifoEmptyFlag,kLPUART_RxFifoEmptyFlag
* Note: This API should be called when the Tx/Rx is idle, otherwise it takes no effects.
*
* @param base LPUART peripheral base address.
* @param mask the status flags to be cleared. The user can use the enumerators in the
* _lpuart_status_flag_t to do the OR operation and get the mask.
* @return 0 succeed, others failed.
* @retval kStatus_LPUART_FlagCannotClearManually The flag can't be cleared by this function but
* it is cleared automatically by hardware.
* @retval kStatus_Success Status in the mask are cleared.
*/
status_t LPUART_ClearStatusFlags(LPUART_Type *base, uint32_t mask);
/* @} */
/*!
* @name Interrupts
* @{
*/
/*!
* @brief Enables LPUART interrupts according to a provided mask.
*
* This function enables the LPUART interrupts according to a provided mask. The mask
* is a logical OR of enumeration members. See the @ref _lpuart_interrupt_enable.
* This examples shows how to enable TX empty interrupt and RX full interrupt:
* @code
* LPUART_EnableInterrupts(LPUART1,kLPUART_TxDataRegEmptyInterruptEnable | kLPUART_RxDataRegFullInterruptEnable);
* @endcode
*
* @param base LPUART peripheral base address.
* @param mask The interrupts to enable. Logical OR of @ref _uart_interrupt_enable.
*/
void LPUART_EnableInterrupts(LPUART_Type *base, uint32_t mask);
/*!
* @brief Disables LPUART interrupts according to a provided mask.
*
* This function disables the LPUART interrupts according to a provided mask. The mask
* is a logical OR of enumeration members. See @ref _lpuart_interrupt_enable.
* This example shows how to disable the TX empty interrupt and RX full interrupt:
* @code
* LPUART_DisableInterrupts(LPUART1,kLPUART_TxDataRegEmptyInterruptEnable | kLPUART_RxDataRegFullInterruptEnable);
* @endcode
*
* @param base LPUART peripheral base address.
* @param mask The interrupts to disable. Logical OR of @ref _lpuart_interrupt_enable.
*/
void LPUART_DisableInterrupts(LPUART_Type *base, uint32_t mask);
/*!
* @brief Gets enabled LPUART interrupts.
*
* This function gets the enabled LPUART interrupts. The enabled interrupts are returned
* as the logical OR value of the enumerators @ref _lpuart_interrupt_enable. To check
* a specific interrupt enable status, compare the return value with enumerators
* in @ref _lpuart_interrupt_enable.
* For example, to check whether the TX empty interrupt is enabled:
* @code
* uint32_t enabledInterrupts = LPUART_GetEnabledInterrupts(LPUART1);
*
* if (kLPUART_TxDataRegEmptyInterruptEnable & enabledInterrupts)
* {
* ...
* }
* @endcode
*
* @param base LPUART peripheral base address.
* @return LPUART interrupt flags which are logical OR of the enumerators in @ref _lpuart_interrupt_enable.
*/
uint32_t LPUART_GetEnabledInterrupts(LPUART_Type *base);
#if defined(FSL_FEATURE_LPUART_HAS_DMA_ENABLE) && FSL_FEATURE_LPUART_HAS_DMA_ENABLE
/*!
* @brief Gets the LPUART data register address.
*
* This function returns the LPUART data register address, which is mainly used by the DMA/eDMA.
*
* @param base LPUART peripheral base address.
* @return LPUART data register addresses which are used both by the transmitter and receiver.
*/
static inline uint32_t LPUART_GetDataRegisterAddress(LPUART_Type *base)
{
return (uint32_t) & (base->DATA);
}
/*!
* @brief Enables or disables the LPUART transmitter DMA request.
*
* This function enables or disables the transmit data register empty flag, STAT[TDRE], to generate DMA requests.
*
* @param base LPUART peripheral base address.
* @param enable True to enable, false to disable.
*/
static inline void LPUART_EnableTxDMA(LPUART_Type *base, bool enable)
{
if (enable)
{
base->BAUD |= LPUART_BAUD_TDMAE_MASK;
base->CTRL |= LPUART_CTRL_TIE_MASK;
}
else
{
base->BAUD &= ~LPUART_BAUD_TDMAE_MASK;
base->CTRL &= ~LPUART_CTRL_TIE_MASK;
}
}
/*!
* @brief Enables or disables the LPUART receiver DMA.
*
* This function enables or disables the receiver data register full flag, STAT[RDRF], to generate DMA requests.
*
* @param base LPUART peripheral base address.
* @param enable True to enable, false to disable.
*/
static inline void LPUART_EnableRxDMA(LPUART_Type *base, bool enable)
{
if (enable)
{
base->BAUD |= LPUART_BAUD_RDMAE_MASK;
base->CTRL |= LPUART_CTRL_RIE_MASK;
}
else
{
base->BAUD &= ~LPUART_BAUD_RDMAE_MASK;
base->CTRL &= ~LPUART_CTRL_RIE_MASK;
}
}
/* @} */
#endif /* FSL_FEATURE_LPUART_HAS_DMA_ENABLE */
/*!
* @name Bus Operations
* @{
*/
/*!
* @brief Enables or disables the LPUART transmitter.
*
* This function enables or disables the LPUART transmitter.
*
* @param base LPUART peripheral base address.
* @param enable True to enable, false to disable.
*/
static inline void LPUART_EnableTx(LPUART_Type *base, bool enable)
{
if (enable)
{
base->CTRL |= LPUART_CTRL_TE_MASK;
}
else
{
base->CTRL &= ~LPUART_CTRL_TE_MASK;
}
}
/*!
* @brief Enables or disables the LPUART receiver.
*
* This function enables or disables the LPUART receiver.
*
* @param base LPUART peripheral base address.
* @param enable True to enable, false to disable.
*/
static inline void LPUART_EnableRx(LPUART_Type *base, bool enable)
{
if (enable)
{
base->CTRL |= LPUART_CTRL_RE_MASK;
}
else
{
base->CTRL &= ~LPUART_CTRL_RE_MASK;
}
}
/*!
* @brief Writes to the transmitter register.
*
* This function writes data to the transmitter register directly. The upper layer must
* ensure that the TX register is empty or that the TX FIFO has room before calling this function.
*
* @param base LPUART peripheral base address.
* @param data Data write to the TX register.
*/
static inline void LPUART_WriteByte(LPUART_Type *base, uint8_t data)
{
base->DATA = data;
}
/*!
* @brief Reads the receiver register.
*
* This function reads data from the receiver register directly. The upper layer must
* ensure that the receiver register is full or that the RX FIFO has data before calling this function.
*
* @param base LPUART peripheral base address.
* @return Data read from data register.
*/
static inline uint8_t LPUART_ReadByte(LPUART_Type *base)
{
#if defined(FSL_FEATURE_LPUART_HAS_7BIT_DATA_SUPPORT) && FSL_FEATURE_LPUART_HAS_7BIT_DATA_SUPPORT
uint32_t ctrl = base->CTRL;
bool isSevenDataBits =
((ctrl & LPUART_CTRL_M7_MASK) ||
((!(ctrl & LPUART_CTRL_M7_MASK)) && (!(ctrl & LPUART_CTRL_M_MASK)) && (ctrl & LPUART_CTRL_PE_MASK)));
if (isSevenDataBits)
{
return (base->DATA & 0x7F);
}
else
{
return base->DATA;
}
#else
return base->DATA;
#endif
}
/*!
* @brief Writes to the transmitter register using a blocking method.
*
* This function polls the transmitter register, waits for the register to be empty or for TX FIFO to have
* room, and writes data to the transmitter buffer.
*
* @note This function does not check whether all data has been sent out to the bus.
* Before disabling the transmitter, check the kLPUART_TransmissionCompleteFlag to ensure that the transmit is
* finished.
*
* @param base LPUART peripheral base address.
* @param data Start address of the data to write.
* @param length Size of the data to write.
*/
void LPUART_WriteBlocking(LPUART_Type *base, const uint8_t *data, size_t length);
/*!
* @brief Reads the receiver data register using a blocking method.
*
* This function polls the receiver register, waits for the receiver register full or receiver FIFO
* has data, and reads data from the TX register.
*
* @param base LPUART peripheral base address.
* @param data Start address of the buffer to store the received data.
* @param length Size of the buffer.
* @retval kStatus_LPUART_RxHardwareOverrun Receiver overrun happened while receiving data.
* @retval kStatus_LPUART_NoiseError Noise error happened while receiving data.
* @retval kStatus_LPUART_FramingError Framing error happened while receiving data.
* @retval kStatus_LPUART_ParityError Parity error happened while receiving data.
* @retval kStatus_Success Successfully received all data.
*/
status_t LPUART_ReadBlocking(LPUART_Type *base, uint8_t *data, size_t length);
/* @} */
/*!
* @name Transactional
* @{
*/
/*!
* @brief Initializes the LPUART handle.
*
* This function initializes the LPUART handle, which can be used for other LPUART
* transactional APIs. Usually, for a specified LPUART instance,
* call this API once to get the initialized handle.
*
* The LPUART driver supports the "background" receiving, which means that user can set up
* an RX ring buffer optionally. Data received is stored into the ring buffer even when the
* user doesn't call the LPUART_TransferReceiveNonBlocking() API. If there is already data received
* in the ring buffer, the user can get the received data from the ring buffer directly.
* The ring buffer is disabled if passing NULL as @p ringBuffer.
*
* @param base LPUART peripheral base address.
* @param handle LPUART handle pointer.
* @param callback Callback function.
* @param userData User data.
*/
void LPUART_TransferCreateHandle(LPUART_Type *base,
lpuart_handle_t *handle,
lpuart_transfer_callback_t callback,
void *userData);
/*!
* @brief Transmits a buffer of data using the interrupt method.
*
* This function send data using an interrupt method. This is a non-blocking function, which
* returns directly without waiting for all data written to the transmitter register. When
* all data is written to the TX register in the ISR, the LPUART driver calls the callback
* function and passes the @ref kStatus_LPUART_TxIdle as status parameter.
*
* @note The kStatus_LPUART_TxIdle is passed to the upper layer when all data are written
* to the TX register. However, there is no check to ensure that all the data sent out. Before disabling the TX,
* check the kLPUART_TransmissionCompleteFlag to ensure that the transmit is finished.
*
* @param base LPUART peripheral base address.
* @param handle LPUART handle pointer.
* @param xfer LPUART transfer structure, see #lpuart_transfer_t.
* @retval kStatus_Success Successfully start the data transmission.
* @retval kStatus_LPUART_TxBusy Previous transmission still not finished, data not all written to the TX register.
* @retval kStatus_InvalidArgument Invalid argument.
*/
status_t LPUART_TransferSendNonBlocking(LPUART_Type *base, lpuart_handle_t *handle, lpuart_transfer_t *xfer);
/*!
* @brief Sets up the RX ring buffer.
*
* This function sets up the RX ring buffer to a specific UART handle.
*
* When the RX ring buffer is used, data received is stored into the ring buffer even when
* the user doesn't call the UART_TransferReceiveNonBlocking() API. If there is already data received
* in the ring buffer, the user can get the received data from the ring buffer directly.
*
* @note When using RX ring buffer, one byte is reserved for internal use. In other
* words, if @p ringBufferSize is 32, then only 31 bytes are used for saving data.
*
* @param base LPUART peripheral base address.
* @param handle LPUART handle pointer.
* @param ringBuffer Start address of ring buffer for background receiving. Pass NULL to disable the ring buffer.
* @param ringBufferSize size of the ring buffer.
*/
void LPUART_TransferStartRingBuffer(LPUART_Type *base,
lpuart_handle_t *handle,
uint8_t *ringBuffer,
size_t ringBufferSize);
/*!
* @brief Aborts the background transfer and uninstalls the ring buffer.
*
* This function aborts the background transfer and uninstalls the ring buffer.
*
* @param base LPUART peripheral base address.
* @param handle LPUART handle pointer.
*/
void LPUART_TransferStopRingBuffer(LPUART_Type *base, lpuart_handle_t *handle);
/*!
* @brief Aborts the interrupt-driven data transmit.
*
* This function aborts the interrupt driven data sending. The user can get the remainBtyes to find out
* how many bytes are not sent out.
*
* @param base LPUART peripheral base address.
* @param handle LPUART handle pointer.
*/
void LPUART_TransferAbortSend(LPUART_Type *base, lpuart_handle_t *handle);
/*!
* @brief Gets the number of bytes that have been written to the LPUART transmitter register.
*
* This function gets the number of bytes that have been written to LPUART TX
* register by an interrupt method.
*
* @param base LPUART peripheral base address.
* @param handle LPUART handle pointer.
* @param count Send bytes count.
* @retval kStatus_NoTransferInProgress No send in progress.
* @retval kStatus_InvalidArgument Parameter is invalid.
* @retval kStatus_Success Get successfully through the parameter \p count;
*/
status_t LPUART_TransferGetSendCount(LPUART_Type *base, lpuart_handle_t *handle, uint32_t *count);
/*!
* @brief Receives a buffer of data using the interrupt method.
*
* This function receives data using an interrupt method. This is a non-blocking function
* which returns without waiting to ensure that all data are received.
* If the RX ring buffer is used and not empty, the data in the ring buffer is copied and
* the parameter @p receivedBytes shows how many bytes are copied from the ring buffer.
* After copying, if the data in the ring buffer is not enough for read, the receive
* request is saved by the LPUART driver. When the new data arrives, the receive request
* is serviced first. When all data is received, the LPUART driver notifies the upper layer
* through a callback function and passes a status parameter @ref kStatus_UART_RxIdle.
* For example, the upper layer needs 10 bytes but there are only 5 bytes in ring buffer.
* The 5 bytes are copied to xfer->data, which returns with the
* parameter @p receivedBytes set to 5. For the remaining 5 bytes, the newly arrived data is
* saved from xfer->data[5]. When 5 bytes are received, the LPUART driver notifies the upper layer.
* If the RX ring buffer is not enabled, this function enables the RX and RX interrupt
* to receive data to xfer->data. When all data is received, the upper layer is notified.
*
* @param base LPUART peripheral base address.
* @param handle LPUART handle pointer.
* @param xfer LPUART transfer structure, see #uart_transfer_t.
* @param receivedBytes Bytes received from the ring buffer directly.
* @retval kStatus_Success Successfully queue the transfer into the transmit queue.
* @retval kStatus_LPUART_RxBusy Previous receive request is not finished.
* @retval kStatus_InvalidArgument Invalid argument.
*/
status_t LPUART_TransferReceiveNonBlocking(LPUART_Type *base,
lpuart_handle_t *handle,
lpuart_transfer_t *xfer,
size_t *receivedBytes);
/*!
* @brief Aborts the interrupt-driven data receiving.
*
* This function aborts the interrupt-driven data receiving. The user can get the remainBytes to find out
* how many bytes not received yet.
*
* @param base LPUART peripheral base address.
* @param handle LPUART handle pointer.
*/
void LPUART_TransferAbortReceive(LPUART_Type *base, lpuart_handle_t *handle);
/*!
* @brief Gets the number of bytes that have been received.
*
* This function gets the number of bytes that have been received.
*
* @param base LPUART peripheral base address.
* @param handle LPUART handle pointer.
* @param count Receive bytes count.
* @retval kStatus_NoTransferInProgress No receive in progress.
* @retval kStatus_InvalidArgument Parameter is invalid.
* @retval kStatus_Success Get successfully through the parameter \p count;
*/
status_t LPUART_TransferGetReceiveCount(LPUART_Type *base, lpuart_handle_t *handle, uint32_t *count);
/*!
* @brief LPUART IRQ handle function.
*
* This function handles the LPUART transmit and receive IRQ request.
*
* @param base LPUART peripheral base address.
* @param handle LPUART handle pointer.
*/
void LPUART_TransferHandleIRQ(LPUART_Type *base, lpuart_handle_t *handle);
/*!
* @brief LPUART Error IRQ handle function.
*
* This function handles the LPUART error IRQ request.
*
* @param base LPUART peripheral base address.
* @param handle LPUART handle pointer.
*/
void LPUART_TransferHandleErrorIRQ(LPUART_Type *base, lpuart_handle_t *handle);
/* @} */
#if defined(__cplusplus)
}
#endif
/*! @}*/
#endif /* _FSL_LPUART_H_ */

View File

@ -0,0 +1,318 @@
/*
* Copyright (c) 2015, Freescale Semiconductor, Inc.
* Copyright 2016-2017 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include "fsl_lpuart_edma.h"
/*******************************************************************************
* Definitions
******************************************************************************/
/*<! Structure definition for lpuart_edma_private_handle_t. The structure is private. */
typedef struct _lpuart_edma_private_handle
{
LPUART_Type *base;
lpuart_edma_handle_t *handle;
} lpuart_edma_private_handle_t;
/* LPUART EDMA transfer handle. */
enum _lpuart_edma_tansfer_states
{
kLPUART_TxIdle, /* TX idle. */
kLPUART_TxBusy, /* TX busy. */
kLPUART_RxIdle, /* RX idle. */
kLPUART_RxBusy /* RX busy. */
};
/*******************************************************************************
* Definitions
******************************************************************************/
/*<! Private handle only used for internally. */
static lpuart_edma_private_handle_t s_edmaPrivateHandle[FSL_FEATURE_SOC_LPUART_COUNT];
/*******************************************************************************
* Prototypes
******************************************************************************/
/*!
* @brief LPUART EDMA send finished callback function.
*
* This function is called when LPUART EDMA send finished. It disables the LPUART
* TX EDMA request and sends @ref kStatus_LPUART_TxIdle to LPUART callback.
*
* @param handle The EDMA handle.
* @param param Callback function parameter.
*/
static void LPUART_SendEDMACallback(edma_handle_t *handle, void *param, bool transferDone, uint32_t tcds);
/*!
* @brief LPUART EDMA receive finished callback function.
*
* This function is called when LPUART EDMA receive finished. It disables the LPUART
* RX EDMA request and sends @ref kStatus_LPUART_RxIdle to LPUART callback.
*
* @param handle The EDMA handle.
* @param param Callback function parameter.
*/
static void LPUART_ReceiveEDMACallback(edma_handle_t *handle, void *param, bool transferDone, uint32_t tcds);
/*!
* @brief Get the LPUART instance from peripheral base address.
*
* @param base LPUART peripheral base address.
* @return LPUART instance.
*/
extern uint32_t LPUART_GetInstance(LPUART_Type *base);
/*******************************************************************************
* Code
******************************************************************************/
static void LPUART_SendEDMACallback(edma_handle_t *handle, void *param, bool transferDone, uint32_t tcds)
{
assert(param);
lpuart_edma_private_handle_t *lpuartPrivateHandle = (lpuart_edma_private_handle_t *)param;
/* Avoid the warning for unused variables. */
handle = handle;
tcds = tcds;
if (transferDone)
{
LPUART_TransferAbortSendEDMA(lpuartPrivateHandle->base, lpuartPrivateHandle->handle);
if (lpuartPrivateHandle->handle->callback)
{
lpuartPrivateHandle->handle->callback(lpuartPrivateHandle->base, lpuartPrivateHandle->handle,
kStatus_LPUART_TxIdle, lpuartPrivateHandle->handle->userData);
}
}
}
static void LPUART_ReceiveEDMACallback(edma_handle_t *handle, void *param, bool transferDone, uint32_t tcds)
{
assert(param);
lpuart_edma_private_handle_t *lpuartPrivateHandle = (lpuart_edma_private_handle_t *)param;
/* Avoid warning for unused parameters. */
handle = handle;
tcds = tcds;
if (transferDone)
{
/* Disable transfer. */
LPUART_TransferAbortReceiveEDMA(lpuartPrivateHandle->base, lpuartPrivateHandle->handle);
if (lpuartPrivateHandle->handle->callback)
{
lpuartPrivateHandle->handle->callback(lpuartPrivateHandle->base, lpuartPrivateHandle->handle,
kStatus_LPUART_RxIdle, lpuartPrivateHandle->handle->userData);
}
}
}
void LPUART_TransferCreateHandleEDMA(LPUART_Type *base,
lpuart_edma_handle_t *handle,
lpuart_edma_transfer_callback_t callback,
void *userData,
edma_handle_t *txEdmaHandle,
edma_handle_t *rxEdmaHandle)
{
assert(handle);
uint32_t instance = LPUART_GetInstance(base);
s_edmaPrivateHandle[instance].base = base;
s_edmaPrivateHandle[instance].handle = handle;
memset(handle, 0, sizeof(*handle));
handle->rxState = kLPUART_RxIdle;
handle->txState = kLPUART_TxIdle;
handle->rxEdmaHandle = rxEdmaHandle;
handle->txEdmaHandle = txEdmaHandle;
handle->callback = callback;
handle->userData = userData;
#if defined(FSL_FEATURE_LPUART_HAS_FIFO) && FSL_FEATURE_LPUART_HAS_FIFO
/* Note:
Take care of the RX FIFO, EDMA request only assert when received bytes
equal or more than RX water mark, there is potential issue if RX water
mark larger than 1.
For example, if RX FIFO water mark is 2, upper layer needs 5 bytes and
5 bytes are received. the last byte will be saved in FIFO but not trigger
EDMA transfer because the water mark is 2.
*/
if (rxEdmaHandle)
{
base->WATER &= (~LPUART_WATER_RXWATER_MASK);
}
#endif
/* Configure TX. */
if (txEdmaHandle)
{
EDMA_SetCallback(handle->txEdmaHandle, LPUART_SendEDMACallback, &s_edmaPrivateHandle[instance]);
}
/* Configure RX. */
if (rxEdmaHandle)
{
EDMA_SetCallback(handle->rxEdmaHandle, LPUART_ReceiveEDMACallback, &s_edmaPrivateHandle[instance]);
}
}
status_t LPUART_SendEDMA(LPUART_Type *base, lpuart_edma_handle_t *handle, lpuart_transfer_t *xfer)
{
assert(handle);
assert(handle->txEdmaHandle);
assert(xfer);
assert(xfer->data);
assert(xfer->dataSize);
edma_transfer_config_t xferConfig;
status_t status;
/* If previous TX not finished. */
if (kLPUART_TxBusy == handle->txState)
{
status = kStatus_LPUART_TxBusy;
}
else
{
handle->txState = kLPUART_TxBusy;
handle->txDataSizeAll = xfer->dataSize;
/* Prepare transfer. */
EDMA_PrepareTransfer(&xferConfig, xfer->data, sizeof(uint8_t), (void *)LPUART_GetDataRegisterAddress(base),
sizeof(uint8_t), sizeof(uint8_t), xfer->dataSize, kEDMA_MemoryToPeripheral);
/* Store the initially configured eDMA minor byte transfer count into the LPUART handle */
handle->nbytes = sizeof(uint8_t);
/* Submit transfer. */
EDMA_SubmitTransfer(handle->txEdmaHandle, &xferConfig);
EDMA_StartTransfer(handle->txEdmaHandle);
/* Enable LPUART TX EDMA. */
LPUART_EnableTxDMA(base, true);
status = kStatus_Success;
}
return status;
}
status_t LPUART_ReceiveEDMA(LPUART_Type *base, lpuart_edma_handle_t *handle, lpuart_transfer_t *xfer)
{
assert(handle);
assert(handle->rxEdmaHandle);
assert(xfer);
assert(xfer->data);
assert(xfer->dataSize);
edma_transfer_config_t xferConfig;
status_t status;
/* If previous RX not finished. */
if (kLPUART_RxBusy == handle->rxState)
{
status = kStatus_LPUART_RxBusy;
}
else
{
handle->rxState = kLPUART_RxBusy;
handle->rxDataSizeAll = xfer->dataSize;
/* Prepare transfer. */
EDMA_PrepareTransfer(&xferConfig, (void *)LPUART_GetDataRegisterAddress(base), sizeof(uint8_t), xfer->data,
sizeof(uint8_t), sizeof(uint8_t), xfer->dataSize, kEDMA_PeripheralToMemory);
/* Store the initially configured eDMA minor byte transfer count into the LPUART handle */
handle->nbytes = sizeof(uint8_t);
/* Submit transfer. */
EDMA_SubmitTransfer(handle->rxEdmaHandle, &xferConfig);
EDMA_StartTransfer(handle->rxEdmaHandle);
/* Enable LPUART RX EDMA. */
LPUART_EnableRxDMA(base, true);
status = kStatus_Success;
}
return status;
}
void LPUART_TransferAbortSendEDMA(LPUART_Type *base, lpuart_edma_handle_t *handle)
{
assert(handle);
assert(handle->txEdmaHandle);
/* Disable LPUART TX EDMA. */
LPUART_EnableTxDMA(base, false);
/* Stop transfer. */
EDMA_AbortTransfer(handle->txEdmaHandle);
handle->txState = kLPUART_TxIdle;
}
void LPUART_TransferAbortReceiveEDMA(LPUART_Type *base, lpuart_edma_handle_t *handle)
{
assert(handle);
assert(handle->rxEdmaHandle);
/* Disable LPUART RX EDMA. */
LPUART_EnableRxDMA(base, false);
/* Stop transfer. */
EDMA_AbortTransfer(handle->rxEdmaHandle);
handle->rxState = kLPUART_RxIdle;
}
status_t LPUART_TransferGetReceiveCountEDMA(LPUART_Type *base, lpuart_edma_handle_t *handle, uint32_t *count)
{
assert(handle);
assert(handle->rxEdmaHandle);
assert(count);
if (kLPUART_RxIdle == handle->rxState)
{
return kStatus_NoTransferInProgress;
}
*count = handle->rxDataSizeAll -
(uint32_t)handle->nbytes *
EDMA_GetRemainingMajorLoopCount(handle->rxEdmaHandle->base, handle->rxEdmaHandle->channel);
return kStatus_Success;
}
status_t LPUART_TransferGetSendCountEDMA(LPUART_Type *base, lpuart_edma_handle_t *handle, uint32_t *count)
{
assert(handle);
assert(handle->txEdmaHandle);
assert(count);
if (kLPUART_TxIdle == handle->txState)
{
return kStatus_NoTransferInProgress;
}
*count = handle->txDataSizeAll -
(uint32_t)handle->nbytes *
EDMA_GetRemainingMajorLoopCount(handle->txEdmaHandle->base, handle->txEdmaHandle->channel);
return kStatus_Success;
}

View File

@ -0,0 +1,167 @@
/*
* Copyright (c) 2015, Freescale Semiconductor, Inc.
* Copyright 2016-2017 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef _FSL_LPUART_EDMA_H_
#define _FSL_LPUART_EDMA_H_
#include "fsl_lpuart.h"
#include "fsl_edma.h"
/*!
* @addtogroup lpuart_edma_driver
* @{
*/
/*******************************************************************************
* Definitions
******************************************************************************/
/* Forward declaration of the handle typedef. */
typedef struct _lpuart_edma_handle lpuart_edma_handle_t;
/*! @brief LPUART transfer callback function. */
typedef void (*lpuart_edma_transfer_callback_t)(LPUART_Type *base,
lpuart_edma_handle_t *handle,
status_t status,
void *userData);
/*!
* @brief LPUART eDMA handle
*/
struct _lpuart_edma_handle
{
lpuart_edma_transfer_callback_t callback; /*!< Callback function. */
void *userData; /*!< LPUART callback function parameter.*/
size_t rxDataSizeAll; /*!< Size of the data to receive. */
size_t txDataSizeAll; /*!< Size of the data to send out. */
edma_handle_t *txEdmaHandle; /*!< The eDMA TX channel used. */
edma_handle_t *rxEdmaHandle; /*!< The eDMA RX channel used. */
uint8_t nbytes; /*!< eDMA minor byte transfer count initially configured. */
volatile uint8_t txState; /*!< TX transfer state. */
volatile uint8_t rxState; /*!< RX transfer state */
};
/*******************************************************************************
* API
******************************************************************************/
#if defined(__cplusplus)
extern "C" {
#endif
/*!
* @name eDMA transactional
* @{
*/
/*!
* @brief Initializes the LPUART handle which is used in transactional functions.
* @param base LPUART peripheral base address.
* @param handle Pointer to lpuart_edma_handle_t structure.
* @param callback Callback function.
* @param userData User data.
* @param txEdmaHandle User requested DMA handle for TX DMA transfer.
* @param rxEdmaHandle User requested DMA handle for RX DMA transfer.
*/
void LPUART_TransferCreateHandleEDMA(LPUART_Type *base,
lpuart_edma_handle_t *handle,
lpuart_edma_transfer_callback_t callback,
void *userData,
edma_handle_t *txEdmaHandle,
edma_handle_t *rxEdmaHandle);
/*!
* @brief Sends data using eDMA.
*
* This function sends data using eDMA. This is a non-blocking function, which returns
* right away. When all data is sent, the send callback function is called.
*
* @param base LPUART peripheral base address.
* @param handle LPUART handle pointer.
* @param xfer LPUART eDMA transfer structure. See #lpuart_transfer_t.
* @retval kStatus_Success if succeed, others failed.
* @retval kStatus_LPUART_TxBusy Previous transfer on going.
* @retval kStatus_InvalidArgument Invalid argument.
*/
status_t LPUART_SendEDMA(LPUART_Type *base, lpuart_edma_handle_t *handle, lpuart_transfer_t *xfer);
/*!
* @brief Receives data using eDMA.
*
* This function receives data using eDMA. This is non-blocking function, which returns
* right away. When all data is received, the receive callback function is called.
*
* @param base LPUART peripheral base address.
* @param handle Pointer to lpuart_edma_handle_t structure.
* @param xfer LPUART eDMA transfer structure, see #lpuart_transfer_t.
* @retval kStatus_Success if succeed, others fail.
* @retval kStatus_LPUART_RxBusy Previous transfer ongoing.
* @retval kStatus_InvalidArgument Invalid argument.
*/
status_t LPUART_ReceiveEDMA(LPUART_Type *base, lpuart_edma_handle_t *handle, lpuart_transfer_t *xfer);
/*!
* @brief Aborts the sent data using eDMA.
*
* This function aborts the sent data using eDMA.
*
* @param base LPUART peripheral base address.
* @param handle Pointer to lpuart_edma_handle_t structure.
*/
void LPUART_TransferAbortSendEDMA(LPUART_Type *base, lpuart_edma_handle_t *handle);
/*!
* @brief Aborts the received data using eDMA.
*
* This function aborts the received data using eDMA.
*
* @param base LPUART peripheral base address.
* @param handle Pointer to lpuart_edma_handle_t structure.
*/
void LPUART_TransferAbortReceiveEDMA(LPUART_Type *base, lpuart_edma_handle_t *handle);
/*!
* @brief Gets the number of bytes written to the LPUART TX register.
*
* This function gets the number of bytes written to the LPUART TX
* register by DMA.
*
* @param base LPUART peripheral base address.
* @param handle LPUART handle pointer.
* @param count Send bytes count.
* @retval kStatus_NoTransferInProgress No send in progress.
* @retval kStatus_InvalidArgument Parameter is invalid.
* @retval kStatus_Success Get successfully through the parameter \p count;
*/
status_t LPUART_TransferGetSendCountEDMA(LPUART_Type *base, lpuart_edma_handle_t *handle, uint32_t *count);
/*!
* @brief Gets the number of received bytes.
*
* This function gets the number of received bytes.
*
* @param base LPUART peripheral base address.
* @param handle LPUART handle pointer.
* @param count Receive bytes count.
* @retval kStatus_NoTransferInProgress No receive in progress.
* @retval kStatus_InvalidArgument Parameter is invalid.
* @retval kStatus_Success Get successfully through the parameter \p count;
*/
status_t LPUART_TransferGetReceiveCountEDMA(LPUART_Type *base, lpuart_edma_handle_t *handle, uint32_t *count);
/*@}*/
#if defined(__cplusplus)
}
#endif
/*! @}*/
#endif /* _FSL_LPUART_EDMA_H_ */

View File

@ -0,0 +1,63 @@
/*
* Copyright (c) 2015, Freescale Semiconductor, Inc.
* Copyright 2016-2017 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include "fsl_mmdvsq.h"
/*******************************************************************************
* Code
******************************************************************************/
int32_t MMDVSQ_GetDivideRemainder(MMDVSQ_Type *base, int32_t dividend, int32_t divisor, bool isUnsigned)
{
uint32_t temp = 0;
temp = base->CSR;
temp &= ~(MMDVSQ_CSR_USGN_MASK | MMDVSQ_CSR_REM_MASK);
/* Prepare setting for calculation */
temp |= MMDVSQ_CSR_USGN(isUnsigned) | MMDVSQ_CSR_REM(true);
/* Write setting to CSR register */
base->CSR = temp;
/* Write dividend to DEND register */
base->DEND = dividend;
/* Write divisor to DSOR register and start calculation if Fast-Start is enabled */
base->DSOR = divisor;
/* Start calculation by writing 1 to SRT bit in case Fast-Start is disabled */
base->CSR |= MMDVSQ_CSR_SRT_MASK;
/* Return remainder, if divide-by-zero is enabled and occurred, reading from
* RES result is error terminated */
return base->RES;
}
int32_t MMDVSQ_GetDivideQuotient(MMDVSQ_Type *base, int32_t dividend, int32_t divisor, bool isUnsigned)
{
uint32_t temp = 0;
temp = base->CSR;
temp &= ~(MMDVSQ_CSR_USGN_MASK | MMDVSQ_CSR_REM_MASK);
/* Prepare setting for calculation */
temp |= MMDVSQ_CSR_USGN(isUnsigned) | MMDVSQ_CSR_REM(false);
/* Write setting mode to CSR register */
base->CSR = temp;
/* Write dividend to DEND register */
base->DEND = dividend;
/* Write divisor to DSOR register and start calculation when Fast-Start is enabled */
base->DSOR = divisor;
/* Start calculation by writing 1 to SRT bit in case Fast-Start is disabled */
base->CSR |= MMDVSQ_CSR_SRT_MASK;
/* Return quotient, if divide-by-zero is enabled and occurred, reading from
* RES result is error terminated */
return base->RES;
}
uint16_t MMDVSQ_Sqrt(MMDVSQ_Type *base, uint32_t radicand)
{
/* Write radicand to RCND register , and start calculation */
base->RCND = radicand;
/* Return result */
return base->RES;
}

View File

@ -0,0 +1,179 @@
/*
* Copyright (c) 2015, Freescale Semiconductor, Inc.
* Copyright 2016-2017 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef _FSL_MMDVSQ_H_
#define _FSL_MMDVSQ_H_
#include "fsl_common.h"
/*!
* @addtogroup mmdvsq
* @{
*/
/*******************************************************************************
* Definitions
******************************************************************************/
/*! @name Driver version */
/*@{*/
#define FSL_MMSVSQ_DRIVER_VERSION (MAKE_VERSION(2, 0, 2)) /*!< Version 2.0.2. */
/*@}*/
/*! @brief MMDVSQ execution status */
typedef enum _mmdvsq_execution_status
{
kMMDVSQ_IdleSquareRoot = 0x01U, /*!< MMDVSQ is idle; the last calculation was a square root */
kMMDVSQ_IdleDivide = 0x02U, /*!< MMDVSQ is idle; the last calculation was division */
kMMDVSQ_BusySquareRoot = 0x05U, /*!< MMDVSQ is busy processing a square root calculation */
kMMDVSQ_BusyDivide = 0x06U /*!< MMDVSQ is busy processing a division calculation */
} mmdvsq_execution_status_t;
/*! @brief MMDVSQ divide fast start select */
typedef enum _mmdvsq_fast_start_select
{
kMMDVSQ_EnableFastStart = 0U, /*!< Division operation is initiated by a write to the DSOR register */
kMMDVSQ_DisableFastStart =
1U /*!< Division operation is initiated by a write to CSR[SRT] = 1; normal start instead fast start */
} mmdvsq_fast_start_select_t;
/*******************************************************************************
* API
******************************************************************************/
#if defined(__cplusplus)
extern "C" {
#endif /* __cplusplus */
/*!
* @name MMDVSQ functional Operation
* @{
*/
/*!
* @brief Performs the MMDVSQ division operation and returns the remainder.
*
* @param base MMDVSQ peripheral address
* @param dividend Dividend value
* @param divisor Divisor value
* @param isUnsigned Mode of unsigned divide
* - true unsigned divide
* - false signed divide
*
*/
int32_t MMDVSQ_GetDivideRemainder(MMDVSQ_Type *base, int32_t dividend, int32_t divisor, bool isUnsigned);
/*!
* @brief Performs the MMDVSQ division operation and returns the quotient.
*
* @param base MMDVSQ peripheral address
* @param dividend Dividend value
* @param divisor Divisor value
* @param isUnsigned Mode of unsigned divide
* - true unsigned divide
* - false signed divide
*
*/
int32_t MMDVSQ_GetDivideQuotient(MMDVSQ_Type *base, int32_t dividend, int32_t divisor, bool isUnsigned);
/*!
* @brief Performs the MMDVSQ square root operation.
*
* This function performs the MMDVSQ square root operation and returns the square root
* result of a given radicand value.
*
* @param base MMDVSQ peripheral address
* @param radicand Radicand value
*
*/
uint16_t MMDVSQ_Sqrt(MMDVSQ_Type *base, uint32_t radicand);
/* @} */
/*!
* @name MMDVSQ status Operation
* @{
*/
/*!
* @brief Gets the MMDVSQ execution status.
*
* This function checks the current MMDVSQ execution status of the combined
* CSR[BUSY, DIV, SQRT] indicators.
*
* @param base MMDVSQ peripheral address
*
* @return Current MMDVSQ execution status
*/
static inline mmdvsq_execution_status_t MMDVSQ_GetExecutionStatus(MMDVSQ_Type *base)
{
return (mmdvsq_execution_status_t)(base->CSR >> MMDVSQ_CSR_SQRT_SHIFT);
}
/*!
* @brief Configures MMDVSQ fast start mode.
*
* This function sets the MMDVSQ division fast start. The MMDVSQ supports two
* mechanisms for initiating a division operation. The default mechanism is
* a fast start where a write to the DSOR register begins the division.
* Alternatively, the start mechanism can begin after a write to the CSR
* register with CSR[SRT] set.
*
* @param base MMDVSQ peripheral address
* @param mode Mode of Divide-Fast-Start
* - kMmdvsqDivideFastStart = 0
* - kMmdvsqDivideNormalStart = 1
*/
static inline void MMDVSQ_SetFastStartConfig(MMDVSQ_Type *base, mmdvsq_fast_start_select_t mode)
{
if (mode)
{
base->CSR |= MMDVSQ_CSR_DFS_MASK;
}
else
{
base->CSR &= ~MMDVSQ_CSR_DFS_MASK;
}
}
/*!
* @brief Configures the MMDVSQ divide-by-zero mode.
*
* This function configures the MMDVSQ response to divide-by-zero
* calculations. If both CSR[DZ] and CSR[DZE] are set, then a subsequent read
* of the RES register is error-terminated to signal the processor of the
* attempted divide-by-zero. Otherwise, the register contents are returned.
*
* @param base MMDVSQ peripheral address
* @param isDivByZero Mode of Divide-By-Zero
* - kMmdvsqDivideByZeroDis = 0
* - kMmdvsqDivideByZeroEn = 1
*/
static inline void MMDVSQ_SetDivideByZeroConfig(MMDVSQ_Type *base, bool isDivByZero)
{
if (isDivByZero)
{
base->CSR |= MMDVSQ_CSR_DZE_MASK;
}
else
{
base->CSR &= ~MMDVSQ_CSR_DZE_MASK;
}
}
/* @} */
#if defined(__cplusplus)
}
#endif /* __cplusplus */
/*! @}*/
#endif /* _FSL_MMDVSQ_H_ */

View File

@ -0,0 +1,290 @@
/*
* Copyright (c) 2016, Freescale Semiconductor, Inc.
* Copyright 2016-2017 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include "fsl_msmc.h"
#if defined(__riscv)
#define CONFIG_NORMAL_SLEEP EVENT_UNIT->SLPCTRL = (EVENT_UNIT->SLPCTRL & ~0x03) | (1 << 0)
#define CONFIG_DEEP_SLEEP EVENT_UNIT->SLPCTRL |= 0x03;
#else
#define CONFIG_NORMAL_SLEEP SCB->SCR &= ~SCB_SCR_SLEEPDEEP_Msk
#define CONFIG_DEEP_SLEEP SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk
#endif
status_t SMC_SetPowerModeRun(SMC_Type *base)
{
uint32_t reg;
reg = base->PMCTRL;
/* configure Normal RUN mode */
reg &= ~SMC_PMCTRL_RUNM_MASK;
reg |= (kSMC_RunNormal << SMC_PMCTRL_RUNM_SHIFT);
base->PMCTRL = reg;
return kStatus_Success;
}
status_t SMC_SetPowerModeHsrun(SMC_Type *base)
{
uint32_t reg;
reg = base->PMCTRL;
/* configure High Speed RUN mode */
reg &= ~SMC_PMCTRL_RUNM_MASK;
reg |= (kSMC_Hsrun << SMC_PMCTRL_RUNM_SHIFT);
base->PMCTRL = reg;
return kStatus_Success;
}
status_t SMC_SetPowerModeWait(SMC_Type *base)
{
/* configure Normal Wait mode */
CONFIG_NORMAL_SLEEP;
__DSB();
__WFI();
__ISB();
return kStatus_Success;
}
status_t SMC_SetPowerModeStop(SMC_Type *base, smc_partial_stop_option_t option)
{
uint32_t reg;
/* configure the Partial Stop mode in Noraml Stop mode */
reg = base->PMCTRL;
reg &= ~(SMC_PMCTRL_PSTOPO_MASK | SMC_PMCTRL_STOPM_MASK);
reg |= ((uint32_t)option << SMC_PMCTRL_PSTOPO_SHIFT) | (kSMC_StopNormal << SMC_PMCTRL_STOPM_SHIFT);
base->PMCTRL = reg;
/* Set the SLEEPDEEP bit to enable deep sleep mode (stop mode) */
CONFIG_DEEP_SLEEP;
/* read back to make sure the configuration valid before entering stop mode */
(void)base->PMCTRL;
__DSB();
__WFI();
__ISB();
#if (defined(FSL_FEATURE_SMC_HAS_PMCTRL_STOPA) && FSL_FEATURE_SMC_HAS_PMCTRL_STOPA)
/* check whether the power mode enter Stop mode succeed */
if (base->PMCTRL & SMC_PMCTRL_STOPA_MASK)
{
return kStatus_SMC_StopAbort;
}
else
{
return kStatus_Success;
}
#else
return kStatus_Success;
#endif /* FSL_FEATURE_SMC_HAS_PMCTRL_STOPA */
}
status_t SMC_SetPowerModeVlpr(SMC_Type *base)
{
uint32_t reg;
reg = base->PMCTRL;
/* configure VLPR mode */
reg &= ~SMC_PMCTRL_RUNM_MASK;
reg |= (kSMC_RunVlpr << SMC_PMCTRL_RUNM_SHIFT);
base->PMCTRL = reg;
return kStatus_Success;
}
status_t SMC_SetPowerModeVlpw(SMC_Type *base)
{
/* configure VLPW mode */
/* Clear the SLEEPDEEP bit to disable deep sleep mode */
CONFIG_NORMAL_SLEEP;
__DSB();
__WFI();
__ISB();
return kStatus_Success;
}
status_t SMC_SetPowerModeVlps(SMC_Type *base)
{
uint32_t reg;
/* configure VLPS mode */
reg = base->PMCTRL;
reg &= ~SMC_PMCTRL_STOPM_MASK;
reg |= (kSMC_StopVlps << SMC_PMCTRL_STOPM_SHIFT);
base->PMCTRL = reg;
/* Set the SLEEPDEEP bit to enable deep sleep mode */
CONFIG_DEEP_SLEEP;
/* read back to make sure the configuration valid before enter stop mode */
(void)base->PMCTRL;
__DSB();
__WFI();
__ISB();
#if (defined(FSL_FEATURE_SMC_HAS_PMCTRL_STOPA) && FSL_FEATURE_SMC_HAS_PMCTRL_STOPA)
/* check whether the power mode enter Stop mode succeed */
if (base->PMCTRL & SMC_PMCTRL_STOPA_MASK)
{
return kStatus_SMC_StopAbort;
}
else
{
return kStatus_Success;
}
#else
return kStatus_Success;
#endif /* FSL_FEATURE_SMC_HAS_PMCTRL_STOPA */
}
status_t SMC_SetPowerModeLls(SMC_Type *base)
{
uint32_t reg;
/* configure to LLS mode */
reg = base->PMCTRL;
reg &= ~SMC_PMCTRL_STOPM_MASK;
reg |= (kSMC_StopLls << SMC_PMCTRL_STOPM_SHIFT);
base->PMCTRL = reg;
/* Set the SLEEPDEEP bit to enable deep sleep mode */
CONFIG_DEEP_SLEEP;
/* read back to make sure the configuration valid before entering stop mode */
(void)base->PMCTRL;
__DSB();
__WFI();
__ISB();
#if (defined(FSL_FEATURE_SMC_HAS_PMCTRL_STOPA) && FSL_FEATURE_SMC_HAS_PMCTRL_STOPA)
/* check whether the power mode enter Stop mode succeed */
if (base->PMCTRL & SMC_PMCTRL_STOPA_MASK)
{
return kStatus_SMC_StopAbort;
}
else
{
return kStatus_Success;
}
#else
return kStatus_Success;
#endif /* FSL_FEATURE_SMC_HAS_PMCTRL_STOPA */
}
#if (defined(FSL_FEATURE_SMC_HAS_SUB_STOP_MODE) && FSL_FEATURE_SMC_HAS_SUB_STOP_MODE)
#if (defined(FSL_FEATURE_SMC_HAS_STOP_SUBMODE0) && FSL_FEATURE_SMC_HAS_STOP_SUBMODE0)
status_t SMC_SetPowerModeVlls0(SMC_Type *base)
{
uint32_t reg;
/* configure to VLLS mode */
reg = base->PMCTRL;
reg &= ~SMC_PMCTRL_STOPM_MASK;
reg |= (kSMC_StopVlls0 << SMC_PMCTRL_STOPM_SHIFT);
base->PMCTRL = reg;
/* Set the SLEEPDEEP bit to enable deep sleep mode */
CONFIG_DEEP_SLEEP;
/* read back to make sure the configuration valid before enter stop mode */
(void)base->PMCTRL;
__DSB();
__WFI();
__ISB();
return kStatus_Success;
}
#endif /* FSL_FEATURE_SMC_HAS_STOP_SUBMODE0 */
#if (defined(FSL_FEATURE_SMC_HAS_STOP_SUBMODE2) && FSL_FEATURE_SMC_HAS_STOP_SUBMODE2)
status_t SMC_SetPowerModeVlls2(SMC_Type *base)
{
uint32_t reg;
/* configure to VLLS mode */
reg = base->PMCTRL;
reg &= ~SMC_PMCTRL_STOPM_MASK;
reg |= (kSMC_StopVlls2 << SMC_PMCTRL_STOPM_SHIFT);
base->PMCTRL = reg;
/* Set the SLEEPDEEP bit to enable deep sleep mode */
CONFIG_DEEP_SLEEP;
/* read back to make sure the configuration valid before enter stop mode */
(void)base->PMCTRL;
__DSB();
__WFI();
__ISB();
return kStatus_Success;
}
#endif /* FSL_FEATURE_SMC_HAS_STOP_SUBMODE0 */
#else /* FSL_FEATURE_SMC_HAS_SUB_STOP_MODE */
status_t SMC_SetPowerModeVlls(SMC_Type *base)
{
uint32_t reg;
/* configure to VLLS mode */
reg = base->PMCTRL;
reg &= ~SMC_PMCTRL_STOPM_MASK;
reg |= (kSMC_StopVlls << SMC_PMCTRL_STOPM_SHIFT);
base->PMCTRL = reg;
#if defined(__riscv)
EVENT->SCR = (EVENT->SCR & ~0x03) | (1 << 1);
#else
/* Set the SLEEPDEEP bit to enable deep sleep mode */
CONFIG_DEEP_SLEEP;
#endif
/* read back to make sure the configuration valid before enter stop mode */
(void)base->PMCTRL;
__DSB();
__WFI();
__ISB();
#if (defined(FSL_FEATURE_SMC_HAS_PMCTRL_STOPA) && FSL_FEATURE_SMC_HAS_PMCTRL_STOPA)
/* check whether the power mode enter Stop mode succeed */
if (base->PMCTRL & SMC_PMCTRL_STOPA_MASK)
{
return kStatus_SMC_StopAbort;
}
else
{
return kStatus_Success;
}
#else
return kStatus_Success;
#endif /* FSL_FEATURE_SMC_HAS_PMCTRL_STOPA */
}
#endif /* FSL_FEATURE_SMC_HAS_SUB_STOP_MODE */
void SMC_ConfigureResetPinFilter(SMC_Type *base, const smc_reset_pin_filter_config_t *config)
{
assert(config);
uint32_t reg;
reg = SMC_RPC_FILTCFG(config->slowClockFilterCount) | SMC_RPC_FILTEN(config->enableFilter);
#if (defined(FSL_FEATURE_SMC_HAS_RPC_LPOFEN) && FSL_FEATURE_SMC_HAS_RPC_LPOFEN)
if (config->enableLpoFilter)
{
reg |= SMC_RPC_LPOFEN_MASK;
}
#endif /* FSL_FEATURE_SMC_HAS_RPC_LPOFEN */
base->RPC = reg;
}

View File

@ -0,0 +1,701 @@
/*
* Copyright (c) 2016, Freescale Semiconductor, Inc.
* Copyright 2016-2017 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef _FSL_MSMC_H_
#define _FSL_MSMC_H_
#include "fsl_common.h"
/*! @addtogroup msmc */
/*! @{*/
/*! @file */
/*******************************************************************************
* Definitions
******************************************************************************/
/*! @name Driver version */
/*@{*/
/*! @brief MSMC driver version 2.1.0. */
#define FSL_MSMC_DRIVER_VERSION (MAKE_VERSION(2, 1, 0))
/*@}*/
/*!
* @brief Power Modes Protection
*/
typedef enum _smc_power_mode_protection
{
kSMC_AllowPowerModeVlls = SMC_PMPROT_AVLLS_MASK, /*!< Allow Very-Low-Leakage Stop Mode. */
kSMC_AllowPowerModeLls = SMC_PMPROT_ALLS_MASK, /*!< Allow Low-Leakage Stop Mode. */
kSMC_AllowPowerModeVlp = SMC_PMPROT_AVLP_MASK, /*!< Allow Very-Low-Power Mode. */
kSMC_AllowPowerModeHsrun = SMC_PMPROT_AHSRUN_MASK, /*!< Allow High Speed Run mode. */
kSMC_AllowPowerModeAll = SMC_PMPROT_AVLLS_MASK | SMC_PMPROT_ALLS_MASK | SMC_PMPROT_AVLP_MASK |
SMC_PMPROT_AHSRUN_MASK /*!< Allow all power mode. */
} smc_power_mode_protection_t;
/*!
* @brief Power Modes in PMSTAT
*/
typedef enum _smc_power_state
{
kSMC_PowerStateRun = 1U, /*!< 0000_0001 - Current power mode is RUN */
kSMC_PowerStateStop = 1U << 1U, /*!< 0000_0010 - Current power mode is any STOP mode */
kSMC_PowerStateVlpr = 1U << 2U, /*!< 0000_0100 - Current power mode is VLPR */
kSMC_PowerStateHsrun = 1U << 7U /*!< 1000_0000 - Current power mode is HSRUN */
} smc_power_state_t;
/*!
* @brief Power Stop Entry Status in PMSTAT
*/
typedef enum _smc_power_stop_entry_status
{
kSMC_PowerStopEntryAlt0 = 1U, /*!< Indicates a Stop mode entry since this field was last cleared. */
kSMC_PowerStopEntryAlt1 = 1U << 1, /*!< Indicates the system bus masters acknowledged the Stop mode entry. */
kSMC_PowerStopEntryAlt2 = 1U << 2, /*!< Indicates the system clock peripherals acknowledged the Stop mode entry. */
kSMC_PowerStopEntryAlt3 = 1U << 3, /*!< Indicates the bus clock peripherals acknowledged the Stop mode entry. */
kSMC_PowerStopEntryAlt4 = 1U << 4, /*!< Indicates the slow clock peripherals acknowledged the Stop mode entry. */
kSMC_PowerStopEntryAlt5 = 1U << 5, /*!< Indicates Stop mode entry completed. */
} smc_power_stop_entry_status_t;
/*!
* @brief Run mode definition
*/
typedef enum _smc_run_mode
{
kSMC_RunNormal = 0U, /*!< normal RUN mode. */
kSMC_RunVlpr = 2U, /*!< Very-Low-Power RUN mode. */
kSMC_Hsrun = 3U /*!< High Speed Run mode (HSRUN). */
} smc_run_mode_t;
/*!
* @brief Stop mode definition
*/
typedef enum _smc_stop_mode
{
kSMC_StopNormal = 0U, /*!< Normal STOP mode. */
kSMC_StopVlps = 2U, /*!< Very-Low-Power STOP mode. */
kSMC_StopLls = 3U, /*!< Low-Leakage Stop mode. */
#if (defined(FSL_FEATURE_SMC_HAS_SUB_STOP_MODE) && FSL_FEATURE_SMC_HAS_SUB_STOP_MODE)
#if (defined(FSL_FEATURE_SMC_HAS_STOP_SUBMODE2) && FSL_FEATURE_SMC_HAS_STOP_SUBMODE2)
kSMC_StopVlls2 = 4U, /*!< Very-Low-Leakage Stop mode, VLPS2/3. */
#endif /* FSL_FEATURE_SMC_HAS_STOP_SUBMODE2 */
#if (defined(FSL_FEATURE_SMC_HAS_STOP_SUBMODE0) && FSL_FEATURE_SMC_HAS_STOP_SUBMODE0)
kSMC_StopVlls0 = 6U, /*!< Very-Low-Leakage Stop mode, VLPS0/1. */
#endif /* FSL_FEATURE_SMC_HAS_STOP_SUBMODE0 */
#else
kSMC_StopVlls = 4U, /*!< Very-Low-Leakage Stop mode. */
#endif /* FSL_FEATURE_SMC_HAS_SUB_STOP_MODE */
} smc_stop_mode_t;
/*!
* @brief Partial STOP option
*/
typedef enum _smc_partial_stop_mode
{
kSMC_PartialStop = 0U, /*!< STOP - Normal Stop mode*/
kSMC_PartialStop1 = 1U, /*!< Partial Stop with both system and bus clocks disabled*/
kSMC_PartialStop2 = 2U, /*!< Partial Stop with system clock disabled and bus clock enabled*/
kSMC_PartialStop3 = 3U, /*!< Partial Stop with system clock enabled and bus clock disabled*/
} smc_partial_stop_option_t;
/*!
* @brief SMC configuration status
*/
enum _smc_status
{
kStatus_SMC_StopAbort = MAKE_STATUS(kStatusGroup_POWER, 0), /*!< Entering Stop mode is abort*/
};
/*!
* @brief System Reset Source Name definitions
*/
typedef enum _smc_reset_source
{
kSMC_SourceWakeup = SMC_SRS_WAKEUP_MASK, /*!< Very low-leakage wakeup reset */
kSMC_SourcePor = SMC_SRS_POR_MASK, /*!< Power on reset */
kSMC_SourceLvd = SMC_SRS_LVD_MASK, /*!< Low-voltage detect reset */
kSMC_SourceHvd = SMC_SRS_HVD_MASK, /*!< High-voltage detect reset */
kSMC_SourceWarm = SMC_SRS_WARM_MASK, /*!< Warm reset. Warm Reset flag will assert if any of the system reset
sources in this register assert (SRS[31:8]) */
kSMC_SourceFatal = SMC_SRS_FATAL_MASK, /*!< Fatal reset */
kSMC_SourceCore =
SMC_SRS_CORE_MASK, /*!< Software reset that only reset the core, NOT a sticky system reset source. */
kSMC_SourcePin = SMC_SRS_PIN_MASK, /*!< RESET_B pin reset. */
kSMC_SourceMdm = SMC_SRS_MDM_MASK, /*!< MDM reset. */
kSMC_SourceRstAck = SMC_SRS_RSTACK_MASK, /*!< Reset Controller timeout reset. */
kSMC_SourceStopAck = SMC_SRS_STOPACK_MASK, /*!< Stop timeout reset */
kSMC_SourceScg = SMC_SRS_SCG_MASK, /*!< SCG loss of lock or loss of clock */
kSMC_SourceWdog = SMC_SRS_WDOG_MASK, /*!< Watchdog reset */
kSMC_SourceSoftware = SMC_SRS_SW_MASK, /*!< Software reset */
kSMC_SourceLockup = SMC_SRS_LOCKUP_MASK, /*!< Lockup reset. Core lockup or exception. */
kSMC_SourceJtag = SMC_SRS_JTAG_MASK, /*!< JTAG system reset */
#if (defined(FSL_FEATURE_SMC_HAS_SRS_SECVIO) && FSL_FEATURE_SMC_HAS_SRS_SECVIO)
kSMC_SourceSecVio = SMC_SRS_SECVIO_MASK, /*!< Security violation reset */
#endif /* FSL_FEATURE_SMC_HAS_SRS_SECVIO */
#if (defined(FSL_FEATURE_SMC_HAS_SRS_TAMPER) && FSL_FEATURE_SMC_HAS_SRS_TAMPER)
kSMC_SourceTamper = SMC_SRS_TAMPER_MASK, /*!< Tamper reset */
#endif /* FSL_FEATURE_SMC_HAS_SRS_TAMPER */
#if (defined(FSL_FEATURE_SMC_HAS_SRS_CORE0) && FSL_FEATURE_SMC_HAS_SRS_CORE0)
kSMC_SourceCore0 = SMC_SRS_CORE0_MASK, /*!< Core0 System Reset. */
#endif /* FSL_FEATURE_SMC_HAS_SRS_CORE0 */
#if (defined(FSL_FEATURE_SMC_HAS_SRS_CORE1) && FSL_FEATURE_SMC_HAS_SRS_CORE1)
kSMC_SourceCore1 = SMC_SRS_CORE1_MASK, /*!< Core1 System Reset. */
#endif /* FSL_FEATURE_SMC_HAS_SRS_CORE1 */
/* Source All. */
kSMC_SourceAll = SMC_SRS_WAKEUP_MASK | SMC_SRS_POR_MASK | SMC_SRS_LVD_MASK | SMC_SRS_HVD_MASK | SMC_SRS_WARM_MASK |
SMC_SRS_FATAL_MASK | SMC_SRS_CORE_MASK | SMC_SRS_PIN_MASK | SMC_SRS_MDM_MASK |
SMC_SRS_RSTACK_MASK | SMC_SRS_STOPACK_MASK | SMC_SRS_SCG_MASK | SMC_SRS_WDOG_MASK |
SMC_SRS_SW_MASK | SMC_SRS_LOCKUP_MASK | SMC_SRS_JTAG_MASK
#if (defined(FSL_FEATURE_SMC_HAS_SRS_SECVIO) && FSL_FEATURE_SMC_HAS_SRS_SECVIO)
|
SMC_SRS_SECVIO_MASK
#endif /* FSL_FEATURE_SMC_HAS_SRS_SECVIO */
#if (defined(FSL_FEATURE_SMC_HAS_SRS_TAMPER) && FSL_FEATURE_SMC_HAS_SRS_TAMPER)
|
SMC_SRS_TAMPER_MASK
#endif /* FSL_FEATURE_SMC_HAS_SRS_TAMPER */
#if (defined(FSL_FEATURE_SMC_HAS_SRS_CORE0) && FSL_FEATURE_SMC_HAS_SRS_CORE0)
|
SMC_SRS_CORE0_MASK
#endif /* FSL_FEATURE_SMC_HAS_SRS_CORE0 */
#if (defined(FSL_FEATURE_SMC_HAS_SRS_CORE1) && FSL_FEATURE_SMC_HAS_SRS_CORE1)
|
SMC_SRS_CORE1_MASK
#endif /* FSL_FEATURE_SMC_HAS_SRS_CORE1 */
,
} smc_reset_source_t;
/*!
* @brief System reset interrupt enable bit definitions.
*/
typedef enum _smc_interrupt_enable
{
kSMC_IntNone = 0U, /*!< No interrupt enabled. */
kSMC_IntPin = SMC_SRIE_PIN_MASK, /*!< Pin reset interrupt. */
kSMC_IntMdm = SMC_SRIE_MDM_MASK, /*!< MDM reset interrupt. */
kSMC_IntStopAck = SMC_SRIE_STOPACK_MASK, /*!< Stop timeout reset interrupt. */
kSMC_IntWdog = SMC_SRIE_WDOG_MASK, /*!< Watchdog interrupt. */
kSMC_IntSoftware = SMC_SRIE_SW_MASK, /*!< Software reset interrupts. */
kSMC_IntLockup = SMC_SRIE_LOCKUP_MASK, /*!< Lock up interrupt. */
#if (defined(FSL_FEATURE_SMC_HAS_CSRE_CORE0) && FSL_FEATURE_SMC_HAS_CSRE_CORE0)
kSMC_IntCore0 = SMC_SRIE_CORE0_MASK, /*! Core 0 interrupts. */
#endif /* FSL_FEATURE_SMC_HAS_CSRE_CORE0 */
#if (defined(FSL_FEATURE_SMC_HAS_CSRE_CORE1) && FSL_FEATURE_SMC_HAS_CSRE_CORE1)
kSMC_IntCore1 = SMC_SRIE_CORE1_MASK, /*! Core 1 interrupts. */
#endif /* FSL_FEATURE_SMC_HAS_CSRE_CORE1 */
kSMC_IntAll = SMC_SRIE_PIN_MASK | /*!< All system reset interrupts. */
SMC_SRIE_MDM_MASK |
SMC_SRIE_STOPACK_MASK | SMC_SRIE_WDOG_MASK | SMC_SRIE_SW_MASK | SMC_SRIE_LOCKUP_MASK
#if (defined(FSL_FEATURE_SMC_HAS_CSRE_CORE0) && FSL_FEATURE_SMC_HAS_CSRE_CORE0)
|
SMC_SRIE_CORE0_MASK
#endif /* FSL_FEATURE_SMC_HAS_CSRE_CORE0 */
#if (defined(FSL_FEATURE_SMC_HAS_CSRE_CORE1) && FSL_FEATURE_SMC_HAS_CSRE_CORE1)
|
SMC_SRIE_CORE1_MASK
#endif /* FSL_FEATURE_SMC_HAS_CSRE_CORE1 */
} smc_interrupt_enable_t;
/*!
* @brief Reset pin filter configuration
*/
typedef struct _smc_reset_pin_filter_config
{
uint8_t slowClockFilterCount; /*!< Reset pin bus clock filter width from 1 to 32 slow clock cycles. */
bool enableFilter; /*!< Reset pin filter enable/disable. */
#if (defined(FSL_FEATURE_SMC_HAS_RPC_LPOFEN) && FSL_FEATURE_SMC_HAS_RPC_LPOFEN)
bool enableLpoFilter; /*!< LPO clock reset pin filter enabled in all modes. */
#endif /* FSL_FEATURE_SMC_HAS_RPC_LPOFEN */
} smc_reset_pin_filter_config_t;
/*******************************************************************************
* API
******************************************************************************/
#if defined(__cplusplus)
extern "C" {
#endif /* __cplusplus*/
/*! @name System mode controller APIs*/
/*@{*/
/*!
* @brief Configures all power mode protection settings.
*
* This function configures the power mode protection settings for
* supported power modes in the specified chip family. The available power modes
* are defined in the smc_power_mode_protection_t. This should be done at an early
* system level initialization stage. See the reference manual for details.
* This register can only write once after the power reset.
*
* The allowed modes are passed as bit map, for example, to allow LLS and VLLS,
* use SMC_SetPowerModeProtection(kSMC_AllowPowerModeLls | kSMC_AllowPowerModeVlls).
* To allow all modes, use SMC_SetPowerModeProtection(kSMC_AllowPowerModeAll).
*
* @param allowedModes Bitmap of the allowed power modes.
*/
static inline void SMC_SetPowerModeProtection(SMC_Type *base, uint8_t allowedModes)
{
base->PMPROT = allowedModes;
}
/*!
* @brief Gets the current power mode status.
*
* This function returns the current power mode stat. Once application
* switches the power mode, it should always check the stat to check whether it
* runs into the specified mode or not. An application should check
* this mode before switching to a different mode. The system requires that
* only certain modes can switch to other specific modes. See the
* reference manual for details and the smc_power_state_t for information about
* the power stat.
*
* @param base SMC peripheral base address.
* @return Current power mode status.
*/
static inline smc_power_state_t SMC_GetPowerModeState(SMC_Type *base)
{
return (smc_power_state_t)((base->PMSTAT & SMC_PMSTAT_PMSTAT_MASK) >> SMC_PMSTAT_PMSTAT_SHIFT);
}
#if (defined(FSL_FEATURE_SMC_HAS_PMSTAT_STOPSTAT) && FSL_FEATURE_SMC_HAS_PMSTAT_STOPSTAT)
/*!
* @brief Gets the result of the previous stop mode entry.
*
* This function returns the result of the previous stop mode entry.
*
* @param base SMC peripheral base address.
* @return Current power stop entry status.
*/
static inline smc_power_stop_entry_status_t SMC_GetStopEntryStatus(SMC_Type *base)
{
return (smc_power_stop_entry_status_t)((base->PMSTAT & SMC_PMSTAT_STOPSTAT_MASK) >> SMC_PMSTAT_STOPSTAT_SHIFT);
}
/*!
* @brief Clears all the result of the previous stop mode entry.
*
* This function clears all the result of the previous stop mode entry.
*
* @param base SMC peripheral base address.
* @return Current power stop entry status.
*/
static inline void SMC_ClearStopEntryStatus(SMC_Type *base)
{
/* Only write 0x01 to clear this field, all other writes are ignored. */
base->PMSTAT = (base->PMSTAT & ~SMC_PMSTAT_STOPSTAT_MASK) | SMC_PMSTAT_STOPSTAT(0x01);
}
#endif /* FSL_FEATURE_SMC_HAS_PMSTAT_STOPSTAT */
/*!
* @brief Prepare to enter stop modes
*
* This function should be called before entering STOP/VLPS/LLS/VLLS modes.
*/
static inline void SMC_PreEnterStopModes(void)
{
__disable_irq();
__ISB();
}
/*!
* @brief Recovering after wake up from stop modes
*
* This function should be called after wake up from STOP/VLPS/LLS/VLLS modes.
* It is used together with @ref SMC_PreEnterStopModes.
*/
static inline void SMC_PostExitStopModes(void)
{
__enable_irq();
__ISB();
}
/*!
* @brief Prepare to enter wait modes
*
* This function should be called before entering WAIT/VLPW modes..
*/
static inline void SMC_PreEnterWaitModes(void)
{
__disable_irq();
__ISB();
}
/*!
* @brief Recovering after wake up from stop modes
*
* This function should be called after wake up from WAIT/VLPW modes.
* It is used together with @ref SMC_PreEnterWaitModes.
*/
static inline void SMC_PostExitWaitModes(void)
{
__enable_irq();
__ISB();
}
/*!
* @brief Configure the system to RUN power mode.
*
* @param base SMC peripheral base address.
* @return SMC configuration error code.
*/
status_t SMC_SetPowerModeRun(SMC_Type *base);
/*!
* @brief Configure the system to HSRUN power mode.
*
* @param base SMC peripheral base address.
* @return SMC configuration error code.
*/
status_t SMC_SetPowerModeHsrun(SMC_Type *base);
/*!
* @brief Configure the system to WAIT power mode.
*
* @param base SMC peripheral base address.
* @return SMC configuration error code.
*/
status_t SMC_SetPowerModeWait(SMC_Type *base);
/*!
* @brief Configure the system to Stop power mode.
*
* @param base SMC peripheral base address.
* @param option Partial Stop mode option.
* @return SMC configuration error code.
*/
status_t SMC_SetPowerModeStop(SMC_Type *base, smc_partial_stop_option_t option);
/*!
* @brief Configure the system to VLPR power mode.
*
* @param base SMC peripheral base address.
* @return SMC configuration error code.
*/
status_t SMC_SetPowerModeVlpr(SMC_Type *base);
/*!
* @brief Configure the system to VLPW power mode.
*
* @param base SMC peripheral base address.
* @return SMC configuration error code.
*/
status_t SMC_SetPowerModeVlpw(SMC_Type *base);
/*!
* @brief Configure the system to VLPS power mode.
*
* @param base SMC peripheral base address.
* @return SMC configuration error code.
*/
status_t SMC_SetPowerModeVlps(SMC_Type *base);
/*!
* @brief Configure the system to LLS power mode.
*
* @param base SMC peripheral base address.
* @return SMC configuration error code.
*/
status_t SMC_SetPowerModeLls(SMC_Type *base);
#if (defined(FSL_FEATURE_SMC_HAS_SUB_STOP_MODE) && FSL_FEATURE_SMC_HAS_SUB_STOP_MODE)
#if (defined(FSL_FEATURE_SMC_HAS_STOP_SUBMODE0) && FSL_FEATURE_SMC_HAS_STOP_SUBMODE0)
/*!
* @brief Configure the system to VLLS0 power mode.
*
* @param base SMC peripheral base address.
* @return SMC configuration error code.
*/
status_t SMC_SetPowerModeVlls0(SMC_Type *base);
#endif /* FSL_FEATURE_SMC_HAS_STOP_SUBMODE0 */
#if (defined(FSL_FEATURE_SMC_HAS_STOP_SUBMODE2) && FSL_FEATURE_SMC_HAS_STOP_SUBMODE2)
/*!
* @brief Configure the system to VLLS2 power mode.
*
* @param base SMC peripheral base address.
* @return SMC configuration error code.
*/
status_t SMC_SetPowerModeVlls2(SMC_Type *base);
#endif /* FSL_FEATURE_SMC_HAS_STOP_SUBMODE2 */
#else
/*!
* @brief Configure the system to VLLS power mode.
*
* @param base SMC peripheral base address.
* @return SMC configuration error code.
*/
status_t SMC_SetPowerModeVlls(SMC_Type *base);
#endif /* FSL_FEATURE_SMC_HAS_SUB_STOP_MODE */
/*!
* @brief Gets the reset source status which caused a previous reset.
*
* This function gets the current reset source status. Use source masks
* defined in the smc_reset_source_t to get the desired source status.
*
* Example:
@code
uint32_t resetStatus;
// To get all reset source statuses.
resetStatus = SMC_GetPreviousResetSources(SMC0) & kSMC_SourceAll;
// To test whether the MCU is reset using Watchdog.
resetStatus = SMC_GetPreviousResetSources(SMC0) & kSMC_SourceWdog;
// To test multiple reset sources.
resetStatus = SMC_GetPreviousResetSources(SMC0) & (kSMC_SourceWdog | kSMC_SourcePin);
@endcode
*
* @param base SMC peripheral base address.
* @return All reset source status bit map.
*/
static inline uint32_t SMC_GetPreviousResetSources(SMC_Type *base)
{
return base->SRS;
}
/*!
* @brief Gets the sticky reset source status.
*
* This function gets the current reset source status that has not been cleared
* by software for some specific source.
*
* Example:
@code
uint32_t resetStatus;
// To get all reset source statuses.
resetStatus = SMC_GetStickyResetSources(SMC0) & kSMC_SourceAll;
// To test whether the MCU is reset using Watchdog.
resetStatus = SMC_GetStickyResetSources(SMC0) & kSMC_SourceWdog;
// To test multiple reset sources.
resetStatus = SMC_GetStickyResetSources(SMC0) & (kSMC_SourceWdog | kSMC_SourcePin);
@endcode
*
* @param base SMC peripheral base address.
* @return All reset source status bit map.
*/
static inline uint32_t SMC_GetStickyResetSources(SMC_Type *base)
{
return base->SSRS;
}
/*!
* @brief Clears the sticky reset source status.
*
* This function clears the sticky system reset flags indicated by source masks.
*
* Example:
@code
// Clears multiple reset sources.
SMC_ClearStickyResetSources(SMC0, (kSMC_SourceWdog | kSMC_SourcePin));
@endcode
*
* @param base SMC peripheral base address.
* @param sourceMasks reset source status bit map
*/
static inline void SMC_ClearStickyResetSources(SMC_Type *base, uint32_t sourceMasks)
{
base->SSRS = sourceMasks;
}
/*!
* @brief Configures the reset pin filter.
*
* This function sets the reset pin filter including the enablement/disablement and filter width.
*
* @param base SMC peripheral base address.
* @param config Pointer to the configuration structure.
*/
void SMC_ConfigureResetPinFilter(SMC_Type *base, const smc_reset_pin_filter_config_t *config);
/*!
* @brief Sets the system reset interrupt configuration.
*
* For a graceful shut down, the MSMC supports delaying the assertion of the system
* reset for a period of time when the reset interrupt is generated. This function
* can be used to enable the interrupt.
* The interrupts are passed in as bit mask. See smc_interrupt_enable_t for details.
* For example, to delay a reset after the WDOG timeout or PIN reset occurs, configure as follows:
* SMC_SetSystemResetInterruptConfig(SMC0, (kSMC_IntWdog | kSMC_IntPin));
*
* @param base SMC peripheral base address.
* @param intMask Bit mask of the system reset interrupts to enable. See
* smc_interrupt_enable_t for details.
*/
static inline void SMC_SetSystemResetInterruptConfig(SMC_Type *base, uint32_t intMask)
{
base->SRIE = intMask;
}
/*!
* @brief Gets the source status of the system reset interrupt.
*
* This function gets the source status of the reset interrupt. Use source masks
* defined in the smc_interrupt_enable_t to get the desired source status.
*
* Example:
@code
uint32_t interruptStatus;
// To get all reset interrupt source statuses.
interruptStatus = SMC_GetResetInterruptSourcesStatus(SMC0) & kSMC_IntAll;
// To test whether the reset interrupt of Watchdog is pending.
interruptStatus = SMC_GetResetInterruptSourcesStatus(SMC0) & kSMC_IntWdog;
// To test multiple reset interrupt sources.
interruptStatus = SMC_GetResetInterruptSourcesStatus(SMC0) & (kSMC_IntWdog | kSMC_IntPin);
@endcode
*
* @param base SMC peripheral base address.
* @return All reset interrupt source status bit map.
*/
static inline uint32_t SMC_GetResetInterruptSourcesStatus(SMC_Type *base)
{
return base->SRIF;
}
/*!
* @brief Clears the source status of the system reset interrupt.
*
* This function clears the source status of the reset interrupt. Use source masks
* defined in the smc_interrupt_enable_t to get the desired source status.
*
* Example:
@code
uint32_t interruptStatus;
// To clear all reset interrupt source statuses.
MMC_ClearResetInterruptSourcesStatus(SMC0, kSMC_IntAll);
// To clear the reset interrupt of Watchdog.
SMC_ClearResetInterruptSourcesStatus(SMC0, kSMC_IntWdog);
// To clear multiple reset interrupt sources status.
SMC_ClearResetInterruptSourcesStatus(SMC0, (kSMC_IntWdog | kSMC_IntPin));
@endcode
*
* @param base SMC peripheral base address.
* @param All reset interrupt source status bit map to clear.
*/
static inline void SMC_ClearResetInterruptSourcesStatus(SMC_Type *base, uint32_t intMask)
{
base->SRIF = intMask;
}
#if (defined(FSL_FEATURE_SMC_HAS_CSRE) && FSL_FEATURE_SMC_HAS_CSRE)
/*!
* @brief Sets the core software reset feature configuration.
*
* The MSMC supports delaying the assertion of the system reset for a period of time while a core
* software reset is generated. This allows software to recover without reseting the entire system.
* This function can be used to enable/disable the core software reset feature.
* The interrupts are passed in as bit mask. See smc_interrupt_enable_t for details.
* For example, to delay a system after the WDOG timeout or PIN core software reset occurs, configure as follows:
* SMC_SetCoreSoftwareResetConfig(SMC0, (kSMC_IntWdog | kSMC_IntPin));
*
* @param base SMC peripheral base address.
* @param intMask Bit mask of the core software reset to enable. See
* smc_interrupt_enable_t for details.
*/
static inline void SMC_SetCoreSoftwareResetConfig(SMC_Type *base, uint32_t intMask)
{
base->CSRE = intMask;
}
#endif /* FSL_FEATURE_SMC_HAS_CSRE */
/*!
* @brief Gets the boot option configuration.
*
* This function gets the boot option configuration of MSMC.
*
* @param base SMC peripheral base address.
* @return The boot option configuration. 1 means boot option enabled. 0 means not.
*/
static inline uint32_t SMC_GetBootOptionConfig(SMC_Type *base)
{
return base->MR;
}
#if (defined(FSL_FEATURE_SMC_HAS_FM) && FSL_FEATURE_SMC_HAS_FM)
/*!
* @brief Sets the force boot option configuration.
*
* This function sets the focus boot option configuration of MSMC. It can force the corresponding
* boot option config to assert on next system reset.
*
* @param base SMC peripheral base address.
* @param val The boot option configuration for next system reset. 1 - boot option enabled. 0 - not.
*/
static inline void SMC_SetForceBootOptionConfig(SMC_Type *base, uint32_t val)
{
base->FM = val;
}
#if (defined(FSL_FEATURE_SMC_HAS_SRAMLPR) && FSL_FEATURE_SMC_HAS_SRAMLPR)
/*!
* @brief Enables the conresponding SRAM array in low power retention mode.
*
* This function enables the conresponding SRAM array in low power retention mode. By default, the SRAM low pwer is
* disabled, and only in RUN mode.
*
* @param base SMC peripheral base address.
* @param arrayIdx Index of responding SRAM array.
* @param enable Enable the SRAM array in low power retention mode.
*/
static inline void SMC_SRAMEnableLowPowerMode(SMC_Type *base, uint32_t arrayIdx, bool enable)
{
if (enable)
{
base->SRAMLPR |= (1U << arrayIdx); /* Set to be placed in RUN modes. */
}
else
{
base->SRAMLPR &= ~(1U << arrayIdx); /* Clear to be placed in low power retention mode. */
}
}
#endif /* FSL_FEATURE_SMC_HAS_SRAMLPR */
#if (defined(FSL_FEATURE_SMC_HAS_SRAMDSR) && FSL_FEATURE_SMC_HAS_SRAMDSR)
/*!
* @brief Enables the conresponding SRAM array in STOP mode.
*
* This function enables the conresponding SRAM array in STOP modes. By default, the SRAM is retained in STOP modes.
* When disabled, the corresponding SRAM array is powered off in STOP modes.
*
* @param base SMC peripheral base address.
* @param arrayIdx Index of responding SRAM array.
* @param enable Enable the SRAM array in STOP modes.
*/
static inline void SMC_SRAMEnableDeepSleepMode(SMC_Type *base, uint32_t arrayIdx, bool enable)
{
if (enable)
{
base->SRAMDSR &= ~(1U << arrayIdx); /* Clear to be retained in STOP modes. */
}
else
{
base->SRAMDSR |= (1U << arrayIdx); /* Set to be powered off in STOP modes. */
}
}
#endif /* FSL_FEATURE_SMC_HAS_SRAMDSR */
#endif /* FSL_FEATURE_SMC_HAS_FM */
/*@}*/
#if defined(__cplusplus)
}
#endif /* __cplusplus*/
/*! @}*/
#endif /* _FSL_MSMC_H_ */

View File

@ -0,0 +1,230 @@
/*
* Copyright (c) 2015, Freescale Semiconductor, Inc.
* Copyright 2016-2017 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include "fsl_mu.h"
/*******************************************************************************
* Variables
******************************************************************************/
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
/*! @brief Pointers to mu clocks for each instance. */
static const clock_ip_name_t s_muClocks[] = MU_CLOCKS;
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
/*! @brief Pointers to mu bases for each instance. */
static MU_Type *const s_muBases[] = MU_BASE_PTRS;
/******************************************************************************
* Code
*****************************************************************************/
static uint32_t MU_GetInstance(MU_Type *base)
{
uint32_t instance;
/* Find the instance index from base address mappings. */
for (instance = 0; instance < (sizeof(s_muBases)/sizeof(s_muBases[0])); instance++)
{
if (s_muBases[instance] == base)
{
break;
}
}
assert(instance < (sizeof(s_muBases)/sizeof(s_muBases[0])));
return instance;
}
void MU_Init(MU_Type *base)
{
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
CLOCK_EnableClock(s_muClocks[MU_GetInstance(base)]);
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
}
void MU_Deinit(MU_Type *base)
{
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
CLOCK_DisableClock(s_muClocks[MU_GetInstance(base)]);
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
}
void MU_SendMsg(MU_Type *base, uint32_t regIndex, uint32_t msg)
{
assert(regIndex < MU_TR_COUNT);
/* Wait TX register to be empty. */
while (!(base->SR & (kMU_Tx0EmptyFlag >> regIndex)))
{
}
base->TR[regIndex] = msg;
}
uint32_t MU_ReceiveMsg(MU_Type *base, uint32_t regIndex)
{
assert(regIndex < MU_TR_COUNT);
/* Wait RX register to be full. */
while (!(base->SR & (kMU_Rx0FullFlag >> regIndex)))
{
}
return base->RR[regIndex];
}
void MU_SetFlags(MU_Type *base, uint32_t flags)
{
/* Wait for update finished. */
while (base->SR & MU_SR_FUP_MASK)
{
}
MU_SetFlagsNonBlocking(base, flags);
}
status_t MU_TriggerInterrupts(MU_Type *base, uint32_t mask)
{
uint32_t reg = base->CR;
/* Previous interrupt has been accepted. */
if (!(reg & mask))
{
/* All interrupts have been accepted, trigger now. */
reg = (reg & ~(MU_CR_GIRn_MASK | MU_CR_NMI_MASK)) | mask;
base->CR = reg;
return kStatus_Success;
}
else
{
return kStatus_Fail;
}
}
void MU_BootCoreB(MU_Type *base, mu_core_boot_mode_t mode)
{
#if (defined(FSL_FEATURE_MU_HAS_RESET_INT) && FSL_FEATURE_MU_HAS_RESET_INT)
/* Clean the reset de-assert pending flag. */
base->SR = MU_SR_RDIP_MASK;
#endif
#if (defined(FSL_FEATURE_MU_HAS_CCR) && FSL_FEATURE_MU_HAS_CCR)
uint32_t reg = base->CCR;
reg = (reg & ~(MU_CCR_HR_MASK | MU_CCR_RSTH_MASK | MU_CCR_BOOT_MASK)) | MU_CCR_BOOT(mode);
base->CCR = reg;
#else
uint32_t reg = base->CR;
reg = (reg & ~((MU_CR_GIRn_MASK | MU_CR_NMI_MASK) | MU_CR_HR_MASK | MU_CR_RSTH_MASK | MU_CR_BBOOT_MASK)) | MU_CR_BBOOT(mode);
base->CR = reg;
#endif
#if (defined(FSL_FEATURE_MU_HAS_RESET_INT) && FSL_FEATURE_MU_HAS_RESET_INT)
/* Wait for coming out of reset. */
while (!(base->SR & MU_SR_RDIP_MASK))
{
}
#endif
}
void MU_BootOtherCore(MU_Type *base, mu_core_boot_mode_t mode)
{
/*
* MU_BootOtherCore and MU_BootCoreB are the same, MU_BootCoreB is kept
* for compatible with older platforms.
*/
MU_BootCoreB(base, mode);
}
#if (defined(FSL_FEATURE_MU_HAS_CCR) && FSL_FEATURE_MU_HAS_CCR)
void MU_HardwareResetOtherCore(MU_Type *base, bool waitReset, bool holdReset, mu_core_boot_mode_t bootMode)
{
volatile uint32_t sr = 0;
uint32_t ccr = base->CCR & ~(MU_CCR_HR_MASK | MU_CCR_RSTH_MASK | MU_CCR_BOOT_MASK);
ccr |= MU_CCR_BOOT(bootMode);
if (holdReset)
{
ccr |= MU_CCR_RSTH_MASK;
}
/* Clean the reset assert pending flag. */
sr = (MU_SR_RAIP_MASK | MU_SR_RDIP_MASK);
base->SR = sr;
/* Set CCR[HR] to trigger hardware reset. */
base->CCR = ccr | MU_CCR_HR_MASK;
/* If don't wait the other core enters reset, return directly. */
if (!waitReset)
{
return;
}
/* Wait for the other core go to reset. */
while (!(base->SR & MU_SR_RAIP_MASK))
{
}
if (!holdReset)
{
/* Clear CCR[HR]. */
base->CCR = ccr;
/* Wait for the other core out of reset. */
while (!(base->SR & MU_SR_RDIP_MASK))
{
}
}
}
#else
void MU_HardwareResetOtherCore(MU_Type *base, bool waitReset, bool holdReset, mu_core_boot_mode_t bootMode)
{
volatile uint32_t sr = 0;
uint32_t cr = base->CR & ~(MU_CR_HR_MASK | MU_CR_RSTH_MASK | MU_CR_BOOT_MASK | MU_CR_GIRn_MASK | MU_CR_NMI_MASK);
cr |= MU_CR_BOOT(bootMode);
if (holdReset)
{
cr |= MU_CR_RSTH_MASK;
}
/* Clean the reset assert pending flag. */
sr = (MU_SR_RAIP_MASK | MU_SR_RDIP_MASK);
base->SR = sr;
/* Set CR[HR] to trigger hardware reset. */
base->CR = cr | MU_CR_HR_MASK;
/* If don't wait the other core enters reset, return directly. */
if (!waitReset)
{
return;
}
/* Wait for the other core go to reset. */
while (!(base->SR & MU_SR_RAIP_MASK))
{
}
if (!holdReset)
{
/* Clear CR[HR]. */
base->CR = cr;
/* Wait for the other core out of reset. */
while (!(base->SR & MU_SR_RDIP_MASK))
{
}
}
}
#endif

View File

@ -0,0 +1,673 @@
/*
* Copyright (c) 2015, Freescale Semiconductor, Inc.
* Copyright 2016-2017 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef _FSL_MU_H_
#define _FSL_MU_H_
#include "fsl_common.h"
/*!
* @addtogroup mu
* @{
*/
/******************************************************************************
* Definitions
*****************************************************************************/
/*! @name Driver version */
/*@{*/
/*! @brief MU driver version 2.0.1. */
#define FSL_MU_DRIVER_VERSION (MAKE_VERSION(2, 0, 1))
/*@}*/
/*!
* @brief MU status flags.
*/
enum _mu_status_flags
{
kMU_Tx0EmptyFlag = (1U << (MU_SR_TEn_SHIFT + 3U)), /*!< TX0 empty. */
kMU_Tx1EmptyFlag = (1U << (MU_SR_TEn_SHIFT + 2U)), /*!< TX1 empty. */
kMU_Tx2EmptyFlag = (1U << (MU_SR_TEn_SHIFT + 1U)), /*!< TX2 empty. */
kMU_Tx3EmptyFlag = (1U << (MU_SR_TEn_SHIFT + 0U)), /*!< TX3 empty. */
kMU_Rx0FullFlag = (1U << (MU_SR_RFn_SHIFT + 3U)), /*!< RX0 full. */
kMU_Rx1FullFlag = (1U << (MU_SR_RFn_SHIFT + 2U)), /*!< RX1 full. */
kMU_Rx2FullFlag = (1U << (MU_SR_RFn_SHIFT + 1U)), /*!< RX2 full. */
kMU_Rx3FullFlag = (1U << (MU_SR_RFn_SHIFT + 0U)), /*!< RX3 full. */
kMU_GenInt0Flag = (1U << (MU_SR_GIPn_SHIFT + 3U)), /*!< General purpose interrupt 0 pending. */
kMU_GenInt1Flag = (1U << (MU_SR_GIPn_SHIFT + 2U)), /*!< General purpose interrupt 0 pending. */
kMU_GenInt2Flag = (1U << (MU_SR_GIPn_SHIFT + 1U)), /*!< General purpose interrupt 0 pending. */
kMU_GenInt3Flag = (1U << (MU_SR_GIPn_SHIFT + 0U)), /*!< General purpose interrupt 0 pending. */
kMU_EventPendingFlag = MU_SR_EP_MASK, /*!< MU event pending. */
kMU_FlagsUpdatingFlag = MU_SR_FUP_MASK, /*!< MU flags update is on-going. */
#if (defined(FSL_FEATURE_MU_HAS_RESET_INT) && FSL_FEATURE_MU_HAS_RESET_INT)
kMU_ResetAssertInterruptFlag = MU_SR_RAIP_MASK, /*!< The other core reset assert interrupt pending. */
kMU_ResetDeassertInterruptFlag = MU_SR_RDIP_MASK, /*!< The other core reset de-assert interrupt pending. */
#endif
#if (defined(FSL_FEATURE_MU_HAS_SR_RS) && FSL_FEATURE_MU_HAS_SR_RS)
kMU_OtherSideInResetFlag = MU_SR_RS_MASK /*!< The other side is in reset. */
#endif
#if (defined(FSL_FEATURE_MU_HAS_SR_MURIP) && FSL_FEATURE_MU_HAS_SR_MURIP)
kMU_MuResetInterruptFlag = MU_SR_MURIP_MASK, /*!< The other side initializes MU reset. */
#endif
#if (defined(FSL_FEATURE_MU_HAS_SR_HRIP) && FSL_FEATURE_MU_HAS_SR_HRIP)
kMU_HardwareResetInterruptFlag = MU_SR_HRIP_MASK, /*!< Current side has been hardware reset by the other side. */
#endif
};
/*!
* @brief MU interrupt source to enable.
*/
enum _mu_interrupt_enable
{
kMU_Tx0EmptyInterruptEnable = (1U << (MU_CR_TIEn_SHIFT + 3U)), /*!< TX0 empty. */
kMU_Tx1EmptyInterruptEnable = (1U << (MU_CR_TIEn_SHIFT + 2U)), /*!< TX1 empty. */
kMU_Tx2EmptyInterruptEnable = (1U << (MU_CR_TIEn_SHIFT + 1U)), /*!< TX2 empty. */
kMU_Tx3EmptyInterruptEnable = (1U << (MU_CR_TIEn_SHIFT + 0U)), /*!< TX3 empty. */
kMU_Rx0FullInterruptEnable = (1U << (MU_CR_RIEn_SHIFT + 3U)), /*!< RX0 full. */
kMU_Rx1FullInterruptEnable = (1U << (MU_CR_RIEn_SHIFT + 2U)), /*!< RX1 full. */
kMU_Rx2FullInterruptEnable = (1U << (MU_CR_RIEn_SHIFT + 1U)), /*!< RX2 full. */
kMU_Rx3FullInterruptEnable = (1U << (MU_CR_RIEn_SHIFT + 0U)), /*!< RX3 full. */
kMU_GenInt0InterruptEnable = (1U << (MU_CR_GIEn_SHIFT + 3U)), /*!< General purpose interrupt 0. */
kMU_GenInt1InterruptEnable = (1U << (MU_CR_GIEn_SHIFT + 2U)), /*!< General purpose interrupt 1. */
kMU_GenInt2InterruptEnable = (1U << (MU_CR_GIEn_SHIFT + 1U)), /*!< General purpose interrupt 2. */
kMU_GenInt3InterruptEnable = (1U << (MU_CR_GIEn_SHIFT + 0U)), /*!< General purpose interrupt 3. */
#if (defined(FSL_FEATURE_MU_HAS_RESET_INT) && FSL_FEATURE_MU_HAS_RESET_INT)
kMU_ResetAssertInterruptEnable = MU_CR_RAIE_MASK, /*!< The other core reset assert interrupt. */
kMU_ResetDeassertInterruptEnable = MU_CR_RDIE_MASK, /*!< The other core reset de-assert interrupt. */
#endif
#if (defined(FSL_FEATURE_MU_HAS_SR_MURIP) && FSL_FEATURE_MU_HAS_SR_MURIP)
kMU_MuResetInterruptEnable = MU_CR_MURIE_MASK, /*!< The other side initializes MU reset. The interrupt
is ORed with the general purpose interrupt 3. The
general purpose interrupt 3 is issued when the other side
set the MU reset and this interrupt is enabled. */
#endif
#if (defined(FSL_FEATURE_MU_HAS_SR_HRIP) && FSL_FEATURE_MU_HAS_SR_HRIP)
kMU_HardwareResetInterruptEnable = MU_CR_HRIE_MASK, /*!< Current side has been hardware reset by the other side. */
#endif
};
/*!
* @brief MU interrupt that could be triggered to the other core.
*/
enum _mu_interrupt_trigger
{
kMU_NmiInterruptTrigger = MU_CR_NMI_MASK, /*!< NMI interrupt. */
kMU_GenInt0InterruptTrigger = (1U << (MU_CR_GIRn_SHIFT + 3U)), /*!< General purpose interrupt 0. */
kMU_GenInt1InterruptTrigger = (1U << (MU_CR_GIRn_SHIFT + 2U)), /*!< General purpose interrupt 1. */
kMU_GenInt2InterruptTrigger = (1U << (MU_CR_GIRn_SHIFT + 1U)), /*!< General purpose interrupt 2. */
kMU_GenInt3InterruptTrigger = (1U << (MU_CR_GIRn_SHIFT + 0U)) /*!< General purpose interrupt 3. */
};
/*******************************************************************************
* API
******************************************************************************/
#if defined(__cplusplus)
extern "C" {
#endif
/*!
* @name MU initialization.
* @{
*/
/*!
* @brief Initializes the MU module.
*
* This function enables the MU clock only.
*
* @param base MU peripheral base address.
*/
void MU_Init(MU_Type *base);
/*!
* @brief De-initializes the MU module.
*
* This function disables the MU clock only.
*
* @param base MU peripheral base address.
*/
void MU_Deinit(MU_Type *base);
/* @} */
/*!
* @name MU Message
* @{
*/
/*!
* @brief Writes a message to the TX register.
*
* This function writes a message to the specific TX register. It does not check
* whether the TX register is empty or not. The upper layer should make sure the TX
* register is empty before calling this function. This function can be used
* in ISR for better performance.
*
* @code
* while (!(kMU_Tx0EmptyFlag & MU_GetStatusFlags(base))) { } // Wait for TX0 register empty.
* MU_SendMsgNonBlocking(base, 0U, MSG_VAL); // Write message to the TX0 register.
* @endcode
*
* @param base MU peripheral base address.
* @param regIndex TX register index.
* @param msg Message to send.
*/
static inline void MU_SendMsgNonBlocking(MU_Type *base, uint32_t regIndex, uint32_t msg)
{
assert(regIndex < MU_TR_COUNT);
base->TR[regIndex] = msg;
}
/*!
* @brief Blocks to send a message.
*
* This function waits until the TX register is empty and sends the message.
*
* @param base MU peripheral base address.
* @param regIndex TX register index.
* @param msg Message to send.
*/
void MU_SendMsg(MU_Type *base, uint32_t regIndex, uint32_t msg);
/*!
* @brief Reads a message from the RX register.
*
* This function reads a message from the specific RX register. It does not check
* whether the RX register is full or not. The upper layer should make sure the RX
* register is full before calling this function. This function can be used
* in ISR for better performance.
*
* @code
* uint32_t msg;
* while (!(kMU_Rx0FullFlag & MU_GetStatusFlags(base)))
* {
* } // Wait for the RX0 register full.
*
* msg = MU_ReceiveMsgNonBlocking(base, 0U); // Read message from RX0 register.
* @endcode
*
* @param base MU peripheral base address.
* @param regIndex TX register index.
* @return The received message.
*/
static inline uint32_t MU_ReceiveMsgNonBlocking(MU_Type *base, uint32_t regIndex)
{
assert(regIndex < MU_TR_COUNT);
return base->RR[regIndex];
}
/*!
* @brief Blocks to receive a message.
*
* This function waits until the RX register is full and receives the message.
*
* @param base MU peripheral base address.
* @param regIndex RX register index.
* @return The received message.
*/
uint32_t MU_ReceiveMsg(MU_Type *base, uint32_t regIndex);
/* @} */
/*!
* @name MU Flags
* @{
*/
/*!
* @brief Sets the 3-bit MU flags reflect on the other MU side.
*
* This function sets the 3-bit MU flags directly. Every time the 3-bit MU flags are changed,
* the status flag \c kMU_FlagsUpdatingFlag asserts indicating the 3-bit MU flags are
* updating to the other side. After the 3-bit MU flags are updated, the status flag
* \c kMU_FlagsUpdatingFlag is cleared by hardware. During the flags updating period,
* the flags cannot be changed. The upper layer should make sure the status flag
* \c kMU_FlagsUpdatingFlag is cleared before calling this function.
*
* @code
* while (kMU_FlagsUpdatingFlag & MU_GetStatusFlags(base))
* {
* } // Wait for previous MU flags updating.
*
* MU_SetFlagsNonBlocking(base, 0U); // Set the mU flags.
* @endcode
*
* @param base MU peripheral base address.
* @param flags The 3-bit MU flags to set.
*/
static inline void MU_SetFlagsNonBlocking(MU_Type *base, uint32_t flags)
{
uint32_t reg = base->CR;
reg = (reg & ~((MU_CR_GIRn_MASK | MU_CR_NMI_MASK) | MU_CR_Fn_MASK)) | MU_CR_Fn(flags);
base->CR = reg;
}
/*!
* @brief Blocks setting the 3-bit MU flags reflect on the other MU side.
*
* This function blocks setting the 3-bit MU flags. Every time the 3-bit MU flags are changed,
* the status flag \c kMU_FlagsUpdatingFlag asserts indicating the 3-bit MU flags are
* updating to the other side. After the 3-bit MU flags are updated, the status flag
* \c kMU_FlagsUpdatingFlag is cleared by hardware. During the flags updating period,
* the flags cannot be changed. This function waits for the MU status flag
* \c kMU_FlagsUpdatingFlag cleared and sets the 3-bit MU flags.
*
* @param base MU peripheral base address.
* @param flags The 3-bit MU flags to set.
*/
void MU_SetFlags(MU_Type *base, uint32_t flags);
/*!
* @brief Gets the current value of the 3-bit MU flags set by the other side.
*
* This functions gets the current 3-bit MU flags on the current side.
*
* @param base MU peripheral base address.
* @return flags Current value of the 3-bit flags.
*/
static inline uint32_t MU_GetFlags(MU_Type *base)
{
return (base->SR & MU_SR_Fn_MASK) >> MU_SR_Fn_SHIFT;
}
/* @} */
/*!
* @name Status and Interrupt.
* @{
*/
/*!
* @brief Gets the MU status flags.
*
* This function returns the bit mask of the MU status flags. See _mu_status_flags.
*
* @code
* uint32_t flags;
* flags = MU_GetStatusFlags(base); // Get all status flags.
* if (kMU_Tx0EmptyFlag & flags)
* {
* // The TX0 register is empty. Message can be sent.
* MU_SendMsgNonBlocking(base, 0U, MSG0_VAL);
* }
* if (kMU_Tx1EmptyFlag & flags)
* {
* // The TX1 register is empty. Message can be sent.
* MU_SendMsgNonBlocking(base, 1U, MSG1_VAL);
* }
* @endcode
*
* @param base MU peripheral base address.
* @return Bit mask of the MU status flags, see _mu_status_flags.
*/
static inline uint32_t MU_GetStatusFlags(MU_Type *base)
{
return (base->SR & (MU_SR_TEn_MASK | MU_SR_RFn_MASK | MU_SR_GIPn_MASK | MU_SR_EP_MASK | MU_SR_FUP_MASK
#if (defined(FSL_FEATURE_MU_HAS_SR_RS) && FSL_FEATURE_MU_HAS_SR_RS)
| MU_SR_RS_MASK
#endif
#if (defined(FSL_FEATURE_MU_HAS_RESET_INT) && FSL_FEATURE_MU_HAS_RESET_INT)
| MU_SR_RDIP_MASK | MU_SR_RAIP_MASK
#endif
#if (defined(FSL_FEATURE_MU_HAS_SR_MURIP) && FSL_FEATURE_MU_HAS_SR_MURIP)
| MU_SR_MURIP_MASK
#endif
#if (defined(FSL_FEATURE_MU_HAS_SR_HRIP) && FSL_FEATURE_MU_HAS_SR_HRIP)
| MU_SR_HRIP_MASK
#endif
));
}
/*!
* @brief Clears the specific MU status flags.
*
* This function clears the specific MU status flags. The flags to clear should
* be passed in as bit mask. See _mu_status_flags.
*
* @code
* //Clear general interrupt 0 and general interrupt 1 pending flags.
* MU_ClearStatusFlags(base, kMU_GenInt0Flag | kMU_GenInt1Flag);
* @endcode
*
* @param base MU peripheral base address.
* @param mask Bit mask of the MU status flags. See _mu_status_flags. The following
* flags are cleared by hardware, this function could not clear them.
* - kMU_Tx0EmptyFlag
* - kMU_Tx1EmptyFlag
* - kMU_Tx2EmptyFlag
* - kMU_Tx3EmptyFlag
* - kMU_Rx0FullFlag
* - kMU_Rx1FullFlag
* - kMU_Rx2FullFlag
* - kMU_Rx3FullFlag
* - kMU_EventPendingFlag
* - kMU_FlagsUpdatingFlag
* - kMU_OtherSideInResetFlag
*/
static inline void MU_ClearStatusFlags(MU_Type *base, uint32_t mask)
{
/* regMask is the mask of w1c status bits. */
uint32_t regMask = MU_SR_GIPn_MASK;
#if (defined(FSL_FEATURE_MU_HAS_RESET_INT) && FSL_FEATURE_MU_HAS_RESET_INT)
regMask |= (MU_SR_RDIP_MASK | MU_SR_RAIP_MASK);
#endif
#if (defined(FSL_FEATURE_MU_HAS_SR_MURIP) && FSL_FEATURE_MU_HAS_SR_MURIP)
regMask |= MU_SR_MURIP_MASK;
#endif
#if (defined(FSL_FEATURE_MU_HAS_SR_HRIP) && FSL_FEATURE_MU_HAS_SR_HRIP)
regMask |= MU_SR_HRIP_MASK;
#endif
base->SR = (mask & regMask);
}
/*!
* @brief Enables the specific MU interrupts.
*
* This function enables the specific MU interrupts. The interrupts to enable
* should be passed in as bit mask. See _mu_interrupt_enable.
*
* @code
* // Enable general interrupt 0 and TX0 empty interrupt.
* MU_EnableInterrupts(base, kMU_GenInt0InterruptEnable | kMU_Tx0EmptyInterruptEnable);
* @endcode
*
* @param base MU peripheral base address.
* @param mask Bit mask of the MU interrupts. See _mu_interrupt_enable.
*/
static inline void MU_EnableInterrupts(MU_Type *base, uint32_t mask)
{
uint32_t reg = base->CR;
reg = (reg & ~(MU_CR_GIRn_MASK | MU_CR_NMI_MASK)) | mask;
base->CR = reg;
}
/*!
* @brief Disables the specific MU interrupts.
*
* This function disables the specific MU interrupts. The interrupts to disable
* should be passed in as bit mask. See _mu_interrupt_enable.
*
* @code
* // Disable general interrupt 0 and TX0 empty interrupt.
* MU_DisableInterrupts(base, kMU_GenInt0InterruptEnable | kMU_Tx0EmptyInterruptEnable);
* @endcode
*
* @param base MU peripheral base address.
* @param mask Bit mask of the MU interrupts. See _mu_interrupt_enable.
*/
static inline void MU_DisableInterrupts(MU_Type *base, uint32_t mask)
{
uint32_t reg = base->CR;
reg &= ~((MU_CR_GIRn_MASK | MU_CR_NMI_MASK) | mask);
base->CR = reg;
}
/*!
* @brief Triggers interrupts to the other core.
*
* This function triggers the specific interrupts to the other core. The interrupts
* to trigger are passed in as bit mask. See \ref _mu_interrupt_trigger.
* The MU should not trigger an interrupt to the other core when the previous interrupt
* has not been processed by the other core. This function checks whether the
* previous interrupts have been processed. If not, it returns an error.
*
* @code
* if (kStatus_Success != MU_TriggerInterrupts(base, kMU_GenInt0InterruptTrigger | kMU_GenInt2InterruptTrigger))
* {
* // Previous general purpose interrupt 0 or general purpose interrupt 2
* // has not been processed by the other core.
* }
* @endcode
*
* @param base MU peripheral base address.
* @param mask Bit mask of the interrupts to trigger. See _mu_interrupt_trigger.
* @retval kStatus_Success Interrupts have been triggered successfully.
* @retval kStatus_Fail Previous interrupts have not been accepted.
*/
status_t MU_TriggerInterrupts(MU_Type *base, uint32_t mask);
/*!
* @brief Clear non-maskable interrupt (NMI) sent by the other core.
*
* This functions clears non-maskable interrupt (NMI) sent by the other core.
*
* @param base MU peripheral base address.
*/
static inline void MU_ClearNmi(MU_Type *base)
{
base->SR = MU_SR_NMIC_MASK;
}
/* @} */
/*!
* @name MU misc functions
* @{
*/
/*!
* @brief Boots the core at B side.
*
* This function sets the B side core's boot configuration and releases the
* core from reset.
*
* @param base MU peripheral base address.
* @param mode Core B boot mode.
* @note Only MU side A can use this function.
*/
void MU_BootCoreB(MU_Type *base, mu_core_boot_mode_t mode);
/*!
* @brief Holds the core reset of B side.
*
* This function causes the core of B side to be held in reset following any reset event.
*
* @param base MU peripheral base address.
* @note Only A side could call this function.
*/
static inline void MU_HoldCoreBReset(MU_Type *base)
{
#if (defined(FSL_FEATURE_MU_HAS_CCR) && FSL_FEATURE_MU_HAS_CCR)
base->CCR |= MU_CCR_RSTH_MASK;
#else /* FSL_FEATURE_MU_HAS_CCR */
uint32_t reg = base->CR;
reg = (reg & ~(MU_CR_GIRn_MASK | MU_CR_NMI_MASK)) | MU_CR_RSTH_MASK;
base->CR = reg;
#endif /* FSL_FEATURE_MU_HAS_CCR */
}
/*!
* @brief Boots the other core.
*
* This function boots the other core with a boot configuration.
*
* @param base MU peripheral base address.
* @param mode The other core boot mode.
*/
void MU_BootOtherCore(MU_Type *base, mu_core_boot_mode_t mode);
/*!
* @brief Holds the other core reset.
*
* This function causes the other core to be held in reset following any reset event.
*
* @param base MU peripheral base address.
*/
static inline void MU_HoldOtherCoreReset(MU_Type *base)
{
/*
* MU_HoldOtherCoreReset and MU_HoldCoreBReset are the same, MU_HoldCoreBReset
* is kept for compatible with older platforms.
*/
MU_HoldCoreBReset(base);
}
/*!
* @brief Resets the MU for both A side and B side.
*
* This function resets the MU for both A side and B side. Before reset, it is
* recommended to interrupt processor B, because this function may affect the
* ongoing processor B programs.
*
* @param base MU peripheral base address.
* @note For some platforms, only MU side A could use this function, check
* reference manual for details.
*/
static inline void MU_ResetBothSides(MU_Type *base)
{
uint32_t reg = base->CR;
reg = (reg & ~(MU_CR_GIRn_MASK | MU_CR_NMI_MASK)) | MU_CR_MUR_MASK;
base->CR = reg;
#if (defined(FSL_FEATURE_MU_HAS_SR_RS) && FSL_FEATURE_MU_HAS_SR_RS)
/* Wait for the other side out of reset. */
while (base->SR & MU_SR_RS_MASK)
{
}
#endif /* FSL_FEATURE_MU_HAS_SR_RS */
}
#if (defined(FSL_FEATURE_MU_HAS_CCR) && FSL_FEATURE_MU_HAS_CCR)
/*!
* @brief Mask hardware reset by the other core.
*
* The other core could call MU_HardwareResetOtherCore() to reset current core.
* To mask the reset, call this function and pass in true.
*
* @param base MU peripheral base address.
* @param mask Pass true to mask the hardware reset, pass false to unmask it.
*/
static inline void MU_MaskHardwareReset(MU_Type *base, bool mask)
{
if (mask)
{
base->CCR |= MU_CCR_HRM_MASK;
}
else
{
base->CCR &= ~MU_CCR_HRM_MASK;
}
}
#endif
/*!
* @brief Hardware reset the other core.
*
* This function resets the other core, the other core could mask the
* hardware reset by calling @ref MU_MaskHardwareReset. The hardware reset
* mask feature is only available for some platforms.
* This function could be used together with MU_BootOtherCore to control the
* other core reset workflow.
*
* Example 1: Reset the other core, and no hold reset
* @code
* MU_HardwareResetOtherCore(MU_A, true, false, bootMode);
* @endcode
* In this example, the core at MU side B will reset with the specified boot mode.
*
* Example 2: Reset the other core and hold it, then boot the other core later.
* @code
* // Here the other core enters reset, and the reset is hold
* MU_HardwareResetOtherCore(MU_A, true, true, modeDontCare);
* // Current core boot the other core when necessary.
* MU_BootOtherCore(MU_A, bootMode);
* @endcode
*
* @param base MU peripheral base address.
* @param waitReset Wait the other core enters reset.
* - true: Wait until the other core enters reset, if the other
* core has masked the hardware reset, then this function will
* be blocked.
* - false: Don't wait the reset.
* @param holdReset Hold the other core reset or not.
* - true: Hold the other core in reset, this function returns
* directly when the other core enters reset.
* - false: Don't hold the other core in reset, this function
* waits until the other core out of reset.
* @param bootMode Boot mode of the other core, if @p holdReset is true, this
* parameter is useless.
*/
void MU_HardwareResetOtherCore(MU_Type *base, bool waitReset, bool holdReset, mu_core_boot_mode_t bootMode);
/*!
* @brief Enables or disables the clock on the other core.
*
* This function enables or disables the platform clock on the other core when
* that core enters a stop mode. If disabled, the platform clock for the other
* core is disabled when it enters stop mode. If enabled, the platform clock
* keeps running on the other core in stop mode, until this core also enters
* stop mode.
*
* @param base MU peripheral base address.
* @param enable Enable or disable the clock on the other core.
*/
static inline void MU_SetClockOnOtherCoreEnable(MU_Type *base, bool enable)
{
#if (defined(FSL_FEATURE_MU_HAS_CCR) && FSL_FEATURE_MU_HAS_CCR)
if (enable)
{
base->CCR |= MU_CCR_CLKE_MASK;
}
else
{
base->CCR &= ~MU_CCR_CLKE_MASK;
}
#else /* FSL_FEATURE_MU_HAS_CCR */
uint32_t reg = base->CR;
reg &= ~(MU_CR_GIRn_MASK | MU_CR_NMI_MASK);
if (enable)
{
reg |= MU_CR_CLKE_MASK;
}
else
{
reg &= ~MU_CR_CLKE_MASK;
}
base->CR = reg;
#endif /* FSL_FEATURE_MU_HAS_CCR */
}
/*!
* @brief Gets the power mode of the other core.
*
* This function gets the power mode of the other core.
*
* @param base MU peripheral base address.
* @return Power mode of the other core.
*/
static inline mu_power_mode_t MU_GetOtherCorePowerMode(MU_Type *base)
{
return (mu_power_mode_t)((base->SR & MU_SR_PM_MASK) >> MU_SR_PM_SHIFT);
}
/* @} */
#if defined(__cplusplus)
}
#endif /*_cplusplus*/
/*@}*/
#endif /* _FSL_MU_H_*/

View File

@ -0,0 +1,464 @@
/*
* Copyright (c) 2015, Freescale Semiconductor, Inc.
* Copyright 2016-2017 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef _FSL_PORT_H_
#define _FSL_PORT_H_
#include "fsl_common.h"
/*!
* @addtogroup port
* @{
*/
/*******************************************************************************
* Definitions
******************************************************************************/
/*! @name Driver version */
/*@{*/
/*! Version 2.0.2. */
#define FSL_PORT_DRIVER_VERSION (MAKE_VERSION(2, 0, 2))
/*@}*/
#if defined(FSL_FEATURE_PORT_HAS_PULL_ENABLE) && FSL_FEATURE_PORT_HAS_PULL_ENABLE
/*! @brief Internal resistor pull feature selection */
enum _port_pull
{
kPORT_PullDisable = 0U, /*!< Internal pull-up/down resistor is disabled. */
kPORT_PullDown = 2U, /*!< Internal pull-down resistor is enabled. */
kPORT_PullUp = 3U, /*!< Internal pull-up resistor is enabled. */
};
#endif /* FSL_FEATURE_PORT_HAS_PULL_ENABLE */
#if defined(FSL_FEATURE_PORT_HAS_SLEW_RATE) && FSL_FEATURE_PORT_HAS_SLEW_RATE
/*! @brief Slew rate selection */
enum _port_slew_rate
{
kPORT_FastSlewRate = 0U, /*!< Fast slew rate is configured. */
kPORT_SlowSlewRate = 1U, /*!< Slow slew rate is configured. */
};
#endif /* FSL_FEATURE_PORT_HAS_SLEW_RATE */
#if defined(FSL_FEATURE_PORT_HAS_OPEN_DRAIN) && FSL_FEATURE_PORT_HAS_OPEN_DRAIN
/*! @brief Open Drain feature enable/disable */
enum _port_open_drain_enable
{
kPORT_OpenDrainDisable = 0U, /*!< Open drain output is disabled. */
kPORT_OpenDrainEnable = 1U, /*!< Open drain output is enabled. */
};
#endif /* FSL_FEATURE_PORT_HAS_OPEN_DRAIN */
#if defined(FSL_FEATURE_PORT_HAS_PASSIVE_FILTER) && FSL_FEATURE_PORT_HAS_PASSIVE_FILTER
/*! @brief Passive filter feature enable/disable */
enum _port_passive_filter_enable
{
kPORT_PassiveFilterDisable = 0U, /*!< Passive input filter is disabled. */
kPORT_PassiveFilterEnable = 1U, /*!< Passive input filter is enabled. */
};
#endif
#if defined(FSL_FEATURE_PORT_HAS_DRIVE_STRENGTH) && FSL_FEATURE_PORT_HAS_DRIVE_STRENGTH
/*! @brief Configures the drive strength. */
enum _port_drive_strength
{
kPORT_LowDriveStrength = 0U, /*!< Low-drive strength is configured. */
kPORT_HighDriveStrength = 1U, /*!< High-drive strength is configured. */
};
#endif /* FSL_FEATURE_PORT_HAS_DRIVE_STRENGTH */
#if defined(FSL_FEATURE_PORT_HAS_PIN_CONTROL_LOCK) && FSL_FEATURE_PORT_HAS_PIN_CONTROL_LOCK
/*! @brief Unlock/lock the pin control register field[15:0] */
enum _port_lock_register
{
kPORT_UnlockRegister = 0U, /*!< Pin Control Register fields [15:0] are not locked. */
kPORT_LockRegister = 1U, /*!< Pin Control Register fields [15:0] are locked. */
};
#endif /* FSL_FEATURE_PORT_HAS_PIN_CONTROL_LOCK */
#if defined(FSL_FEATURE_PORT_PCR_MUX_WIDTH) && FSL_FEATURE_PORT_PCR_MUX_WIDTH
/*! @brief Pin mux selection */
typedef enum _port_mux
{
kPORT_PinDisabledOrAnalog = 0U, /*!< Corresponding pin is disabled, but is used as an analog pin. */
kPORT_MuxAsGpio = 1U, /*!< Corresponding pin is configured as GPIO. */
kPORT_MuxAlt2 = 2U, /*!< Chip-specific */
kPORT_MuxAlt3 = 3U, /*!< Chip-specific */
kPORT_MuxAlt4 = 4U, /*!< Chip-specific */
kPORT_MuxAlt5 = 5U, /*!< Chip-specific */
kPORT_MuxAlt6 = 6U, /*!< Chip-specific */
kPORT_MuxAlt7 = 7U, /*!< Chip-specific */
kPORT_MuxAlt8 = 8U, /*!< Chip-specific */
kPORT_MuxAlt9 = 9U, /*!< Chip-specific */
kPORT_MuxAlt10 = 10U, /*!< Chip-specific */
kPORT_MuxAlt11 = 11U, /*!< Chip-specific */
kPORT_MuxAlt12 = 12U, /*!< Chip-specific */
kPORT_MuxAlt13 = 13U, /*!< Chip-specific */
kPORT_MuxAlt14 = 14U, /*!< Chip-specific */
kPORT_MuxAlt15 = 15U, /*!< Chip-specific */
} port_mux_t;
#endif /* FSL_FEATURE_PORT_PCR_MUX_WIDTH */
/*! @brief Configures the interrupt generation condition. */
typedef enum _port_interrupt
{
kPORT_InterruptOrDMADisabled = 0x0U, /*!< Interrupt/DMA request is disabled. */
#if defined(FSL_FEATURE_PORT_HAS_DMA_REQUEST) && FSL_FEATURE_PORT_HAS_DMA_REQUEST
kPORT_DMARisingEdge = 0x1U, /*!< DMA request on rising edge. */
kPORT_DMAFallingEdge = 0x2U, /*!< DMA request on falling edge. */
kPORT_DMAEitherEdge = 0x3U, /*!< DMA request on either edge. */
#endif
#if defined(FSL_FEATURE_PORT_HAS_IRQC_FLAG) && FSL_FEATURE_PORT_HAS_IRQC_FLAG
kPORT_FlagRisingEdge = 0x05U, /*!< Flag sets on rising edge. */
kPORT_FlagFallingEdge = 0x06U, /*!< Flag sets on falling edge. */
kPORT_FlagEitherEdge = 0x07U, /*!< Flag sets on either edge. */
#endif
kPORT_InterruptLogicZero = 0x8U, /*!< Interrupt when logic zero. */
kPORT_InterruptRisingEdge = 0x9U, /*!< Interrupt on rising edge. */
kPORT_InterruptFallingEdge = 0xAU, /*!< Interrupt on falling edge. */
kPORT_InterruptEitherEdge = 0xBU, /*!< Interrupt on either edge. */
kPORT_InterruptLogicOne = 0xCU, /*!< Interrupt when logic one. */
#if defined(FSL_FEATURE_PORT_HAS_IRQC_TRIGGER) && FSL_FEATURE_PORT_HAS_IRQC_TRIGGER
kPORT_ActiveHighTriggerOutputEnable = 0xDU, /*!< Enable active high-trigger output. */
kPORT_ActiveLowTriggerOutputEnable = 0xEU, /*!< Enable active low-trigger output. */
#endif
} port_interrupt_t;
#if defined(FSL_FEATURE_PORT_HAS_DIGITAL_FILTER) && FSL_FEATURE_PORT_HAS_DIGITAL_FILTER
/*! @brief Digital filter clock source selection */
typedef enum _port_digital_filter_clock_source
{
kPORT_BusClock = 0U, /*!< Digital filters are clocked by the bus clock. */
kPORT_LpoClock = 1U, /*!< Digital filters are clocked by the 1 kHz LPO clock. */
} port_digital_filter_clock_source_t;
/*! @brief PORT digital filter feature configuration definition */
typedef struct _port_digital_filter_config
{
uint32_t digitalFilterWidth; /*!< Set digital filter width */
port_digital_filter_clock_source_t clockSource; /*!< Set digital filter clockSource */
} port_digital_filter_config_t;
#endif /* FSL_FEATURE_PORT_HAS_DIGITAL_FILTER */
#if defined(FSL_FEATURE_PORT_PCR_MUX_WIDTH) && FSL_FEATURE_PORT_PCR_MUX_WIDTH
/*! @brief PORT pin configuration structure */
typedef struct _port_pin_config
{
#if defined(FSL_FEATURE_PORT_HAS_PULL_ENABLE) && FSL_FEATURE_PORT_HAS_PULL_ENABLE
uint16_t pullSelect : 2; /*!< No-pull/pull-down/pull-up select */
#else
uint16_t : 2;
#endif /* FSL_FEATURE_PORT_HAS_PULL_ENABLE */
#if defined(FSL_FEATURE_PORT_HAS_SLEW_RATE) && FSL_FEATURE_PORT_HAS_SLEW_RATE
uint16_t slewRate : 1; /*!< Fast/slow slew rate Configure */
#else
uint16_t : 1;
#endif /* FSL_FEATURE_PORT_HAS_SLEW_RATE */
uint16_t : 1;
#if defined(FSL_FEATURE_PORT_HAS_PASSIVE_FILTER) && FSL_FEATURE_PORT_HAS_PASSIVE_FILTER
uint16_t passiveFilterEnable : 1; /*!< Passive filter enable/disable */
#else
uint16_t : 1;
#endif /* FSL_FEATURE_PORT_HAS_PASSIVE_FILTER */
#if defined(FSL_FEATURE_PORT_HAS_OPEN_DRAIN) && FSL_FEATURE_PORT_HAS_OPEN_DRAIN
uint16_t openDrainEnable : 1; /*!< Open drain enable/disable */
#else
uint16_t : 1;
#endif /* FSL_FEATURE_PORT_HAS_OPEN_DRAIN */
#if defined(FSL_FEATURE_PORT_HAS_DRIVE_STRENGTH) && FSL_FEATURE_PORT_HAS_DRIVE_STRENGTH
uint16_t driveStrength : 1; /*!< Fast/slow drive strength configure */
#else
uint16_t : 1;
#endif
uint16_t : 1;
#if defined(FSL_FEATURE_PORT_PCR_MUX_WIDTH) && (FSL_FEATURE_PORT_PCR_MUX_WIDTH == 3)
uint16_t mux : 3; /*!< Pin mux Configure */
uint16_t : 4;
#elif defined(FSL_FEATURE_PORT_PCR_MUX_WIDTH) && (FSL_FEATURE_PORT_PCR_MUX_WIDTH == 4)
uint16_t mux : 4; /*!< Pin mux Configure */
uint16_t : 3;
#else
uint16_t : 7,
#endif
#if defined(FSL_FEATURE_PORT_HAS_PIN_CONTROL_LOCK) && FSL_FEATURE_PORT_HAS_PIN_CONTROL_LOCK
uint16_t lockRegister : 1; /*!< Lock/unlock the PCR field[15:0] */
#else
uint16_t : 1;
#endif /* FSL_FEATURE_PORT_HAS_PIN_CONTROL_LOCK */
} port_pin_config_t;
#endif /* FSL_FEATURE_PORT_PCR_MUX_WIDTH */
/*******************************************************************************
* API
******************************************************************************/
#if defined(__cplusplus)
extern "C" {
#endif
#if defined(FSL_FEATURE_PORT_PCR_MUX_WIDTH) && FSL_FEATURE_PORT_PCR_MUX_WIDTH
/*! @name Configuration */
/*@{*/
/*!
* @brief Sets the port PCR register.
*
* This is an example to define an input pin or output pin PCR configuration.
* @code
* // Define a digital input pin PCR configuration
* port_pin_config_t config = {
* kPORT_PullUp,
* kPORT_FastSlewRate,
* kPORT_PassiveFilterDisable,
* kPORT_OpenDrainDisable,
* kPORT_LowDriveStrength,
* kPORT_MuxAsGpio,
* kPORT_UnLockRegister,
* };
* @endcode
*
* @param base PORT peripheral base pointer.
* @param pin PORT pin number.
* @param config PORT PCR register configuration structure.
*/
static inline void PORT_SetPinConfig(PORT_Type *base, uint32_t pin, const port_pin_config_t *config)
{
assert(config);
uint32_t addr = (uint32_t)&base->PCR[pin];
*(volatile uint16_t *)(addr) = *((const uint16_t *)config);
}
/*!
* @brief Sets the port PCR register for multiple pins.
*
* This is an example to define input pins or output pins PCR configuration.
* @code
* // Define a digital input pin PCR configuration
* port_pin_config_t config = {
* kPORT_PullUp ,
* kPORT_PullEnable,
* kPORT_FastSlewRate,
* kPORT_PassiveFilterDisable,
* kPORT_OpenDrainDisable,
* kPORT_LowDriveStrength,
* kPORT_MuxAsGpio,
* kPORT_UnlockRegister,
* };
* @endcode
*
* @param base PORT peripheral base pointer.
* @param mask PORT pin number macro.
* @param config PORT PCR register configuration structure.
*/
static inline void PORT_SetMultiplePinsConfig(PORT_Type *base, uint32_t mask, const port_pin_config_t *config)
{
assert(config);
uint16_t pcrl = *((const uint16_t *)config);
if (mask & 0xffffU)
{
base->GPCLR = ((mask & 0xffffU) << 16) | pcrl;
}
if (mask >> 16)
{
base->GPCHR = (mask & 0xffff0000U) | pcrl;
}
}
#if defined(FSL_FEATURE_PORT_HAS_MULTIPLE_IRQ_CONFIG) && FSL_FEATURE_PORT_HAS_MULTIPLE_IRQ_CONFIG
/*!
* @brief Sets the port interrupt configuration in PCR register for multiple pins.
*
* @param base PORT peripheral base pointer.
* @param mask PORT pin number macro.
* @param config PORT pin interrupt configuration.
* - #kPORT_InterruptOrDMADisabled: Interrupt/DMA request disabled.
* - #kPORT_DMARisingEdge : DMA request on rising edge(if the DMA requests exit).
* - #kPORT_DMAFallingEdge: DMA request on falling edge(if the DMA requests exit).
* - #kPORT_DMAEitherEdge : DMA request on either edge(if the DMA requests exit).
* - #kPORT_FlagRisingEdge : Flag sets on rising edge(if the Flag states exit).
* - #kPORT_FlagFallingEdge : Flag sets on falling edge(if the Flag states exit).
* - #kPORT_FlagEitherEdge : Flag sets on either edge(if the Flag states exit).
* - #kPORT_InterruptLogicZero : Interrupt when logic zero.
* - #kPORT_InterruptRisingEdge : Interrupt on rising edge.
* - #kPORT_InterruptFallingEdge: Interrupt on falling edge.
* - #kPORT_InterruptEitherEdge : Interrupt on either edge.
* - #kPORT_InterruptLogicOne : Interrupt when logic one.
* - #kPORT_ActiveHighTriggerOutputEnable : Enable active high-trigger output (if the trigger states exit).
* - #kPORT_ActiveLowTriggerOutputEnable : Enable active low-trigger output (if the trigger states exit)..
*/
static inline void PORT_SetMultipleInterruptPinsConfig(PORT_Type *base, uint32_t mask, port_interrupt_t config)
{
assert(config);
if (mask & 0xffffU)
{
base->GICLR = (config << 16) | (mask & 0xffffU);
}
if (mask >> 16)
{
base->GICHR = (config << 16) | (mask & 0xffff0000U);
}
}
#endif
/*!
* @brief Configures the pin muxing.
*
* @param base PORT peripheral base pointer.
* @param pin PORT pin number.
* @param mux pin muxing slot selection.
* - #kPORT_PinDisabledOrAnalog: Pin disabled or work in analog function.
* - #kPORT_MuxAsGpio : Set as GPIO.
* - #kPORT_MuxAlt2 : chip-specific.
* - #kPORT_MuxAlt3 : chip-specific.
* - #kPORT_MuxAlt4 : chip-specific.
* - #kPORT_MuxAlt5 : chip-specific.
* - #kPORT_MuxAlt6 : chip-specific.
* - #kPORT_MuxAlt7 : chip-specific.
* @Note : This function is NOT recommended to use together with the PORT_SetPinsConfig, because
* the PORT_SetPinsConfig need to configure the pin mux anyway (Otherwise the pin mux is
* reset to zero : kPORT_PinDisabledOrAnalog).
* This function is recommended to use to reset the pin mux
*
*/
static inline void PORT_SetPinMux(PORT_Type *base, uint32_t pin, port_mux_t mux)
{
base->PCR[pin] = (base->PCR[pin] & ~PORT_PCR_MUX_MASK) | PORT_PCR_MUX(mux);
}
#endif /* FSL_FEATURE_PORT_PCR_MUX_WIDTH */
#if defined(FSL_FEATURE_PORT_HAS_DIGITAL_FILTER) && FSL_FEATURE_PORT_HAS_DIGITAL_FILTER
/*!
* @brief Enables the digital filter in one port, each bit of the 32-bit register represents one pin.
*
* @param base PORT peripheral base pointer.
* @param mask PORT pin number macro.
*/
static inline void PORT_EnablePinsDigitalFilter(PORT_Type *base, uint32_t mask, bool enable)
{
if (enable == true)
{
base->DFER |= mask;
}
else
{
base->DFER &= ~mask;
}
}
/*!
* @brief Sets the digital filter in one port, each bit of the 32-bit register represents one pin.
*
* @param base PORT peripheral base pointer.
* @param config PORT digital filter configuration structure.
*/
static inline void PORT_SetDigitalFilterConfig(PORT_Type *base, const port_digital_filter_config_t *config)
{
assert(config);
base->DFCR = PORT_DFCR_CS(config->clockSource);
base->DFWR = PORT_DFWR_FILT(config->digitalFilterWidth);
}
#endif /* FSL_FEATURE_PORT_HAS_DIGITAL_FILTER */
/*@}*/
/*! @name Interrupt */
/*@{*/
/*!
* @brief Configures the port pin interrupt/DMA request.
*
* @param base PORT peripheral base pointer.
* @param pin PORT pin number.
* @param config PORT pin interrupt configuration.
* - #kPORT_InterruptOrDMADisabled: Interrupt/DMA request disabled.
* - #kPORT_DMARisingEdge : DMA request on rising edge(if the DMA requests exit).
* - #kPORT_DMAFallingEdge: DMA request on falling edge(if the DMA requests exit).
* - #kPORT_DMAEitherEdge : DMA request on either edge(if the DMA requests exit).
* - #kPORT_FlagRisingEdge : Flag sets on rising edge(if the Flag states exit).
* - #kPORT_FlagFallingEdge : Flag sets on falling edge(if the Flag states exit).
* - #kPORT_FlagEitherEdge : Flag sets on either edge(if the Flag states exit).
* - #kPORT_InterruptLogicZero : Interrupt when logic zero.
* - #kPORT_InterruptRisingEdge : Interrupt on rising edge.
* - #kPORT_InterruptFallingEdge: Interrupt on falling edge.
* - #kPORT_InterruptEitherEdge : Interrupt on either edge.
* - #kPORT_InterruptLogicOne : Interrupt when logic one.
* - #kPORT_ActiveHighTriggerOutputEnable : Enable active high-trigger output (if the trigger states exit).
* - #kPORT_ActiveLowTriggerOutputEnable : Enable active low-trigger output (if the trigger states exit).
*/
static inline void PORT_SetPinInterruptConfig(PORT_Type *base, uint32_t pin, port_interrupt_t config)
{
base->PCR[pin] = (base->PCR[pin] & ~PORT_PCR_IRQC_MASK) | PORT_PCR_IRQC(config);
}
#if defined(FSL_FEATURE_PORT_HAS_DRIVE_STRENGTH) && FSL_FEATURE_PORT_HAS_DRIVE_STRENGTH
/*!
* @brief Configures the port pin drive strength.
*
* @param base PORT peripheral base pointer.
* @param pin PORT pin number.
* @param config PORT pin drive strength
* - #kPORT_LowDriveStrength = 0U - Low-drive strength is configured.
* - #kPORT_HighDriveStrength = 1U - High-drive strength is configured.
*/
static inline void PORT_SetPinDriveStrength(PORT_Type* base, uint32_t pin, uint8_t strength)
{
base->PCR[pin] = (base->PCR[pin] & ~PORT_PCR_DSE_MASK) | PORT_PCR_DSE(strength);
}
#endif
/*!
* @brief Reads the whole port status flag.
*
* If a pin is configured to generate the DMA request, the corresponding flag
* is cleared automatically at the completion of the requested DMA transfer.
* Otherwise, the flag remains set until a logic one is written to that flag.
* If configured for a level sensitive interrupt that remains asserted, the flag
* is set again immediately.
*
* @param base PORT peripheral base pointer.
* @return Current port interrupt status flags, for example, 0x00010001 means the
* pin 0 and 16 have the interrupt.
*/
static inline uint32_t PORT_GetPinsInterruptFlags(PORT_Type *base)
{
return base->ISFR;
}
/*!
* @brief Clears the multiple pin interrupt status flag.
*
* @param base PORT peripheral base pointer.
* @param mask PORT pin number macro.
*/
static inline void PORT_ClearPinsInterruptFlags(PORT_Type *base, uint32_t mask)
{
base->ISFR = mask;
}
/*@}*/
#if defined(__cplusplus)
}
#endif
/*! @}*/
#endif /* _FSL_PORT_H_ */

View File

@ -0,0 +1,650 @@
/*
* Copyright (c) 2015, Freescale Semiconductor, Inc.
* Copyright 2016-2017 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include "fsl_rtc.h"
/*******************************************************************************
* Definitions
******************************************************************************/
#define SECONDS_IN_A_DAY (86400U)
#define SECONDS_IN_A_HOUR (3600U)
#define SECONDS_IN_A_MINUTE (60U)
#define DAYS_IN_A_YEAR (365U)
#define YEAR_RANGE_START (1970U)
#define YEAR_RANGE_END (2099U)
/*******************************************************************************
* Prototypes
******************************************************************************/
/*!
* @brief Checks whether the date and time passed in is valid
*
* @param datetime Pointer to structure where the date and time details are stored
*
* @return Returns false if the date & time details are out of range; true if in range
*/
static bool RTC_CheckDatetimeFormat(const rtc_datetime_t *datetime);
/*!
* @brief Converts time data from datetime to seconds
*
* @param datetime Pointer to datetime structure where the date and time details are stored
*
* @return The result of the conversion in seconds
*/
static uint32_t RTC_ConvertDatetimeToSeconds(const rtc_datetime_t *datetime);
/*!
* @brief Converts time data from seconds to a datetime structure
*
* @param seconds Seconds value that needs to be converted to datetime format
* @param datetime Pointer to the datetime structure where the result of the conversion is stored
*/
static void RTC_ConvertSecondsToDatetime(uint32_t seconds, rtc_datetime_t *datetime);
/*******************************************************************************
* Code
******************************************************************************/
static bool RTC_CheckDatetimeFormat(const rtc_datetime_t *datetime)
{
assert(datetime);
/* Table of days in a month for a non leap year. First entry in the table is not used,
* valid months start from 1
*/
uint8_t daysPerMonth[] = {0U, 31U, 28U, 31U, 30U, 31U, 30U, 31U, 31U, 30U, 31U, 30U, 31U};
/* Check year, month, hour, minute, seconds */
if ((datetime->year < YEAR_RANGE_START) || (datetime->year > YEAR_RANGE_END) || (datetime->month > 12U) ||
(datetime->month < 1U) || (datetime->hour >= 24U) || (datetime->minute >= 60U) || (datetime->second >= 60U))
{
/* If not correct then error*/
return false;
}
/* Adjust the days in February for a leap year */
if ((((datetime->year & 3U) == 0) && (datetime->year % 100 != 0)) || (datetime->year % 400 == 0))
{
daysPerMonth[2] = 29U;
}
/* Check the validity of the day */
if ((datetime->day > daysPerMonth[datetime->month]) || (datetime->day < 1U))
{
return false;
}
return true;
}
static uint32_t RTC_ConvertDatetimeToSeconds(const rtc_datetime_t *datetime)
{
assert(datetime);
/* Number of days from begin of the non Leap-year*/
/* Number of days from begin of the non Leap-year*/
uint16_t monthDays[] = {0U, 0U, 31U, 59U, 90U, 120U, 151U, 181U, 212U, 243U, 273U, 304U, 334U};
uint32_t seconds;
/* Compute number of days from 1970 till given year*/
seconds = (datetime->year - 1970U) * DAYS_IN_A_YEAR;
/* Add leap year days */
seconds += ((datetime->year / 4) - (1970U / 4));
/* Add number of days till given month*/
seconds += monthDays[datetime->month];
/* Add days in given month. We subtract the current day as it is
* represented in the hours, minutes and seconds field*/
seconds += (datetime->day - 1);
/* For leap year if month less than or equal to Febraury, decrement day counter*/
if ((!(datetime->year & 3U)) && (datetime->month <= 2U))
{
seconds--;
}
seconds = (seconds * SECONDS_IN_A_DAY) + (datetime->hour * SECONDS_IN_A_HOUR) +
(datetime->minute * SECONDS_IN_A_MINUTE) + datetime->second;
return seconds;
}
static void RTC_ConvertSecondsToDatetime(uint32_t seconds, rtc_datetime_t *datetime)
{
assert(datetime);
uint32_t x;
uint32_t secondsRemaining, days;
uint16_t daysInYear;
/* Table of days in a month for a non leap year. First entry in the table is not used,
* valid months start from 1
*/
uint8_t daysPerMonth[] = {0U, 31U, 28U, 31U, 30U, 31U, 30U, 31U, 31U, 30U, 31U, 30U, 31U};
/* Start with the seconds value that is passed in to be converted to date time format */
secondsRemaining = seconds;
/* Calcuate the number of days, we add 1 for the current day which is represented in the
* hours and seconds field
*/
days = secondsRemaining / SECONDS_IN_A_DAY + 1;
/* Update seconds left*/
secondsRemaining = secondsRemaining % SECONDS_IN_A_DAY;
/* Calculate the datetime hour, minute and second fields */
datetime->hour = secondsRemaining / SECONDS_IN_A_HOUR;
secondsRemaining = secondsRemaining % SECONDS_IN_A_HOUR;
datetime->minute = secondsRemaining / 60U;
datetime->second = secondsRemaining % SECONDS_IN_A_MINUTE;
/* Calculate year */
daysInYear = DAYS_IN_A_YEAR;
datetime->year = YEAR_RANGE_START;
while (days > daysInYear)
{
/* Decrease day count by a year and increment year by 1 */
days -= daysInYear;
datetime->year++;
/* Adjust the number of days for a leap year */
if (datetime->year & 3U)
{
daysInYear = DAYS_IN_A_YEAR;
}
else
{
daysInYear = DAYS_IN_A_YEAR + 1;
}
}
/* Adjust the days in February for a leap year */
if (!(datetime->year & 3U))
{
daysPerMonth[2] = 29U;
}
for (x = 1U; x <= 12U; x++)
{
if (days <= daysPerMonth[x])
{
datetime->month = x;
break;
}
else
{
days -= daysPerMonth[x];
}
}
datetime->day = days;
}
void RTC_Init(RTC_Type *base, const rtc_config_t *config)
{
assert(config);
uint32_t reg;
#if defined(RTC_CLOCKS)
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
CLOCK_EnableClock(kCLOCK_Rtc0);
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
#endif /* RTC_CLOCKS */
/* Issue a software reset if timer is invalid */
if (RTC_GetStatusFlags(RTC) & kRTC_TimeInvalidFlag)
{
RTC_Reset(RTC);
}
reg = base->CR;
/* Setup the update mode and supervisor access mode */
reg &= ~(RTC_CR_UM_MASK | RTC_CR_SUP_MASK);
reg |= RTC_CR_UM(config->updateMode) | RTC_CR_SUP(config->supervisorAccess);
#if defined(FSL_FEATURE_RTC_HAS_WAKEUP_PIN_SELECTION) && FSL_FEATURE_RTC_HAS_WAKEUP_PIN_SELECTION
/* Setup the wakeup pin select */
reg &= ~(RTC_CR_WPS_MASK);
reg |= RTC_CR_WPS(config->wakeupSelect);
#endif /* FSL_FEATURE_RTC_HAS_WAKEUP_PIN */
base->CR = reg;
/* Configure the RTC time compensation register */
base->TCR = (RTC_TCR_CIR(config->compensationInterval) | RTC_TCR_TCR(config->compensationTime));
#if defined(FSL_FEATURE_RTC_HAS_TSIC) && FSL_FEATURE_RTC_HAS_TSIC
/* Configure RTC timer seconds interrupt to be generated once per second */
base->IER &= ~(RTC_IER_TSIC_MASK | RTC_IER_TSIE_MASK);
#endif
}
void RTC_GetDefaultConfig(rtc_config_t *config)
{
assert(config);
/* Wakeup pin will assert if the RTC interrupt asserts or if the wakeup pin is turned on */
config->wakeupSelect = false;
/* Registers cannot be written when locked */
config->updateMode = false;
/* Non-supervisor mode write accesses are not supported and will generate a bus error */
config->supervisorAccess = false;
/* Compensation interval used by the crystal compensation logic */
config->compensationInterval = 0;
/* Compensation time used by the crystal compensation logic */
config->compensationTime = 0;
}
status_t RTC_SetDatetime(RTC_Type *base, const rtc_datetime_t *datetime)
{
assert(datetime);
/* Return error if the time provided is not valid */
if (!(RTC_CheckDatetimeFormat(datetime)))
{
return kStatus_InvalidArgument;
}
/* Set time in seconds */
base->TSR = RTC_ConvertDatetimeToSeconds(datetime);
return kStatus_Success;
}
void RTC_GetDatetime(RTC_Type *base, rtc_datetime_t *datetime)
{
assert(datetime);
uint32_t seconds = 0;
seconds = base->TSR;
RTC_ConvertSecondsToDatetime(seconds, datetime);
}
status_t RTC_SetAlarm(RTC_Type *base, const rtc_datetime_t *alarmTime)
{
assert(alarmTime);
uint32_t alarmSeconds = 0;
uint32_t currSeconds = 0;
/* Return error if the alarm time provided is not valid */
if (!(RTC_CheckDatetimeFormat(alarmTime)))
{
return kStatus_InvalidArgument;
}
alarmSeconds = RTC_ConvertDatetimeToSeconds(alarmTime);
/* Get the current time */
currSeconds = base->TSR;
/* Return error if the alarm time has passed */
if (alarmSeconds < currSeconds)
{
return kStatus_Fail;
}
/* Set alarm in seconds*/
base->TAR = alarmSeconds;
return kStatus_Success;
}
void RTC_GetAlarm(RTC_Type *base, rtc_datetime_t *datetime)
{
assert(datetime);
uint32_t alarmSeconds = 0;
/* Get alarm in seconds */
alarmSeconds = base->TAR;
RTC_ConvertSecondsToDatetime(alarmSeconds, datetime);
}
void RTC_EnableInterrupts(RTC_Type *base, uint32_t mask)
{
uint32_t tmp32 = 0U;
/* RTC_IER */
if (kRTC_TimeInvalidInterruptEnable == (kRTC_TimeInvalidInterruptEnable & mask))
{
tmp32 |= RTC_IER_TIIE_MASK;
}
if (kRTC_TimeOverflowInterruptEnable == (kRTC_TimeOverflowInterruptEnable & mask))
{
tmp32 |= RTC_IER_TOIE_MASK;
}
if (kRTC_AlarmInterruptEnable == (kRTC_AlarmInterruptEnable & mask))
{
tmp32 |= RTC_IER_TAIE_MASK;
}
if (kRTC_SecondsInterruptEnable == (kRTC_SecondsInterruptEnable & mask))
{
tmp32 |= RTC_IER_TSIE_MASK;
}
#if defined(FSL_FEATURE_RTC_HAS_MONOTONIC) && (FSL_FEATURE_RTC_HAS_MONOTONIC)
if (kRTC_MonotonicOverflowInterruptEnable == (kRTC_MonotonicOverflowInterruptEnable & mask))
{
tmp32 |= RTC_IER_MOIE_MASK;
}
#endif /* FSL_FEATURE_RTC_HAS_MONOTONIC */
base->IER |= tmp32;
#if (defined(FSL_FEATURE_RTC_HAS_TIR) && FSL_FEATURE_RTC_HAS_TIR)
tmp32 = 0U;
/* RTC_TIR */
if (kRTC_TestModeInterruptEnable == (kRTC_TestModeInterruptEnable & mask))
{
tmp32 |= RTC_TIR_TMIE_MASK;
}
if (kRTC_FlashSecurityInterruptEnable == (kRTC_FlashSecurityInterruptEnable & mask))
{
tmp32 |= RTC_TIR_FSIE_MASK;
}
#if (defined(FSL_FEATURE_RTC_HAS_TIR_TPIE) && FSL_FEATURE_RTC_HAS_TIR_TPIE)
if (kRTC_TamperPinInterruptEnable == (kRTC_TamperPinInterruptEnable & mask))
{
tmp32 |= RTC_TIR_TPIE_MASK;
}
#endif /* FSL_FEATURE_RTC_HAS_TIR_TPIE */
#if (defined(FSL_FEATURE_RTC_HAS_TIR_SIE) && FSL_FEATURE_RTC_HAS_TIR_SIE)
if (kRTC_SecurityModuleInterruptEnable == (kRTC_SecurityModuleInterruptEnable & mask))
{
tmp32 |= RTC_TIR_SIE_MASK;
}
#endif /* FSL_FEATURE_RTC_HAS_TIR_SIE */
#if (defined(FSL_FEATURE_RTC_HAS_TIR_LCIE) && FSL_FEATURE_RTC_HAS_TIR_LCIE)
if (kRTC_LossOfClockInterruptEnable == (kRTC_LossOfClockInterruptEnable & mask))
{
tmp32 |= RTC_TIR_LCIE_MASK;
}
#endif /* FSL_FEATURE_RTC_HAS_TIR_LCIE */
base->TIR |= tmp32;
#endif /* FSL_FEATURE_RTC_HAS_TIR */
}
void RTC_DisableInterrupts(RTC_Type *base, uint32_t mask)
{
uint32_t tmp32 = 0U;
/* RTC_IER */
if (kRTC_TimeInvalidInterruptEnable == (kRTC_TimeInvalidInterruptEnable & mask))
{
tmp32 |= RTC_IER_TIIE_MASK;
}
if (kRTC_TimeOverflowInterruptEnable == (kRTC_TimeOverflowInterruptEnable & mask))
{
tmp32 |= RTC_IER_TOIE_MASK;
}
if (kRTC_AlarmInterruptEnable == (kRTC_AlarmInterruptEnable & mask))
{
tmp32 |= RTC_IER_TAIE_MASK;
}
if (kRTC_SecondsInterruptEnable == (kRTC_SecondsInterruptEnable & mask))
{
tmp32 |= RTC_IER_TSIE_MASK;
}
#if defined(FSL_FEATURE_RTC_HAS_MONOTONIC) && (FSL_FEATURE_RTC_HAS_MONOTONIC)
if (kRTC_MonotonicOverflowInterruptEnable == (kRTC_MonotonicOverflowInterruptEnable & mask))
{
tmp32 |= RTC_IER_MOIE_MASK;
}
#endif /* FSL_FEATURE_RTC_HAS_MONOTONIC */
base->IER &= (uint32_t)(~tmp32);
#if (defined(FSL_FEATURE_RTC_HAS_TIR) && FSL_FEATURE_RTC_HAS_TIR)
tmp32 = 0U;
/* RTC_TIR */
if (kRTC_TestModeInterruptEnable == (kRTC_TestModeInterruptEnable & mask))
{
tmp32 |= RTC_TIR_TMIE_MASK;
}
if (kRTC_FlashSecurityInterruptEnable == (kRTC_FlashSecurityInterruptEnable & mask))
{
tmp32 |= RTC_TIR_FSIE_MASK;
}
#if (defined(FSL_FEATURE_RTC_HAS_TIR_TPIE) && FSL_FEATURE_RTC_HAS_TIR_TPIE)
if (kRTC_TamperPinInterruptEnable == (kRTC_TamperPinInterruptEnable & mask))
{
tmp32 |= RTC_TIR_TPIE_MASK;
}
#endif /* FSL_FEATURE_RTC_HAS_TIR_TPIE */
#if (defined(FSL_FEATURE_RTC_HAS_TIR_SIE) && FSL_FEATURE_RTC_HAS_TIR_SIE)
if (kRTC_SecurityModuleInterruptEnable == (kRTC_SecurityModuleInterruptEnable & mask))
{
tmp32 |= RTC_TIR_SIE_MASK;
}
#endif /* FSL_FEATURE_RTC_HAS_TIR_SIE */
#if (defined(FSL_FEATURE_RTC_HAS_TIR_LCIE) && FSL_FEATURE_RTC_HAS_TIR_LCIE)
if (kRTC_LossOfClockInterruptEnable == (kRTC_LossOfClockInterruptEnable & mask))
{
tmp32 |= RTC_TIR_LCIE_MASK;
}
#endif /* FSL_FEATURE_RTC_HAS_TIR_LCIE */
base->TIR &= (uint32_t)(~tmp32);
#endif /* FSL_FEATURE_RTC_HAS_TIR */
}
uint32_t RTC_GetEnabledInterrupts(RTC_Type *base)
{
uint32_t tmp32 = 0U;
/* RTC_IER */
if (RTC_IER_TIIE_MASK == (RTC_IER_TIIE_MASK & base->IER))
{
tmp32 |= kRTC_TimeInvalidInterruptEnable;
}
if (RTC_IER_TOIE_MASK == (RTC_IER_TOIE_MASK & base->IER))
{
tmp32 |= kRTC_TimeOverflowInterruptEnable;
}
if (RTC_IER_TAIE_MASK == (RTC_IER_TAIE_MASK & base->IER))
{
tmp32 |= kRTC_AlarmInterruptEnable;
}
if (RTC_IER_TSIE_MASK == (RTC_IER_TSIE_MASK & base->IER))
{
tmp32 |= kRTC_SecondsInterruptEnable;
}
#if defined(FSL_FEATURE_RTC_HAS_MONOTONIC) && (FSL_FEATURE_RTC_HAS_MONOTONIC)
if (RTC_IER_MOIE_MASK == (RTC_IER_MOIE_MASK & base->IER))
{
tmp32 |= kRTC_MonotonicOverflowInterruptEnable;
}
#endif /* FSL_FEATURE_RTC_HAS_MONOTONIC */
#if (defined(FSL_FEATURE_RTC_HAS_TIR) && FSL_FEATURE_RTC_HAS_TIR)
/* RTC_TIR */
if (RTC_TIR_TMIE_MASK == (RTC_TIR_TMIE_MASK & base->TIR))
{
tmp32 |= kRTC_TestModeInterruptEnable;
}
if (RTC_TIR_FSIE_MASK == (RTC_TIR_FSIE_MASK & base->TIR))
{
tmp32 |= kRTC_FlashSecurityInterruptEnable;
}
#if (defined(FSL_FEATURE_RTC_HAS_TIR_TPIE) && FSL_FEATURE_RTC_HAS_TIR_TPIE)
if (RTC_TIR_TPIE_MASK == (RTC_TIR_TPIE_MASK & base->TIR))
{
tmp32 |= kRTC_TamperPinInterruptEnable;
}
#endif /* FSL_FEATURE_RTC_HAS_TIR_TPIE */
#if (defined(FSL_FEATURE_RTC_HAS_TIR_SIE) && FSL_FEATURE_RTC_HAS_TIR_SIE)
if (RTC_TIR_SIE_MASK == (RTC_TIR_SIE_MASK & base->TIR))
{
tmp32 |= kRTC_SecurityModuleInterruptEnable;
}
#endif /* FSL_FEATURE_RTC_HAS_TIR_SIE */
#if (defined(FSL_FEATURE_RTC_HAS_TIR_LCIE) && FSL_FEATURE_RTC_HAS_TIR_LCIE)
if (RTC_TIR_LCIE_MASK == (RTC_TIR_LCIE_MASK & base->TIR))
{
tmp32 |= kRTC_LossOfClockInterruptEnable;
}
#endif /* FSL_FEATURE_RTC_HAS_TIR_LCIE */
#endif /* FSL_FEATURE_RTC_HAS_TIR */
return tmp32;
}
uint32_t RTC_GetStatusFlags(RTC_Type *base)
{
uint32_t tmp32 = 0U;
/* RTC_SR */
if (RTC_SR_TIF_MASK == (RTC_SR_TIF_MASK & base->SR))
{
tmp32 |= kRTC_TimeInvalidFlag;
}
if (RTC_SR_TOF_MASK == (RTC_SR_TOF_MASK & base->SR))
{
tmp32 |= kRTC_TimeOverflowFlag;
}
if (RTC_SR_TAF_MASK == (RTC_SR_TAF_MASK & base->SR))
{
tmp32 |= kRTC_AlarmFlag;
}
#if defined(FSL_FEATURE_RTC_HAS_MONOTONIC) && (FSL_FEATURE_RTC_HAS_MONOTONIC)
if (RTC_SR_MOF_MASK == (RTC_SR_MOF_MASK & base->SR))
{
tmp32 |= kRTC_MonotonicOverflowFlag;
}
#endif /* FSL_FEATURE_RTC_HAS_MONOTONIC */
#if (defined(FSL_FEATURE_RTC_HAS_SR_TIDF) && FSL_FEATURE_RTC_HAS_SR_TIDF)
if (RTC_SR_TIDF_MASK == (RTC_SR_TIDF_MASK & base->SR))
{
tmp32 |= kRTC_TamperInterruptDetectFlag;
}
#endif /* FSL_FEATURE_RTC_HAS_SR_TIDF */
#if (defined(FSL_FEATURE_RTC_HAS_TDR) && FSL_FEATURE_RTC_HAS_TDR)
/* RTC_TDR */
if (RTC_TDR_TMF_MASK == (RTC_TDR_TMF_MASK & base->TDR))
{
tmp32 |= kRTC_TestModeFlag;
}
if (RTC_TDR_FSF_MASK == (RTC_TDR_FSF_MASK & base->TDR))
{
tmp32 |= kRTC_FlashSecurityFlag;
}
#if (defined(FSL_FEATURE_RTC_HAS_TDR_TPF) && FSL_FEATURE_RTC_HAS_TDR_TPF)
if (RTC_TDR_TPF_MASK == (RTC_TDR_TPF_MASK & base->TDR))
{
tmp32 |= kRTC_TamperPinFlag;
}
#endif /* FSL_FEATURE_RTC_HAS_TDR_TPF */
#if (defined(FSL_FEATURE_RTC_HAS_TDR_STF) && FSL_FEATURE_RTC_HAS_TDR_STF)
if (RTC_TDR_STF_MASK == (RTC_TDR_STF_MASK & base->TDR))
{
tmp32 |= kRTC_SecurityTamperFlag;
}
#endif /* FSL_FEATURE_RTC_HAS_TDR_STF */
#if (defined(FSL_FEATURE_RTC_HAS_TDR_LCTF) && FSL_FEATURE_RTC_HAS_TDR_LCTF)
if (RTC_TDR_LCTF_MASK == (RTC_TDR_LCTF_MASK & base->TDR))
{
tmp32 |= kRTC_LossOfClockTamperFlag;
}
#endif /* FSL_FEATURE_RTC_HAS_TDR_LCTF */
#endif /* FSL_FEATURE_RTC_HAS_TDR */
return tmp32;
}
void RTC_ClearStatusFlags(RTC_Type *base, uint32_t mask)
{
/* The alarm flag is cleared by writing to the TAR register */
if (mask & kRTC_AlarmFlag)
{
base->TAR = 0U;
}
/* The timer overflow flag is cleared by initializing the TSR register.
* The time counter should be disabled for this write to be successful
*/
if (mask & kRTC_TimeOverflowFlag)
{
base->TSR = 1U;
}
/* The timer overflow flag is cleared by initializing the TSR register.
* The time counter should be disabled for this write to be successful
*/
if (mask & kRTC_TimeInvalidFlag)
{
base->TSR = 1U;
}
#if (defined(FSL_FEATURE_RTC_HAS_TDR) && FSL_FEATURE_RTC_HAS_TDR)
/* To clear, write logic one to this flag after exiting from all test modes */
if (kRTC_TestModeFlag == (kRTC_TestModeFlag & mask))
{
base->TDR = RTC_TDR_TMF_MASK;
}
/* To clear, write logic one to this flag after flash security is enabled */
if (kRTC_FlashSecurityFlag == (kRTC_FlashSecurityFlag & mask))
{
base->TDR = RTC_TDR_FSF_MASK;
}
#if (defined(FSL_FEATURE_RTC_HAS_TDR_TPF) && FSL_FEATURE_RTC_HAS_TDR_TPF)
/* To clear, write logic one to the corresponding flag after that tamper pin negates */
if (kRTC_TamperPinFlag == (kRTC_TamperPinFlag & mask))
{
base->TDR = RTC_TDR_TPF_MASK;
}
#endif /* FSL_FEATURE_RTC_HAS_TDR_TPF */
#if (defined(FSL_FEATURE_RTC_HAS_TDR_STF) && FSL_FEATURE_RTC_HAS_TDR_STF)
/* To clear, write logic one to this flag after security module has negated its tamper detect */
if (kRTC_SecurityTamperFlag == (kRTC_SecurityTamperFlag & mask))
{
base->TDR = RTC_TDR_STF_MASK;
}
#endif /* FSL_FEATURE_RTC_HAS_TDR_STF */
#if (defined(FSL_FEATURE_RTC_HAS_TDR_LCTF) && FSL_FEATURE_RTC_HAS_TDR_LCTF)
/* To clear, write logic one to this flag after loss of clock negates */
if (kRTC_LossOfClockTamperFlag == (kRTC_LossOfClockTamperFlag & mask))
{
base->TDR = RTC_TDR_LCTF_MASK;
}
#endif /* FSL_FEATURE_RTC_HAS_TDR_LCTF */
#endif /* FSL_FEATURE_RTC_HAS_TDR */
}
#if defined(FSL_FEATURE_RTC_HAS_MONOTONIC) && (FSL_FEATURE_RTC_HAS_MONOTONIC)
void RTC_GetMonotonicCounter(RTC_Type *base, uint64_t *counter)
{
assert(counter);
*counter = (((uint64_t)base->MCHR << 32) | ((uint64_t)base->MCLR));
}
void RTC_SetMonotonicCounter(RTC_Type *base, uint64_t counter)
{
/* Prepare to initialize the register with the new value written */
base->MER &= ~RTC_MER_MCE_MASK;
base->MCHR = (uint32_t)((counter) >> 32);
base->MCLR = (uint32_t)(counter);
}
status_t RTC_IncrementMonotonicCounter(RTC_Type *base)
{
if (base->SR & (RTC_SR_MOF_MASK | RTC_SR_TIF_MASK))
{
return kStatus_Fail;
}
/* Prepare to switch to increment mode */
base->MER |= RTC_MER_MCE_MASK;
/* Write anything so the counter increments*/
base->MCLR = 1U;
return kStatus_Success;
}
#endif /* FSL_FEATURE_RTC_HAS_MONOTONIC */

View File

@ -0,0 +1,465 @@
/*
* Copyright (c) 2015, Freescale Semiconductor, Inc.
* Copyright 2016-2017 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef _FSL_RTC_H_
#define _FSL_RTC_H_
#include "fsl_common.h"
/*!
* @addtogroup rtc
* @{
*/
/*******************************************************************************
* Definitions
******************************************************************************/
/*! @name Driver version */
/*@{*/
#define FSL_RTC_DRIVER_VERSION (MAKE_VERSION(2, 0, 0)) /*!< Version 2.0.0 */
/*@}*/
/*! @brief List of RTC interrupts */
typedef enum _rtc_interrupt_enable
{
kRTC_TimeInvalidInterruptEnable = (1U << 0U), /*!< Time invalid interrupt.*/
kRTC_TimeOverflowInterruptEnable = (1U << 1U), /*!< Time overflow interrupt.*/
kRTC_AlarmInterruptEnable = (1U << 2U), /*!< Alarm interrupt.*/
kRTC_SecondsInterruptEnable = (1U << 3U), /*!< Seconds interrupt.*/
#if defined(FSL_FEATURE_RTC_HAS_MONOTONIC) && (FSL_FEATURE_RTC_HAS_MONOTONIC)
kRTC_MonotonicOverflowInterruptEnable = (1U << 4U), /*!< Monotonic Overflow Interrupt Enable */
#endif /* FSL_FEATURE_RTC_HAS_MONOTONIC */
#if (defined(FSL_FEATURE_RTC_HAS_TIR) && FSL_FEATURE_RTC_HAS_TIR)
kRTC_TestModeInterruptEnable = (1U << 5U), /* test mode interrupt */
kRTC_FlashSecurityInterruptEnable = (1U << 6U), /* flash security interrupt */
#if (defined(FSL_FEATURE_RTC_HAS_TIR_TPIE) && FSL_FEATURE_RTC_HAS_TIR_TPIE)
kRTC_TamperPinInterruptEnable = (1U << 7U), /* Tamper pin interrupt */
#endif /* FSL_FEATURE_RTC_HAS_TIR_TPIE */
#if (defined(FSL_FEATURE_RTC_HAS_TIR_SIE) && FSL_FEATURE_RTC_HAS_TIR_SIE)
kRTC_SecurityModuleInterruptEnable = (1U << 8U), /* security module interrupt */
#endif /* FSL_FEATURE_RTC_HAS_TIR_SIE */
#if (defined(FSL_FEATURE_RTC_HAS_TIR_LCIE) && FSL_FEATURE_RTC_HAS_TIR_LCIE)
kRTC_LossOfClockInterruptEnable = (1U << 9U), /* loss of clock interrupt */
#endif /* FSL_FEATURE_RTC_HAS_TIR_LCIE */
#endif /* FSL_FEATURE_RTC_HAS_TIR */
} rtc_interrupt_enable_t;
/*! @brief List of RTC flags */
typedef enum _rtc_status_flags
{
kRTC_TimeInvalidFlag = (1U << 0U), /*!< Time invalid flag */
kRTC_TimeOverflowFlag = (1U << 1U), /*!< Time overflow flag */
kRTC_AlarmFlag = (1U << 2U), /*!< Alarm flag*/
#if defined(FSL_FEATURE_RTC_HAS_MONOTONIC) && (FSL_FEATURE_RTC_HAS_MONOTONIC)
kRTC_MonotonicOverflowFlag = (1U << 3U), /*!< Monotonic Overflow Flag */
#endif /* FSL_FEATURE_RTC_HAS_MONOTONIC */
#if (defined(FSL_FEATURE_RTC_HAS_SR_TIDF) && FSL_FEATURE_RTC_HAS_SR_TIDF)
kRTC_TamperInterruptDetectFlag = (1U << 4U), /*!< Tamper interrupt detect flag */
#endif /* FSL_FEATURE_RTC_HAS_SR_TIDF */
#if (defined(FSL_FEATURE_RTC_HAS_TDR) && FSL_FEATURE_RTC_HAS_TDR)
kRTC_TestModeFlag = (1U << 5U), /* Test mode flag */
kRTC_FlashSecurityFlag = (1U << 6U), /* Flash security flag */
#if (defined(FSL_FEATURE_RTC_HAS_TDR_TPF) && FSL_FEATURE_RTC_HAS_TDR_TPF)
kRTC_TamperPinFlag = (1U << 7U), /* Tamper pin flag */
#endif /* FSL_FEATURE_RTC_HAS_TDR_TPF */
#if (defined(FSL_FEATURE_RTC_HAS_TDR_STF) && FSL_FEATURE_RTC_HAS_TDR_STF)
kRTC_SecurityTamperFlag = (1U << 8U), /* Security tamper flag */
#endif /* FSL_FEATURE_RTC_HAS_TDR_STF */
#if (defined(FSL_FEATURE_RTC_HAS_TDR_LCTF) && FSL_FEATURE_RTC_HAS_TDR_LCTF)
kRTC_LossOfClockTamperFlag = (1U << 9U), /* Loss of clock flag */
#endif /* FSL_FEATURE_RTC_HAS_TDR_LCTF */
#endif /* FSL_FEATURE_RTC_HAS_TDR */
} rtc_status_flags_t;
#if (defined(FSL_FEATURE_RTC_HAS_OSC_SCXP) && FSL_FEATURE_RTC_HAS_OSC_SCXP)
/*! @brief List of RTC Oscillator capacitor load settings */
typedef enum _rtc_osc_cap_load
{
kRTC_Capacitor_2p = RTC_CR_SC2P_MASK, /*!< 2 pF capacitor load */
kRTC_Capacitor_4p = RTC_CR_SC4P_MASK, /*!< 4 pF capacitor load */
kRTC_Capacitor_8p = RTC_CR_SC8P_MASK, /*!< 8 pF capacitor load */
kRTC_Capacitor_16p = RTC_CR_SC16P_MASK /*!< 16 pF capacitor load */
} rtc_osc_cap_load_t;
#endif /* FSL_FEATURE_SCG_HAS_OSC_SCXP */
/*! @brief Structure is used to hold the date and time */
typedef struct _rtc_datetime
{
uint16_t year; /*!< Range from 1970 to 2099.*/
uint8_t month; /*!< Range from 1 to 12.*/
uint8_t day; /*!< Range from 1 to 31 (depending on month).*/
uint8_t hour; /*!< Range from 0 to 23.*/
uint8_t minute; /*!< Range from 0 to 59.*/
uint8_t second; /*!< Range from 0 to 59.*/
} rtc_datetime_t;
#if (defined(FSL_FEATURE_RTC_HAS_PCR) && FSL_FEATURE_RTC_HAS_PCR)
/*!
* @brief RTC pin config structure
*/
typedef struct _rtc_pin_config
{
bool inputLogic; /*!< true: Tamper pin input data is logic one.
false: Tamper pin input data is logic zero. */
bool pinActiveLow; /*!< true: Tamper pin is active low.
false: Tamper pin is active high. */
bool filterEnable; /*!< true: Input filter is enabled on the tamper pin.
false: Input filter is disabled on the tamper pin. */
bool pullSelectNegate; /*!< true: Tamper pin pull resistor direction will negate the tamper pin.
false: Tamper pin pull resistor direction will assert the tamper pin. */
bool pullEnable; /*!< true: Pull resistor is enabled on tamper pin.
false: Pull resistor is disabled on tamper pin. */
} rtc_pin_config_t;
#endif /* FSL_FEATURE_RTC_HAS_PCR */
/*!
* @brief RTC config structure
*
* This structure holds the configuration settings for the RTC peripheral. To initialize this
* structure to reasonable defaults, call the RTC_GetDefaultConfig() function and pass a
* pointer to your config structure instance.
*
* The config struct can be made const so it resides in flash
*/
typedef struct _rtc_config
{
bool wakeupSelect; /*!< true: Wakeup pin outputs the 32 KHz clock;
false:Wakeup pin used to wakeup the chip */
bool updateMode; /*!< true: Registers can be written even when locked under certain
conditions, false: No writes allowed when registers are locked */
bool supervisorAccess; /*!< true: Non-supervisor accesses are allowed;
false: Non-supervisor accesses are not supported */
uint32_t compensationInterval; /*!< Compensation interval that is written to the CIR field in RTC TCR Register */
uint32_t compensationTime; /*!< Compensation time that is written to the TCR field in RTC TCR Register */
} rtc_config_t;
/*******************************************************************************
* API
******************************************************************************/
#if defined(__cplusplus)
extern "C" {
#endif
/*!
* @name Initialization and deinitialization
* @{
*/
/*!
* @brief Ungates the RTC clock and configures the peripheral for basic operation.
*
* This function issues a software reset if the timer invalid flag is set.
*
* @note This API should be called at the beginning of the application using the RTC driver.
*
* @param base RTC peripheral base address
* @param config Pointer to the user's RTC configuration structure.
*/
void RTC_Init(RTC_Type *base, const rtc_config_t *config);
/*!
* @brief Stops the timer and gate the RTC clock.
*
* @param base RTC peripheral base address
*/
static inline void RTC_Deinit(RTC_Type *base)
{
/* Stop the RTC timer */
base->SR &= ~RTC_SR_TCE_MASK;
#if defined(RTC_CLOCKS)
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
/* Gate the module clock */
CLOCK_DisableClock(kCLOCK_Rtc0);
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
#endif /* RTC_CLOCKS */
}
/*!
* @brief Fills in the RTC config struct with the default settings.
*
* The default values are as follows.
* @code
* config->wakeupSelect = false;
* config->updateMode = false;
* config->supervisorAccess = false;
* config->compensationInterval = 0;
* config->compensationTime = 0;
* @endcode
* @param config Pointer to the user's RTC configuration structure.
*/
void RTC_GetDefaultConfig(rtc_config_t *config);
/*! @}*/
/*!
* @name Current Time & Alarm
* @{
*/
/*!
* @brief Sets the RTC date and time according to the given time structure.
*
* The RTC counter must be stopped prior to calling this function because writes to the RTC
* seconds register fail if the RTC counter is running.
*
* @param base RTC peripheral base address
* @param datetime Pointer to the structure where the date and time details are stored.
*
* @return kStatus_Success: Success in setting the time and starting the RTC
* kStatus_InvalidArgument: Error because the datetime format is incorrect
*/
status_t RTC_SetDatetime(RTC_Type *base, const rtc_datetime_t *datetime);
/*!
* @brief Gets the RTC time and stores it in the given time structure.
*
* @param base RTC peripheral base address
* @param datetime Pointer to the structure where the date and time details are stored.
*/
void RTC_GetDatetime(RTC_Type *base, rtc_datetime_t *datetime);
/*!
* @brief Sets the RTC alarm time.
*
* The function checks whether the specified alarm time is greater than the present
* time. If not, the function does not set the alarm and returns an error.
*
* @param base RTC peripheral base address
* @param alarmTime Pointer to the structure where the alarm time is stored.
*
* @return kStatus_Success: success in setting the RTC alarm
* kStatus_InvalidArgument: Error because the alarm datetime format is incorrect
* kStatus_Fail: Error because the alarm time has already passed
*/
status_t RTC_SetAlarm(RTC_Type *base, const rtc_datetime_t *alarmTime);
/*!
* @brief Returns the RTC alarm time.
*
* @param base RTC peripheral base address
* @param datetime Pointer to the structure where the alarm date and time details are stored.
*/
void RTC_GetAlarm(RTC_Type *base, rtc_datetime_t *datetime);
/*! @}*/
/*!
* @name Interrupt Interface
* @{
*/
/*!
* @brief Enables the selected RTC interrupts.
*
* @param base RTC peripheral base address
* @param mask The interrupts to enable. This is a logical OR of members of the
* enumeration ::rtc_interrupt_enable_t
*/
void RTC_EnableInterrupts(RTC_Type *base, uint32_t mask);
/*!
* @brief Disables the selected RTC interrupts.
*
* @param base RTC peripheral base address
* @param mask The interrupts to enable. This is a logical OR of members of the
* enumeration ::rtc_interrupt_enable_t
*/
void RTC_DisableInterrupts(RTC_Type *base, uint32_t mask);
/*!
* @brief Gets the enabled RTC interrupts.
*
* @param base RTC peripheral base address
*
* @return The enabled interrupts. This is the logical OR of members of the
* enumeration ::rtc_interrupt_enable_t
*/
uint32_t RTC_GetEnabledInterrupts(RTC_Type *base);
/*! @}*/
/*!
* @name Status Interface
* @{
*/
/*!
* @brief Gets the RTC status flags.
*
* @param base RTC peripheral base address
*
* @return The status flags. This is the logical OR of members of the
* enumeration ::rtc_status_flags_t
*/
uint32_t RTC_GetStatusFlags(RTC_Type *base);
/*!
* @brief Clears the RTC status flags.
*
* @param base RTC peripheral base address
* @param mask The status flags to clear. This is a logical OR of members of the
* enumeration ::rtc_status_flags_t
*/
void RTC_ClearStatusFlags(RTC_Type *base, uint32_t mask);
/*! @}*/
/*!
* @brief Set RTC clock source.
*
* @param base RTC peripheral base address
*
* @note After setting this bit, wait the oscillator startup time before enabling
* the time counter to allow the 32.768 kHz clock time to stabilize.
*/
static inline void RTC_SetClockSource(RTC_Type *base)
{
/* Enable the RTC 32KHz oscillator */
base->CR |= RTC_CR_OSCE_MASK;
}
#if (defined(FSL_FEATURE_RTC_HAS_TTSR) && FSL_FEATURE_RTC_HAS_TTSR)
/*!
* @brief Get the RTC tamper time seconds.
*
* @param base RTC peripheral base address
*/
static inline uint32_t RTC_GetTamperTimeSeconds(RTC_Type *base)
{
return base->TTSR;
}
#endif /* FSL_FEATURE_RTC_HAS_TTSR */
/*!
* @name Timer Start and Stop
* @{
*/
/*!
* @brief Starts the RTC time counter.
*
* After calling this function, the timer counter increments once a second provided SR[TOF] or
* SR[TIF] are not set.
*
* @param base RTC peripheral base address
*/
static inline void RTC_StartTimer(RTC_Type *base)
{
base->SR |= RTC_SR_TCE_MASK;
}
/*!
* @brief Stops the RTC time counter.
*
* RTC's seconds register can be written to only when the timer is stopped.
*
* @param base RTC peripheral base address
*/
static inline void RTC_StopTimer(RTC_Type *base)
{
base->SR &= ~RTC_SR_TCE_MASK;
}
/*! @}*/
#if (defined(FSL_FEATURE_RTC_HAS_OSC_SCXP) && FSL_FEATURE_RTC_HAS_OSC_SCXP)
/*!
* @brief This function sets the specified capacitor configuration for the RTC oscillator.
*
* @param base RTC peripheral base address
* @param capLoad Oscillator loads to enable. This is a logical OR of members of the
* enumeration ::rtc_osc_cap_load_t
*/
static inline void RTC_SetOscCapLoad(RTC_Type *base, uint32_t capLoad)
{
uint32_t reg = base->CR;
reg &= ~(RTC_CR_SC2P_MASK | RTC_CR_SC4P_MASK | RTC_CR_SC8P_MASK | RTC_CR_SC16P_MASK);
reg |= capLoad;
base->CR = reg;
}
#endif /* FSL_FEATURE_SCG_HAS_OSC_SCXP */
/*!
* @brief Performs a software reset on the RTC module.
*
* This resets all RTC registers except for the SWR bit and the RTC_WAR and RTC_RAR
* registers. The SWR bit is cleared by software explicitly clearing it.
*
* @param base RTC peripheral base address
*/
static inline void RTC_Reset(RTC_Type *base)
{
base->CR |= RTC_CR_SWR_MASK;
base->CR &= ~RTC_CR_SWR_MASK;
/* Set TSR register to 0x1 to avoid the timer invalid (TIF) bit being set in the SR register */
base->TSR = 1U;
}
#if defined(FSL_FEATURE_RTC_HAS_MONOTONIC) && (FSL_FEATURE_RTC_HAS_MONOTONIC)
/*!
* @name Monotonic counter functions
* @{
*/
/*!
* @brief Reads the values of the Monotonic Counter High and Monotonic Counter Low and returns
* them as a single value.
*
* @param base RTC peripheral base address
* @param counter Pointer to variable where the value is stored.
*/
void RTC_GetMonotonicCounter(RTC_Type *base, uint64_t *counter);
/*!
* @brief Writes values Monotonic Counter High and Monotonic Counter Low by decomposing
* the given single value. The Monotonic Overflow Flag in RTC_SR is cleared due to the API.
*
* @param base RTC peripheral base address
* @param counter Counter value
*/
void RTC_SetMonotonicCounter(RTC_Type *base, uint64_t counter);
/*!
* @brief Increments the Monotonic Counter by one.
*
* Increments the Monotonic Counter (registers RTC_MCLR and RTC_MCHR accordingly) by setting
* the monotonic counter enable (MER[MCE]) and then writing to the RTC_MCLR register. A write to the
* monotonic counter low that causes it to overflow also increments the monotonic counter high.
*
* @param base RTC peripheral base address
*
* @return kStatus_Success: success
* kStatus_Fail: error occurred, either time invalid or monotonic overflow flag was found
*/
status_t RTC_IncrementMonotonicCounter(RTC_Type *base);
/*! @}*/
#endif /* FSL_FEATURE_RTC_HAS_MONOTONIC */
#if defined(__cplusplus)
}
#endif
/*! @}*/
#endif /* _FSL_RTC_H_ */

View File

@ -0,0 +1,134 @@
/*
* Copyright (c) 2015, Freescale Semiconductor, Inc.
* Copyright 2016-2017 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include "fsl_sema42.h"
/******************************************************************************
* Definitions
*****************************************************************************/
/* The first number write to RSTGDP when reset SEMA42 gate. */
#define SEMA42_GATE_RESET_PATTERN_1 (0xE2U)
/* The second number write to RSTGDP when reset SEMA42 gate. */
#define SEMA42_GATE_RESET_PATTERN_2 (0x1DU)
/*******************************************************************************
* Prototypes
******************************************************************************/
/*!
* @brief Get instance number for SEMA42 module.
*
* @param base SEMA42 peripheral base address.
*/
uint32_t SEMA42_GetInstance(SEMA42_Type *base);
/*******************************************************************************
* Variables
******************************************************************************/
/*! @brief Pointers to sema42 bases for each instance. */
static SEMA42_Type *const s_sema42Bases[] = SEMA42_BASE_PTRS;
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
/*! @brief Pointers to sema42 clocks for each instance. */
static const clock_ip_name_t s_sema42Clocks[] = SEMA42_CLOCKS;
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
/******************************************************************************
* CODE
*****************************************************************************/
uint32_t SEMA42_GetInstance(SEMA42_Type *base)
{
uint32_t instance;
/* Find the instance index from base address mappings. */
for (instance = 0; instance < ARRAY_SIZE(s_sema42Bases); instance++)
{
if (s_sema42Bases[instance] == base)
{
break;
}
}
assert(instance < ARRAY_SIZE(s_sema42Bases));
return instance;
}
void SEMA42_Init(SEMA42_Type *base)
{
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
CLOCK_EnableClock(s_sema42Clocks[SEMA42_GetInstance(base)]);
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
}
void SEMA42_Deinit(SEMA42_Type *base)
{
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
CLOCK_DisableClock(s_sema42Clocks[SEMA42_GetInstance(base)]);
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
}
status_t SEMA42_TryLock(SEMA42_Type *base, uint8_t gateNum, uint8_t procNum)
{
assert(gateNum < FSL_FEATURE_SEMA42_GATE_COUNT);
++procNum;
/* Try to lock. */
SEMA42_GATEn(base, gateNum) = procNum;
/* Check locked or not. */
if (procNum != SEMA42_GATEn(base, gateNum))
{
return kStatus_SEMA42_Busy;
}
return kStatus_Success;
}
void SEMA42_Lock(SEMA42_Type *base, uint8_t gateNum, uint8_t procNum)
{
assert(gateNum < FSL_FEATURE_SEMA42_GATE_COUNT);
++procNum;
while (procNum != SEMA42_GATEn(base, gateNum))
{
/* Wait for unlocked status. */
while (SEMA42_GATEn(base, gateNum))
{
}
/* Lock the gate. */
SEMA42_GATEn(base, gateNum) = procNum;
}
}
status_t SEMA42_ResetGate(SEMA42_Type *base, uint8_t gateNum)
{
/*
* Reset all gates if gateNum >= SEMA42_GATE_NUM_RESET_ALL
* Reset specific gate if gateNum < FSL_FEATURE_SEMA42_GATE_COUNT
*/
assert(!((gateNum < SEMA42_GATE_NUM_RESET_ALL) && (gateNum >= FSL_FEATURE_SEMA42_GATE_COUNT)));
/* Check whether some reset is ongoing. */
if (base->RSTGT_R & SEMA42_RSTGT_R_RSTGSM_MASK)
{
return kStatus_SEMA42_Reseting;
}
/* First step. */
base->RSTGT_W = SEMA42_RSTGT_W_RSTGDP(SEMA42_GATE_RESET_PATTERN_1);
/* Second step. */
base->RSTGT_W = SEMA42_RSTGT_W_RSTGDP(SEMA42_GATE_RESET_PATTERN_2) | SEMA42_RSTGT_W_RSTGTN(gateNum);
return kStatus_Success;
}

View File

@ -0,0 +1,212 @@
/*
* Copyright (c) 2015, Freescale Semiconductor, Inc.
* Copyright 2016-2017 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef _FSL_SEMA42_H_
#define _FSL_SEMA42_H_
#include "fsl_common.h"
/*!
* @addtogroup sema42
* @{
*/
/******************************************************************************
* Definitions
*****************************************************************************/
/*! @name Driver version */
/*@{*/
/*! @brief SEMA42 driver version */
#define FSL_SEMA42_DRIVER_VERSION (MAKE_VERSION(2, 0, 0))
/*@}*/
/*!
* @brief SEMA42 status return codes.
*/
enum _sema42_status
{
kStatus_SEMA42_Busy = MAKE_STATUS(kStatusGroup_SEMA42, 0), /*!< SEMA42 gate has been locked by other processor. */
kStatus_SEMA42_Reseting = MAKE_STATUS(kStatusGroup_SEMA42, 1) /*!< SEMA42 gate reseting is ongoing. */
};
/*!
* @brief SEMA42 gate lock status.
*/
typedef enum _sema42_gate_status
{
kSEMA42_Unlocked = 0U, /*!< The gate is unlocked. */
kSEMA42_LockedByProc0 = 1U, /*!< The gate is locked by processor 0. */
kSEMA42_LockedByProc1 = 2U, /*!< The gate is locked by processor 1. */
kSEMA42_LockedByProc2 = 3U, /*!< The gate is locked by processor 2. */
kSEMA42_LockedByProc3 = 4U, /*!< The gate is locked by processor 3. */
kSEMA42_LockedByProc4 = 5U, /*!< The gate is locked by processor 4. */
kSEMA42_LockedByProc5 = 6U, /*!< The gate is locked by processor 5. */
kSEMA42_LockedByProc6 = 7U, /*!< The gate is locked by processor 6. */
kSEMA42_LockedByProc7 = 8U, /*!< The gate is locked by processor 7. */
kSEMA42_LockedByProc8 = 9U, /*!< The gate is locked by processor 8. */
kSEMA42_LockedByProc9 = 10U, /*!< The gate is locked by processor 9. */
kSEMA42_LockedByProc10 = 11U, /*!< The gate is locked by processor 10. */
kSEMA42_LockedByProc11 = 12U, /*!< The gate is locked by processor 11. */
kSEMA42_LockedByProc12 = 13U, /*!< The gate is locked by processor 12. */
kSEMA42_LockedByProc13 = 14U, /*!< The gate is locked by processor 13. */
kSEMA42_LockedByProc14 = 15U /*!< The gate is locked by processor 14. */
} sema42_gate_status_t;
/*! @brief The number to reset all SEMA42 gates. */
#define SEMA42_GATE_NUM_RESET_ALL (64U)
/*! @brief SEMA42 gate n register address.
*
* The SEMA42 gates are sorted in the order 3, 2, 1, 0, 7, 6, 5, 4, ... not in the order
* 0, 1, 2, 3, 4, 5, 6, 7, ... The macro SEMA42_GATEn gets the SEMA42 gate based on the gate
* index.
*
* The input gate index is XOR'ed with 3U:
* 0 ^ 3 = 3
* 1 ^ 3 = 2
* 2 ^ 3 = 1
* 3 ^ 3 = 0
* 4 ^ 3 = 7
* 5 ^ 3 = 6
* 6 ^ 3 = 5
* 7 ^ 3 = 4
* ...
*/
#define SEMA42_GATEn(base, n) (*(&((base)->GATE3) + ((n) ^ 3U)))
/*******************************************************************************
* API
******************************************************************************/
#if defined(__cplusplus)
extern "C" {
#endif
/*!
* @brief Initializes the SEMA42 module.
*
* This function initializes the SEMA42 module. It only enables the clock but does
* not reset the gates because the module might be used by other processors
* at the same time. To reset the gates, call either SEMA42_ResetGate or
* SEMA42_ResetAllGates function.
*
* @param base SEMA42 peripheral base address.
*/
void SEMA42_Init(SEMA42_Type *base);
/*!
* @brief De-initializes the SEMA42 module.
*
* This function de-initializes the SEMA42 module. It only disables the clock.
*
* @param base SEMA42 peripheral base address.
*/
void SEMA42_Deinit(SEMA42_Type *base);
/*!
* @brief Tries to lock the SEMA42 gate.
*
* This function tries to lock the specific SEMA42 gate. If the gate has been
* locked by another processor, this function returns an error code.
*
* @param base SEMA42 peripheral base address.
* @param gateNum Gate number to lock.
* @param procNum Current processor number.
*
* @retval kStatus_Success Lock the sema42 gate successfully.
* @retval kStatus_SEMA42_Busy Sema42 gate has been locked by another processor.
*/
status_t SEMA42_TryLock(SEMA42_Type *base, uint8_t gateNum, uint8_t procNum);
/*!
* @brief Locks the SEMA42 gate.
*
* This function locks the specific SEMA42 gate. If the gate has been
* locked by other processors, this function waits until it is unlocked and then
* lock it.
*
* @param base SEMA42 peripheral base address.
* @param gateNum Gate number to lock.
* @param procNum Current processor number.
*/
void SEMA42_Lock(SEMA42_Type *base, uint8_t gateNum, uint8_t procNum);
/*!
* @brief Unlocks the SEMA42 gate.
*
* This function unlocks the specific SEMA42 gate. It only writes unlock value
* to the SEMA42 gate register. However, it does not check whether the SEMA42 gate is locked
* by the current processor or not. As a result, if the SEMA42 gate is not locked by the current
* processor, this function has no effect.
*
* @param base SEMA42 peripheral base address.
* @param gateNum Gate number to unlock.
*/
static inline void SEMA42_Unlock(SEMA42_Type *base, uint8_t gateNum)
{
assert(gateNum < FSL_FEATURE_SEMA42_GATE_COUNT);
/* ^= 0x03U because SEMA42 gates are in the order 3, 2, 1, 0, 7, 6, 5, 4, 11, 10, 9, 8, 7, ...*/
SEMA42_GATEn(base, gateNum) = kSEMA42_Unlocked;
}
/*!
* @brief Gets the status of the SEMA42 gate.
*
* This function checks the lock status of a specific SEMA42 gate.
*
* @param base SEMA42 peripheral base address.
* @param gateNum Gate number.
*
* @return status Current status.
*/
static inline sema42_gate_status_t SEMA42_GetGateStatus(SEMA42_Type *base, uint8_t gateNum)
{
assert(gateNum < FSL_FEATURE_SEMA42_GATE_COUNT);
return (sema42_gate_status_t)(SEMA42_GATEn(base, gateNum));
}
/*!
* @brief Resets the SEMA42 gate to an unlocked status.
*
* This function resets a SEMA42 gate to an unlocked status.
*
* @param base SEMA42 peripheral base address.
* @param gateNum Gate number.
*
* @retval kStatus_Success SEMA42 gate is reset successfully.
* @retval kStatus_SEMA42_Reseting Some other reset process is ongoing.
*/
status_t SEMA42_ResetGate(SEMA42_Type *base, uint8_t gateNum);
/*!
* @brief Resets all SEMA42 gates to an unlocked status.
*
* This function resets all SEMA42 gate to an unlocked status.
*
* @param base SEMA42 peripheral base address.
*
* @retval kStatus_Success SEMA42 is reset successfully.
* @retval kStatus_SEMA42_Reseting Some other reset process is ongoing.
*/
static inline status_t SEMA42_ResetAllGates(SEMA42_Type *base)
{
return SEMA42_ResetGate(base, SEMA42_GATE_NUM_RESET_ALL);
}
#if defined(__cplusplus)
}
#endif
/*!
* @}
*/
#endif /* _FSL_SEMA42_H_ */

View File

@ -0,0 +1,43 @@
/*
* Copyright (c) 2015, Freescale Semiconductor, Inc.
* Copyright 2016-2017 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include "fsl_sim.h"
/*******************************************************************************
* Codes
******************************************************************************/
#if (defined(FSL_FEATURE_SIM_OPT_HAS_USB_VOLTAGE_REGULATOR) && FSL_FEATURE_SIM_OPT_HAS_USB_VOLTAGE_REGULATOR)
void SIM_SetUsbVoltRegulatorEnableMode(uint32_t mask)
{
SIM->SOPT1CFG |= (SIM_SOPT1CFG_URWE_MASK | SIM_SOPT1CFG_UVSWE_MASK | SIM_SOPT1CFG_USSWE_MASK);
SIM->SOPT1 = (SIM->SOPT1 & ~kSIM_UsbVoltRegEnableInAllModes) | mask;
}
#endif /* FSL_FEATURE_SIM_OPT_HAS_USB_VOLTAGE_REGULATOR */
void SIM_GetUniqueId(sim_uid_t *uid)
{
#if defined(SIM_UIDH)
uid->H = SIM->UIDH;
#endif
#if (defined(FSL_FEATURE_SIM_HAS_UIDM) && FSL_FEATURE_SIM_HAS_UIDM)
uid->M = SIM->UIDM;
#else
uid->MH = SIM->UIDMH;
uid->ML = SIM->UIDML;
#endif /* FSL_FEATURE_SIM_HAS_UIDM */
uid->L = SIM->UIDL;
}
#if (defined(FSL_FEATURE_SIM_HAS_RF_MAC_ADDR) && FSL_FEATURE_SIM_HAS_RF_MAC_ADDR)
void SIM_GetRfAddr(sim_rf_addr_t *info)
{
info->rfAddrL = SIM->RFADDRL;
info->rfAddrH = SIM->RFADDRH;
}
#endif /* FSL_FEATURE_SIM_HAS_RF_MAC_ADDR */

View File

@ -0,0 +1,150 @@
/*
* Copyright (c) 2015, Freescale Semiconductor, Inc.
* Copyright 2016-2017 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef _FSL_SIM_H_
#define _FSL_SIM_H_
#include "fsl_common.h"
/*! @addtogroup sim */
/*! @{*/
/*******************************************************************************
* Definitions
*******************************************************************************/
/*! @name Driver version */
/*@{*/
#define FSL_SIM_DRIVER_VERSION (MAKE_VERSION(2, 0, 0)) /*!< Driver version 2.0.0 */
/*@}*/
#if (defined(FSL_FEATURE_SIM_OPT_HAS_USB_VOLTAGE_REGULATOR) && FSL_FEATURE_SIM_OPT_HAS_USB_VOLTAGE_REGULATOR)
/*!@brief USB voltage regulator enable setting. */
enum _sim_usb_volt_reg_enable_mode
{
kSIM_UsbVoltRegEnable = SIM_SOPT1_USBREGEN_MASK, /*!< Enable voltage regulator. */
kSIM_UsbVoltRegEnableInLowPower = SIM_SOPT1_USBVSTBY_MASK, /*!< Enable voltage regulator in VLPR/VLPW modes. */
kSIM_UsbVoltRegEnableInStop = SIM_SOPT1_USBSSTBY_MASK, /*!< Enable voltage regulator in STOP/VLPS/LLS/VLLS modes. */
kSIM_UsbVoltRegEnableInAllModes = SIM_SOPT1_USBREGEN_MASK | SIM_SOPT1_USBSSTBY_MASK |
SIM_SOPT1_USBVSTBY_MASK /*!< Enable voltage regulator in all power modes. */
};
#endif /* (defined(FSL_FEATURE_SIM_OPT_HAS_USB_VOLTAGE_REGULATOR) && FSL_FEATURE_SIM_OPT_HAS_USB_VOLTAGE_REGULATOR) */
/*!@brief Unique ID. */
typedef struct _sim_uid
{
#if defined(SIM_UIDH)
uint32_t H; /*!< UIDH. */
#endif
#if (defined(FSL_FEATURE_SIM_HAS_UIDM) && FSL_FEATURE_SIM_HAS_UIDM)
uint32_t M; /*!< SIM_UIDM. */
#else
uint32_t MH; /*!< UIDMH. */
uint32_t ML; /*!< UIDML. */
#endif /* FSL_FEATURE_SIM_HAS_UIDM */
uint32_t L; /*!< UIDL. */
} sim_uid_t;
#if (defined(FSL_FEATURE_SIM_HAS_RF_MAC_ADDR) && FSL_FEATURE_SIM_HAS_RF_MAC_ADDR)
/*! @brief RF Mac Address.*/
typedef struct _sim_rf_addr
{
uint32_t rfAddrL; /*!< RFADDRL. */
uint32_t rfAddrH; /*!< RFADDRH. */
} sim_rf_addr_t;
#endif /* FSL_FEATURE_SIM_HAS_RF_MAC_ADDR */
/*!@brief Flash enable mode. */
enum _sim_flash_mode
{
kSIM_FlashDisableInWait = SIM_FCFG1_FLASHDOZE_MASK, /*!< Disable flash in wait mode. */
kSIM_FlashDisable = SIM_FCFG1_FLASHDIS_MASK /*!< Disable flash in normal mode. */
};
/*******************************************************************************
* API
******************************************************************************/
#if defined(__cplusplus)
extern "C" {
#endif /* __cplusplus*/
#if (defined(FSL_FEATURE_SIM_OPT_HAS_USB_VOLTAGE_REGULATOR) && FSL_FEATURE_SIM_OPT_HAS_USB_VOLTAGE_REGULATOR)
/*!
* @brief Sets the USB voltage regulator setting.
*
* This function configures whether the USB voltage regulator is enabled in
* normal RUN mode, STOP/VLPS/LLS/VLLS modes, and VLPR/VLPW modes. The configurations
* are passed in as mask value of \ref _sim_usb_volt_reg_enable_mode. For example, to enable
* USB voltage regulator in RUN/VLPR/VLPW modes and disable in STOP/VLPS/LLS/VLLS mode,
* use:
*
* SIM_SetUsbVoltRegulatorEnableMode(kSIM_UsbVoltRegEnable | kSIM_UsbVoltRegEnableInLowPower);
*
* @param mask USB voltage regulator enable setting.
*/
void SIM_SetUsbVoltRegulatorEnableMode(uint32_t mask);
#endif /* FSL_FEATURE_SIM_OPT_HAS_USB_VOLTAGE_REGULATOR */
/*!
* @brief Gets the unique identification register value.
*
* @param uid Pointer to the structure to save the UID value.
*/
void SIM_GetUniqueId(sim_uid_t *uid);
/*!
* @brief Sets the flash enable mode.
*
* @param mode The mode to set; see \ref _sim_flash_mode for mode details.
*/
static inline void SIM_SetFlashMode(uint8_t mode)
{
SIM->FCFG1 = mode;
}
#if (defined(FSL_FEATURE_SIM_HAS_RF_MAC_ADDR) && FSL_FEATURE_SIM_HAS_RF_MAC_ADDR)
/*!
* @brief Gets the RF address register value.
*
* @param info Pointer to the structure to save the RF address value.
*/
void SIM_GetRfAddr(sim_rf_addr_t *info);
#endif /* FSL_FEATURE_SIM_HAS_RF_MAC_ADDR */
#if (defined(FSL_FEATURE_SIM_MISC2_HAS_SYSTICK_CLK_EN) && FSL_FEATURE_SIM_MISC2_HAS_SYSTICK_CLK_EN)
/*!
* @brief Enable the Systick clock or not.
*
* The Systick clock is enabled by default.
*
* @param enable The switcher for Systick clock.
*/
static inline void SIM_EnableSystickClock(bool enable)
{
if (enable)
{
SIM->MISC2 &= ~SIM_MISC2_SYSTICK_CLK_EN_MASK; /* Clear to enable. */
}
else
{
SIM->MISC2 |= SIM_MISC2_SYSTICK_CLK_EN_MASK; /* Set to disable. */
}
}
#endif /* FSL_FEATURE_SIM_MISC2_HAS_SYSTICK_CLK_EN */
#if defined(__cplusplus)
}
#endif /* __cplusplus*/
/*! @}*/
#endif /* _FSL_SIM_H_ */

View File

@ -0,0 +1,191 @@
/*
* Copyright (c) 2015, Freescale Semiconductor, Inc.
* Copyright (c) 2016, NXP
* All rights reserved.
*
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include "fsl_spm.h"
#include "math.h" /* Using floor() function to convert float variable to int. */
void SPM_GetRegulatorStatus(SPM_Type *base, spm_regulator_status_t *info)
{
assert(info);
volatile uint32_t tmp32 = base->RSR; /* volatile here is to make sure this value is actually from the hardware. */
info->isRadioRunForcePowerModeOn = (SPM_RSR_RFRUNFORCE_MASK == (tmp32 & SPM_RSR_RFRUNFORCE_MASK));
info->radioLowPowerModeStatus =
(spm_radio_low_power_mode_status_t)((tmp32 & SPM_RSR_RFPMSTAT_MASK) >> SPM_RSR_RFPMSTAT_SHIFT);
info->mcuLowPowerModeStatus =
(spm_mcu_low_power_mode_status_t)((tmp32 & SPM_RSR_MCUPMSTAT_MASK) >> SPM_RSR_MCUPMSTAT_SHIFT);
info->isDcdcLdoOn =
(0x4 == (0x4 & ((tmp32 & SPM_RSR_REGSEL_MASK) >> SPM_RSR_REGSEL_SHIFT))); /* 1<<2 responses DCDC LDO. */
info->isRfLdoOn =
(0x2 == (0x2 & ((tmp32 & SPM_RSR_REGSEL_MASK) >> SPM_RSR_REGSEL_SHIFT))); /* 1<<1 responses RF LDO. */
info->isCoreLdoOn =
(0x1 == (0x1 & ((tmp32 & SPM_RSR_REGSEL_MASK) >> SPM_RSR_REGSEL_SHIFT))); /* 1<<0 responses CORE LDO. */
}
void SPM_SetLowVoltDetectConfig(SPM_Type *base, const spm_low_volt_detect_config_t *config)
{
uint32_t tmp32 = base->LVDSC1 &
~(SPM_LVDSC1_VDD_LVDIE_MASK | SPM_LVDSC1_VDD_LVDRE_MASK | SPM_LVDSC1_VDD_LVDV_MASK |
SPM_LVDSC1_COREVDD_LVDIE_MASK | SPM_LVDSC1_COREVDD_LVDRE_MASK);
/* VDD voltage detection. */
tmp32 |= SPM_LVDSC1_VDD_LVDV(config->vddLowVoltDetectSelect);
if (config->enableIntOnVddLowVolt)
{
tmp32 |= SPM_LVDSC1_VDD_LVDIE_MASK;
}
if (config->enableResetOnVddLowVolt)
{
tmp32 |= SPM_LVDSC1_VDD_LVDRE_MASK;
}
/* Clear the Low Voltage Detect Flag with previouse power detect setting. */
tmp32 |= SPM_LVDSC1_VDD_LVDACK_MASK;
/* COREVDD voltage detection. */
if (config->enableIntOnCoreLowVolt)
{
tmp32 |= SPM_LVDSC1_COREVDD_LVDIE_MASK;
}
if (config->enableResetOnCoreLowVolt)
{
tmp32 |= SPM_LVDSC1_COREVDD_LVDRE_MASK;
}
tmp32 |= SPM_LVDSC1_COREVDD_LVDACK_MASK; /* Clear previous error flag. */
base->LVDSC1 = tmp32;
}
void SPM_SetLowVoltWarningConfig(SPM_Type *base, const spm_low_volt_warning_config_t *config)
{
uint32_t tmp32 = base->LVDSC2 & ~(SPM_LVDSC2_VDD_LVWV_MASK | SPM_LVDSC2_VDD_LVWIE_MASK);
tmp32 |= SPM_LVDSC2_VDD_LVWV(config->vddLowVoltDetectSelect);
if (config->enableIntOnVddLowVolt)
{
tmp32 |= SPM_LVDSC2_VDD_LVWIE_MASK;
}
tmp32 |= SPM_LVDSC2_VDD_LVWACK_MASK; /* Clear previous error flag. */
base->LVDSC2 = tmp32;
}
void SPM_SetHighVoltDetectConfig(SPM_Type *base, const spm_high_volt_detect_config_t *config)
{
uint32_t tmp32;
tmp32 = base->HVDSC1 & ~(SPM_HVDSC1_VDD_HVDIE_MASK | SPM_HVDSC1_VDD_HVDRE_MASK |\
SPM_HVDSC1_VDD_HVDV_MASK);
tmp32 |= SPM_HVDSC1_VDD_HVDV(config->vddHighVoltDetectSelect);
if(config->enableIntOnVddHighVolt)
{
tmp32 |= SPM_HVDSC1_VDD_HVDIE_MASK;
}
if(config->enableResetOnVddHighVolt)
{
tmp32 |= SPM_HVDSC1_VDD_HVDRE_MASK;
}
tmp32 |= SPM_HVDSC1_VDD_HVDACK_MASK; /* Clear previous error flag. */
base->HVDSC1 = tmp32;
}
void SPM_SetRfLdoConfig(SPM_Type *base, const spm_rf_ldo_config_t *config)
{
uint32_t tmp32 = 0U;
switch (config->lowPowerMode)
{
case kSPM_RfLdoRemainInHighPowerInLowPowerModes:
tmp32 |= SPM_RFLDOLPCNFG_LPSEL_MASK;
break;
default: /* kSPM_RfLdoEnterLowPowerInLowPowerModes. */
break;
}
base->RFLDOLPCNFG = tmp32;
tmp32 = SPM_RFLDOSC_IOSSSEL(config->softStartDuration) | SPM_RFLDOSC_IOREGVSEL(config->rfIoRegulatorVolt);
if (config->enableCurSink)
{
tmp32 |= SPM_RFLDOSC_ISINKEN_MASK;
}
base->RFLDOSC = tmp32;
}
void SPM_SetDcdcBattMonitor(SPM_Type *base, uint32_t batAdcVal)
{
/* Clear the value and disable it at first. */
base->DCDCC2 &= ~(SPM_DCDCC2_DCDC_BATTMONITOR_BATT_VAL_MASK | SPM_DCDCC2_DCDC_BATTMONITOR_EN_BATADJ_MASK);
if (0U != batAdcVal)
{
/* When setting the value to BATT_VAL field, it should be zero before. */
base->DCDCC2 |= SPM_DCDCC2_DCDC_BATTMONITOR_BATT_VAL(batAdcVal);
base->DCDCC2 |= SPM_DCDCC2_DCDC_BATTMONITOR_EN_BATADJ_MASK;
}
}
void SPM_EnableVddxStepLock(SPM_Type *base, bool enable)
{
if (enable)
{
base->DCDCC3 |= (SPM_DCDCC3_DCDC_VDD1P8CTRL_DISABLE_STEP_MASK | SPM_DCDCC3_DCDC_VDD1P2CTRL_DISABLE_STEP_MASK);
}
else
{
base->DCDCC3 &= ~(SPM_DCDCC3_DCDC_VDD1P8CTRL_DISABLE_STEP_MASK | SPM_DCDCC3_DCDC_VDD1P2CTRL_DISABLE_STEP_MASK);
}
}
void SPM_BypassDcdcBattMonitor(SPM_Type *base, bool enable, uint32_t value)
{
if (enable)
{
/* Set the user-defined value before enable the bypass. */
base->DCDCC3 = (base->DCDCC3 & ~SPM_DCDCC3_DCDC_VBAT_VALUE_MASK) | SPM_DCDCC3_DCDC_VBAT_VALUE(value);
/* Enable the bypass and load the user-defined value. */
base->DCDCC3 |= SPM_DCDCC3_DCDC_BYPASS_ADC_MEAS_MASK;
}
else
{
base->DCDCC3 &= ~SPM_DCDCC3_DCDC_BYPASS_ADC_MEAS_MASK;
}
}
void SPM_SetDcdcIntegratorConfig(SPM_Type *base, const spm_dcdc_integrator_config_t *config)
{
int32_t tmp32u;
double dutyCycle;
if (NULL == config)
{
base->DCDCC4 = 0U;
}
else
{
dutyCycle = ((config->vdd1p2Value / config->vBatValue)*32 - 16)*8192;
tmp32u = (int32_t)(dutyCycle);
base->DCDCC4 = SPM_DCDCC4_PULSE_RUN_SPEEDUP_MASK | SPM_DCDCC4_INTEGRATOR_VALUE_SELECT_MASK |
SPM_DCDCC4_INTEGRATOR_VALUE(tmp32u);
}
}
void SPM_SetLowPowerReqOutPinConfig(SPM_Type *base, const spm_low_power_req_out_pin_config_t *config)
{
if ((NULL == config) || (config->pinOutEnable))
{
base->LPREQPINCNTRL = 0U;
}
else
{
base->LPREQPINCNTRL =
SPM_LPREQPINCNTRL_POLARITY(config->pinOutPol) | SPM_LPREQPINCNTRL_LPREQOE_MASK; /* Enable the output. */
}
}

View File

@ -0,0 +1,861 @@
/*
* Copyright (c) 2015, Freescale Semiconductor, Inc.
* Copyright (c) 2016, NXP
* All rights reserved.
*
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef _FSL_SPM_H_
#define _FSL_SPM_H_
#include "fsl_common.h"
/*! @addtogroup spm */
/*! @{ */
/*******************************************************************************
* Definitions
******************************************************************************/
/*! @name Driver version */
/*@{*/
/*! @brief SPM driver version */
#define FSL_SPM_DRIVER_VERSION (MAKE_VERSION(2, 0, 0)) /*!< Version 2.0.0. */
/*@}*/
/*!
* @brief IP version ID definition.
*/
typedef struct _spm_version_id
{
uint16_t feature; /*!< Feature Specification Number. */
uint8_t minor; /*!< Minor version number. */
uint8_t major; /*!< Major version number. */
} spm_version_id_t;
/*!
* @brief Status of last RADIO Power Mode Configuration.
*/
typedef enum _spm_radio_low_power_mode_status
{
kSPM_RadioLowPowerModeReserved = 0x0, /*!< Reserved. */
kSPM_RadioLowPowerModeVLPS = 0x1, /*!< Current Power mode is VLPS. */
kSPM_RadioLowPowerModeLLS = 0x2, /*!< Current Power mode is LLS. */
kSPM_RadioLowPowerModeVLLS = 0x4, /*!< Current Power mode is VLLS. */
} spm_radio_low_power_mode_status_t;
/*!
* @brief Status of last MCU STOP Mode Power Configuration.
*/
typedef enum _spm_mcu_low_power_mode_status
{
kSPM_McuLowPowerModeReserved = 0U, /*!< Reserved. */
kSPM_McuLowPowerModeSTOP = 1U, /*!< Last Low Power mode is STOP. */
kSPM_McuLowPowerModeVLPS = (1U << 1), /*!< Last Low Power mode is VLPS. */
kSPM_McuLowPowerModeLLS = (1U << 2), /*!< Last Low Power mode is LLS. */
kSPM_McuLowPowerModeVLLS23 = (1U << 3), /*!< Last Low Power mode is VLLS23. */
kSPM_McuLowPowerModeVLLS01 = (1U << 4), /*!< Last Low Power mode is VLLS01. */
} spm_mcu_low_power_mode_status_t;
/*!
* @brief define the mask code for LDO regulators.
*
* These mask can be combined with 'or' as a parameter to any function.
*/
enum _spm_ldo_regulator
{
kSPM_CoreLdo = 1U, /*!< Mask code for CORE LDO. */
kSPM_RfLdo = (1U << 1), /*!< Mask code for RF LDO. */
kSPM_DcdcLdo = (1U << 2), /*!< Mask code for DCDC LDO. */
};
/*!
* @brief Keep the regulator status information.
*/
typedef struct _spm_regulator_status
{
bool isRadioRunForcePowerModeOn; /*!< RADIO Run Force Power Mode Status. */
spm_radio_low_power_mode_status_t radioLowPowerModeStatus; /*!< Status of last RADIO Power Mode Configuration. */
spm_mcu_low_power_mode_status_t mcuLowPowerModeStatus; /*!< Status of last MCU STOP Mode Power Configuration. */
bool isDcdcLdoOn; /*!< DCDC LDO regulator enabled. */
bool isRfLdoOn; /*!< RF LDO regulator enabled. */
bool isCoreLdoOn; /*!< Core LDO regulator enabled. */
} spm_regulator_status_t;
/*!
* @brief Configure the CORE LDO in run modes.
*/
enum _spm_core_ldo_run_mode_config
{
kSPM_CoreLdoRunModeEnableRtcPowerMonitor =
SPM_CORERCNFG_RTCVDDMEN_MASK, /*!< RTC power monitor enabled in run modes. */
kSPM_CoreLdoRunModeEnableUsbPowerMonitor =
SPM_CORERCNFG_USBVDDMEN_MASK, /*!< USB power monitor enabled in run modes. */
kSPM_CoreLdoRunModeEnableVddioPowerMonitor =
SPM_CORERCNFG_VDDIOVDDMEN_MASK, /*!< VDDIO power monitor enabled in run modes. */
};
/*!
* @brief Configure the CORE LDO in low power modes.
*/
enum _spm_core_ldo_low_power_mode_config
{
kSPM_CoreLdoLowPowerModeEnableRtcPowerMonitor =
SPM_CORELPCNFG_RTCVDDMEN_MASK, /*!< RTC power monitor enabled in LP modes. */
kSPM_CoreLdoLowPowerModeEnableUsbPowerMonitor =
SPM_CORELPCNFG_USBVDDMEN_MASK, /*!< USB power monitor enabled in LP modes. */
kSPM_CoreLdoLowPowerModeEnableVddioPowerMonitor =
SPM_CORELPCNFG_VDDIOVDDMEN_MASK, /*!< VDDIO power monitor enabled in LP modes. */
kSPM_CoreLdoLowPowerModeEnableAllReference =
SPM_CORELPCNFG_ALLREFEN_MASK, /*!< Enable all reference (bandgap, WELL
BIAS, 1k clk and LP 25na) in VLLS. */
kSPM_CoreLdoLowPowerModeEnableHighDrive = SPM_CORELPCNFG_LPHIDRIVE_MASK, /*!< Enable high driver in low power. */
kSPM_CoreLdoLowPowerModeEnableLVD =
SPM_CORELPCNFG_LVDEN_MASK, /*!< Enable level voltage detect in VLP/STOP modes. */
kSPM_CoreLdoLowPowerModeEnablePOR = SPM_CORELPCNFG_POREN_MASK, /*!< POR brownout remains enabled in VLLS mode. */
kSPM_CoreLdoLowPowerModeEnableLPO = SPM_CORELPCNFG_LPOEN_MASK, /*!< LPO remains enabled in VLLS modes. */
kSPM_CoreLdoLowPowerModeEnableBandgapBufferHightDrive =
SPM_CORELPCNFG_BGBDS_MASK, /*!< Enable the high drive for Bandgap Buffer. */
kSPM_CoreLdoLowPowerModeEnableBandgapBuffer = SPM_CORELPCNFG_BGBEN_MASK, /*!< Enable Bandgap Buffer. */
kSPM_CoreLdoLowPowerModeEnableBandgapInVLPx = SPM_CORELPCNFG_BGEN_MASK, /*!< Enable Bandgap in VLPx mode. */
kSPM_CoreLdoLowPowerModeRemainInHighPower =
SPM_CORELPCNFG_LPSEL_MASK, /*!< Core LDO remains in high power state in VLP/Stop modes. */
};
/*!
* @brief Sets the Core LDO voltage level.
*/
typedef enum _spm_core_ldo_voltage_select
{
kSPM_CoreLdoVoltLevel1P2 = 0U, /*!< Regulate to 1.2V set by the CORETRIM[VTRIM1P2] register. */
kSPM_CoreLdoVoltLevel1P1 = 1U, /*!< Regulate to 1.1V set by the CORETRIM[VTRIM1P1] register. */
kSPM_CoreLdoVoltLevelOffset = 3U, /*!< Regulate to Offset Voltage set by CORETRIM[OFFVTRIM] register. */
} spm_core_ldo_volt_select_t;
/*!
* @brief Low-voltage Detect Voltage Select
*/
typedef enum _spm_low_volt_detect_volt_select
{
kSPM_LowVoltDetectLowTrip = 0U, /*!< Low-trip point selected (VLVD = VLVDL )*/
kSPM_LowVoltDetectHighTrip = 1U /*!< High-trip point selected (VLVD = VLVDH )*/
} spm_low_volt_detect_volt_select_t;
/*!
* @brief Low-voltage Detect Configuration Structure.
*
* This structure reuses the configuration structure from legacy PMC module.
*/
typedef struct _spm_low_volt_detect_config
{
/* VDD voltage detection. */
bool enableIntOnVddLowVolt; /*!< Enable interrupt when VDD Low-voltage detect. */
bool enableResetOnVddLowVolt; /*!< Enable forcing a system reset when VDD Low-voltage detect. */
spm_low_volt_detect_volt_select_t vddLowVoltDetectSelect; /*!< Low-voltage detect trip point voltage selection. */
/* CORE voltage detection. */
bool enableIntOnCoreLowVolt; /*!< Enable interrupt when Core Low-voltage detect. */
bool enableResetOnCoreLowVolt; /*!< Enable forcing a system reset when Core Low-voltage detect. */
} spm_low_volt_detect_config_t;
/*!
* @brief Low-voltage Warning Voltage Select.
*/
typedef enum _spm_low_volt_warning_volt_select
{
kSPM_LowVoltWarningLowTrip = 0U, /*!< Low-trip point selected (VLVW = VLVW1)*/
kSPM_LowVoltWarningMID1Trip = 1U, /*!< Mid1-trip point selected (VLVW = VLVW2)*/
kSPM_LowVoltWarningMID2Trip = 2U, /*!< Mid2-trip point selected (VLVW = VLVW3)*/
kSPM_LowVoltWarningHighTrip = 3U /*!< High-trip point selected (VLVW = VLVW4)*/
} spm_low_volt_warning_volt_select_t;
/*!
* @brief Low-voltage Warning Configuration Structure
*/
typedef struct _spm_low_volt_warning_config
{
bool enableIntOnVddLowVolt; /*!< Enable interrupt when low-voltage warning*/
spm_low_volt_warning_volt_select_t vddLowVoltDetectSelect; /*!< Low-voltage warning trip point voltage selection*/
} spm_low_volt_warning_config_t;
/*!
* @brief High-voltage Detect Voltage Select.
*/
typedef enum _spm_high_volt_detect_volt_select
{
kSPM_HighVoltDetectLowTrip = 0U, /*!< Low-trip point selected (VHVD = VHVDL )*/
kSPM_HighVoltDetectHighTrip = 1U /*!< High-trip point selected (VHVD = VHVDH )*/
} spm_high_volt_detect_volt_select_t;
/*!
* @brief High-voltage Detect Configuration Structure.
*
* This structure reuses the configuration structure from legacy PMC module.
*/
typedef struct _spm_high_volt_detect_config
{
bool enableIntOnVddHighVolt; /*!< Enable interrupt when high-voltage detect*/
bool enableResetOnVddHighVolt; /*!< Enable system reset when high-voltage detect*/
spm_high_volt_detect_volt_select_t vddHighVoltDetectSelect; /*!< High-voltage detect trip point voltage selection*/
} spm_high_volt_detect_config_t;
/*!
* @brief Defines the RF LDO low power behiavior when in low power modes.
*/
typedef enum _spm_rf_ldo_low_power_mode
{
kSPM_RfLdoEnterLowPowerInLowPowerModes = 0U, /*!< RF LDO regulator enters low power state in VLP/Stop modes. */
kSPM_RfLdoRemainInHighPowerInLowPowerModes =
1U, /*!< RF LDO regulator remains in high power state in VLP/Stop modes. */
} spm_rf_ldo_low_power_mode_t;
/*!
* @brief Selects the soft start duration delay for the IO 1.8 full power regulator.
*/
typedef enum _spm_rf_ldo_soft_start_duration
{
kSPM_RfLdoSoftStartDuration110us = 0U, /*!< 110 us. */
kSPM_RfLdoSoftStartDuration95us = 1U, /*!< 95 us. */
kSPM_RfLdoSoftStartDuration60us = 2U, /*!< 60 us. */
kSPM_RfLdoSoftStartDuration48us = 3U, /*!< 48 us. */
kSPM_RfLdoSoftStartDuration38us = 4U, /*!< 38 us. */
kSPM_RfLdoSoftStartDuration30us = 5U, /*!< 30 us. */
kSPM_RfLdoSoftStartDuration24us = 6U, /*!< 24 us. */
kSPM_RfLdoSoftStartDuration17us = 7U, /*!< 17 us. */
} spm_rf_ldo_soft_start_duration_t;
/*!
* @brief IO Regulator Voltage Select.
*/
typedef enum _spm_rf_io_regulator_volt_select
{
kSPM_RfIoRegulatorVoltLevel1p8 = 0U, /*!< Regulate to 1.8V. */
kSPM_RfIoRegulatorVoltLevel1p5 = 1U, /*!< Regulate to 1.5V. */
} spm_rf_io_regulator_volt_select_t;
/*!
* @brief RF LDO configuration structure.
*/
typedef struct _spm_rf_ldo_config
{
spm_rf_ldo_low_power_mode_t lowPowerMode; /*!< RF LDO low power behaviour when in low power modes. */
spm_rf_ldo_soft_start_duration_t
softStartDuration; /*!< Selects the soft start duration delay for the IO 1.8 full power regulator. */
bool enableCurSink; /*!< Enables current sink feature of low power regulator.*/
spm_rf_io_regulator_volt_select_t rfIoRegulatorVolt; /*!< IO Regulator Voltage Select. */
} spm_rf_ldo_config_t;
/*!
* @brief Selects which sns 1p8 vdd pin is used.
*/
typedef enum _spm_rf_vdd_1p8_sns_pin_select
{
kSPM_RfVdd1p8Sns0 = 0U, /*!< VDD1p8_SNS0 selected. */
kSPM_RfVdd1p8Sns1 = 1U, /*!< VDD1p8_SNS1 selected. */
} spm_rf_vdd_1p8_sns_pin_select_t;
/*!
* @brief Selects the trim point for RF LDO.
*/
typedef enum _spm_rf_ldo_volt_trim_select
{
kSPM_RfLdoLowPowerVolt1p8Trim, /*!< RF LDO Low Power 1.8V trim point value. */
kSPM_RfLdoLowPowerVlot1p5Trim, /*!< RF LDO Low Power 1.5V trim point value. */
kSPM_RfLdoHighPowerVolt1p8Trim, /*!< RF LDO High Power 1.8V trim point value. */
kSPM_RfLdoHighPowerVolt1p5Trim, /*!< RF LDO High Power 1.5V trim point value/ */
kSPM_RfLdoRegulatorOffsetTrim,
} spm_rf_ldo_volt_trim_select_t;
/*!
* @brief Configuration for setting DCDC integrator value.
*/
typedef struct _spm_dcdc_integrator_value_config
{
double vdd1p2Value; /*!< VDD1P2 output voltage value. */
double vBatValue; /*!< Battery input voltage value, or the Vdd_dcdcin voltage value. */
} spm_dcdc_integrator_config_t;
/*!
* @brief Defines the selection of DCDC vbat voltage divider for ADC measure.
*/
typedef enum _spm_dcdc_vbat_adc_divider
{
kSPM_DcdcVbatAdcOff = 0U, /*!< OFF. */
kSPM_DcdcVbatAdcDivider1 = 1U, /*!< VBAT. */
kSPM_DcdcVbatAdcDivider2 = 2U, /*!< VBAT /2. */
kSPM_DcdcVbatAdcDivider4 = 3U, /*!< VBAT /4. */
} spm_dcdc_vbat_adc_divider_t;
/*!
* @brief Configuration of power switch delay.
*/
typedef struct _spm_power_switch_delay_config
{
uint32_t coreRegFromDeepPowerDownToIso; /*!< Deep Power Down Wakeup Switch to ISO Delay. <= 0xFF */
uint32_t coreRegFromLowPowerToIso; /*!< Low Power Wakeup Switch to ISO Delay. */
uint32_t lowPowerToBandgapOn; /*!< Low Power Wake Up Delay. */
uint32_t dcdcStartupDelay; /*!< Configures the number of cycles for DCDC startup before the Core
LDO or RF LDO can be disabled. */
uint32_t ldoCoreSwitchHsrunDelay; /*!< Configures the number of cycles delay for LDO CORE
Regulator in and out of HSRUN mode. */
} spm_power_switch_delay_config_t;
/*!
* @brief Defines the selection of low power request pin out pin polarity.
*/
typedef enum _spm_low_power_req_out_pin_pol
{
kSPM_LowPowerReqOutPinHighTruePol = 0U, /*!< High true polarity. */
kSPM_LowPowerReqOutPinLowTruePol = 1U, /*!< Low true polarity. */
} spm_low_power_req_out_pin_pol_t;
/*!
* @brief Configuration structure of low power request out pin.
*/
typedef struct _spm_low_power_req_out_pin_config
{
spm_low_power_req_out_pin_pol_t pinOutPol; /*!< ow power request pin out pin polarity. */
bool pinOutEnable; /*!< Low Power request output pin is enabled or not. */
} spm_low_power_req_out_pin_config_t;
/*!
* @brief Defines the selection of DCDC driver strength.
*
* The more FETs are enabled, the more drive strength DCDC would provide.
*/
typedef enum _spm_dcdc_drive_strength
{
kSPM_DcdcDriveStrengthWithNormal = 0U, /*!< No additional FET setting. */
kSPM_DcdcDriveStrengthWithHalfFETs = 0x4, /*!< Half FETs. */
kSPM_DcdcDriveStrengthWithDoubleFETs = 0x2, /*!< Double FETs. */
kSPM_DcdcDriveStrengthWithExtraHalfFETs = 0x1, /*!< Half FETs. */
kSPM_DcdcDriveStrengthWithHalfAndDoubleFETs = 0x6, /*!< Half + Double FETs. */
kSPM_DcdcDriveStrengthWithHalfAndExtraDoubleFETs = 0x5, /*!< Half + Extra Double FETs. */
kSPM_DcdcDriveStrengthWithDoubleAndExtraDoubleFETs = 0x3, /*!< Double + Extra Double FETs. */
kSPM_DcdcDriveStrengthWithAllFETs = 7U, /*!< Half + Double + Extra Double FETs. */
} spm_dcdc_drive_strength_t;
/*!
* @brief DCDC flags.
*/
enum _spm_dcdc_flags
{
kSPM_DcdcStableOKFlag = SPM_DCDCSC_DCDC_STS_DC_OK_MASK, /*!< Status flag to indicate DCDC lock. */
kSPM_DcdcClockFaultFlag =
SPM_DCDCSC_CLKFLT_FAULT_MASK, /*!< Asserts if DCDC detect a clk fault. Will cause a system lvd reset to assert.
*/
};
/*******************************************************************************
* API
******************************************************************************/
#if defined(__cplusplus)
extern "C" {
#endif /* __cplusplus*/
/*! @name System Power Manager. */
/*@{*/
/*!
* @brief Gets the SPM version ID.
*
* This function gets the SPM version ID, including major version number,
* minor version number, and a feature specification number.
*
* @param base SPM peripheral base address.
* @param versionId Pointer to version ID structure.
*/
static inline void SPM_GetVersionId(SPM_Type *base, spm_version_id_t *versionId)
{
*((uint32_t *)versionId) = base->VERID;
}
/*!
* @brief Gets the regulators Status.
*
* @param base SPM peripheral base address.
* @param info Pointer to status structure, see to #spm_regulator_status_t.
*/
void SPM_GetRegulatorStatus(SPM_Type *base, spm_regulator_status_t *info);
/*!
* @brief Controls which regulators are enabled in RUN and HSRUN modes.
*
* This function controls which regulator (CORE LDO, RF LDO, and DCDC) are enabled in RUN and HSRUN
* modes. It sets the SPM_RCTRL register.
* Note that the RCTRL bits are reset solely on a POR/LVD only event.
*
* @param base SPM peripheral base address.
* @param enable Enable or disable the LDOs list in ldoMask.
* @param ldoMask Mask value of LDO list. See to #_spm_ldo_regulator.
*/
static inline void SPM_EnableRegulatorInRunMdoe(SPM_Type *base, bool enable, uint32_t ldoMask)
{
if (enable)
{
base->RCTRL |= SPM_RCTRL_REGSEL(ldoMask);
}
else
{
base->RCTRL &= ~SPM_RCTRL_REGSEL(ldoMask);
}
}
/*!
* @brief Controls which regulators are enabled in low power modes.
*
* This function controls which regulator (CORE LDO, RF LDO, and DCDC) are enabled in low power
* modes. It sets the SPM_LPCTRL register.
* Note that the SPM_LPCTRL bits are reset solely on a POR/LVD only event.
*
* @param base SPM peripheral base address.
* @param enable Enable or disable the LDOs list in ldoMask.
* @param ldoMask Mask value of LDO list.
*/
static inline void SPM_EnableRegulatorInLowPowerMode(SPM_Type *base, bool enable, uint32_t ldoMask)
{
if (enable)
{
base->LPCTRL |= SPM_LPCTRL_REGSEL(ldoMask);
}
else
{
base->LPCTRL &= ~SPM_LPCTRL_REGSEL(ldoMask);
}
}
/*!
* @brief Configures the CORE LDO working in run modes.
*
* @param base SPM peripheral base address.
* @param conifgMask Mask value of configuration items. See to #_spm_core_ldo_run_mode_config.
*/
static inline void SPM_SetCoreLdoRunModeConfig(SPM_Type *base, uint32_t configMask)
{
base->CORERCNFG = configMask;
}
/*!
* @brief Configures the CORE LDO working in low power modes.
*
* @param base SPM peripheral base address.
* @param conifgMask Mask value of configuration items. See to #_spm_core_ldo_low_power_mode_config.
*/
static inline void SPM_SetCoreLdoLowPowerModeConfig(SPM_Type *base, uint32_t configMask)
{
base->CORELPCNFG = configMask;
}
/*!
* @brief Check if the CORE LDO is in run regulation.
*
* @param base SPM peripheral base address.
* @retval true Regulator is in run regulation.
* @retval false Regulator is in stop regulation or in transition to/from it.
*/
static inline bool SPM_GetCoreLdoInRunRegulationFlag(SPM_Type *base)
{
return (SPM_CORESC_REGONS_MASK == (SPM_CORESC_REGONS_MASK & base->CORESC));
}
/*!
* @brief Gets the acknowledge Peripherals and I/O pads isolation flag.
*
* This function reads the Acknowledge Isolation setting that indicates
* whether certain peripherals and the I/O pads are in a latched state as
* a result of having been in the VLLS mode.
*
* @param base SPM peripheral base address.
* @return ACK isolation
* 0 - Peripherals and I/O pads are in a normal run state.
* 1 - Certain peripherals and I/O pads are in an isolated and
* latched state.
*/
static inline bool SPM_GetPeriphIOIsolationFlag(SPM_Type *base)
{
return (SPM_CORESC_ACKISO_MASK == (base->CORESC & SPM_CORESC_ACKISO_MASK));
}
/*!
* @brief Acknowledges the isolation flag to Peripherals and I/O pads.
*
* This function clears the ACK Isolation flag. Writing one to this setting
* when it is set releases the I/O pads and certain peripherals to their normal
* run mode state.
*
* @param base SPM peripheral base address.
*/
static inline void SPM_ClearPeriphIOIsolationFlag(SPM_Type *base)
{
base->CORESC |= SPM_CORESC_ACKISO_MASK;
}
/*@}*/
/*! @name VDD Low voltage detection APIs*/
/*@{*/
/*!
* @brief Configures the low-voltage detect setting.
*
* This function configures the low-voltage detect setting, including the trip
* point voltage setting, enables or disables the interrupt, enables or disables the system reset.
*
* @param base SPM peripheral base address.
* @param config Pointer to low-voltage detect configuration structure, see to #spm_low_volt_detect_config_t.
*/
void SPM_SetLowVoltDetectConfig(SPM_Type *base, const spm_low_volt_detect_config_t *config);
/*!
* @brief Gets VDD Low-voltage Detect Flag status.
*
* @param base SPM peripheral base address.
* @return Current low-voltage detect flag
* - true: Low-voltage detected
* - false: Low-voltage not detected
*/
static inline bool SPM_GetVddLowVoltDetectFlag(SPM_Type *base)
{
return (SPM_LVDSC1_VDD_LVDF_MASK == (base->LVDSC1 & SPM_LVDSC1_VDD_LVDF_MASK));
}
/*!
* @brief Acknowledges clearing the Low-voltage Detect flag.
*
* This function acknowledges the low-voltage detection errors.
*
* @param base SPM peripheral base address.
*/
static inline void SPM_ClearVddLowVoltDetectFlag(SPM_Type *base)
{
base->LVDSC1 |= SPM_LVDSC1_VDD_LVDACK_MASK; /* W1C. */
}
/*@}*/
/*! @name CORE LDO Low voltage detection APIs */
/*@{*/
/*!
* @brief Gets the COREVdds Low-voltage Detect Flag status.
*
* This function reads the current LVDF status. If it returns 1, a low-voltage event is detected.
*
* @param base SPM peripheral base address.
* @return Current low-voltage detect flag
* - true: Low-voltage detected
* - false: Low-voltage not detected
*/
static inline bool SPM_GetCoreLowVoltDetectFlag(SPM_Type *base)
{
return (SPM_LVDSC1_COREVDD_LVDF_MASK == (base->LVDSC1 & SPM_LVDSC1_COREVDD_LVDF_MASK));
}
/*!
* @brief Acknowledges clearing the CORE VDD Low-voltage Detect flag.
*
* This function acknowledges the CORE VDD low-voltage detection errors.
*
* @param base SPM peripheral base address.
*/
static inline void SPM_ClearCoreLowVoltDetectFlag(SPM_Type *base)
{
base->LVDSC1 |= SPM_LVDSC1_COREVDD_LVDACK_MASK; /* W1C. */
}
/*!
* @brief Configures the low-voltage warning setting.
*
* This function configures the low-voltage warning setting, including the trip
* point voltage setting and enabling or disabling the interrupt.
*
* @param base SPM peripheral base address.
* @param config Pointer to Low-voltage warning configuration structure, see to #spm_low_volt_warning_config_t.
*/
void SPM_SetLowVoltWarningConfig(SPM_Type *base, const spm_low_volt_warning_config_t *config);
/*!
* @brief Gets Vdd Low-voltage Warning Flag status.
*
* This function polls the current LVWF status. When 1 is returned, it
* indicates a low-voltage warning event. LVWF is set when V Supply transitions
* below the trip point or after reset and V Supply is already below the V LVW.
*
* @param base SPM peripheral base address.
* @return Current LVWF status
* - true: Low-voltage Warning Flag is set.
* - false: the Low-voltage Warning does not happen.
*/
static inline bool SPM_GetVddLowVoltWarningFlag(SPM_Type *base)
{
return (SPM_LVDSC2_VDD_LVWF_MASK == (base->LVDSC2 & SPM_LVDSC2_VDD_LVWF_MASK));
}
/*!
* @brief Acknowledges the Low-voltage Warning flag.
*
* This function acknowledges the low voltage warning errors (write 1 to
* clear LVWF).
*
* @param base SPM peripheral base address.
*/
static inline void SPM_ClearLowVoltWarningFlag(SPM_Type *base)
{
base->LVDSC2 |= SPM_LVDSC2_VDD_LVWACK_MASK; /* W1C. */
}
/*@}*/
/*! @name VDD high voltage detection APIs. */
/*@{*/
/*!
* @brief Configures the high-voltage detect setting.
*
* This function configures the high-voltage detect setting, including the trip
* point voltage setting, enabling or disabling the interrupt, enabling or disabling the system reset.
*
* @param base SPM peripheral base address.
* @param config High-voltage detect configuration structure, see to #spm_high_volt_detect_config_t.
*/
void SPM_SetHighVoltDetectConfig(SPM_Type *base, const spm_high_volt_detect_config_t *config);
/*!
* @brief Gets the High-voltage Detect Flag status.
*
* This function reads the current HVDF status. If it returns 1, a low
* voltage event is detected.
*
* @param base SPM peripheral base address.
* @return Current high-voltage detect flag
* - true: High-voltage detected
* - false: High-voltage not detected
*/
static inline bool SPM_GetHighVoltDetectFlag(SPM_Type *base)
{
return (SPM_HVDSC1_VDD_HVDF_MASK == (base->HVDSC1 & SPM_HVDSC1_VDD_HVDF_MASK));
}
/*!
* @brief Acknowledges clearing the High-voltage Detect flag.
*
* This function acknowledges the high-voltage detection errors (write 1 to
* clear HVDF).
*
* @param base SPM peripheral base address.
*/
static inline void SPM_ClearHighVoltDetectFlag(SPM_Type *base)
{
base->HVDSC1 |= SPM_HVDSC1_VDD_HVDACK_MASK; /* W1C. */
}
/*@}*/
/*! @name RF LDO Low voltage detection APIs */
/*@{*/
/*!
* @brief Configures the RF LDO.
*
* @param base SPM peripheral base address.
* @param config Pointer to configuration structure, see to #spm_rf_ldo_config_t.
*/
void SPM_SetRfLdoConfig(SPM_Type *base, const spm_rf_ldo_config_t *config);
/*!
* @brief Selects which SNS 1p8 vdd pin is used.
*
* @param base SPM peripheral base address.
* @param pin Selection of SNS 1p8 Vdd pin to be used, see to #spm_rf_vdd_1p8_sns_pin_select_t.
*/
static inline void SPM_SelectVdd1p8SnsPin(SPM_Type *base, spm_rf_vdd_1p8_sns_pin_select_t pin)
{
base->RFLDOSC = (base->RFLDOSC & ~SPM_RFLDOSC_VDD1P8SEL_MASK) | SPM_RFLDOSC_VDD1P8SEL(pin);
}
/*! @name DCDC Control APIs*/
/*@{*/
/*!
* @brief Sets DCDC battery monitor with its ADC value.
*
* For better accuracy, software would call this function to set the battery voltage value into DCDC
* measured by ADC.
*
* @param base SPM peripheral base address.
* @param batAdcVal ADC measured battery value with an 8mV LSB resolution.
* Value 0 would disable the battery monitor.
*/
void SPM_SetDcdcBattMonitor(SPM_Type *base, uint32_t batAdcVal);
/*!
* @brief Sets DCDC VBAT voltage divider.
*
* The divided VBAT output is input to an ADC channel which allows the battery voltage to be measured.
*
* @param base SPM peripheral base address.
* @param divider Setting divider, see to #spm_dcdc_vbat_adc_divider_t.
*/
static inline void SPM_SetDcdcVbatAdcMeasure(SPM_Type *base, spm_dcdc_vbat_adc_divider_t divider)
{
base->DCDCSC = (base->DCDCSC & ~SPM_DCDCSC_DCDC_VBAT_DIV_CTRL_MASK) | SPM_DCDCSC_DCDC_VBAT_DIV_CTRL(divider);
}
/*!
* @brief Power down output range comparator.
*
* @param base SPM peripheral base address.
* @param enable Power down the CMP or not.
*/
static inline void SPM_EnablePowerDownCmpOffset(SPM_Type *base, bool enable)
{
if (enable)
{
base->DCDCSC |= SPM_DCDCSC_PWD_CMP_OFFSET_MASK;
}
else
{
base->DCDCSC &= ~SPM_DCDCSC_PWD_CMP_OFFSET_MASK;
}
}
/*!
* @brief Get the status flags of DCDC module.
*
* @param base SPM peripheral base address.
* @return Mask value of flags. See to #_spm_dcdc_flags.
*/
static inline uint32_t SPM_GetDcdcStatusFlags(SPM_Type *base)
{
return (base->DCDCSC & (SPM_DCDCSC_DCDC_STS_DC_OK_MASK | SPM_DCDCSC_CLKFLT_FAULT_MASK));
}
/*!
* @brief Disable stepping for VDD1P8 and VDD1P2.
*
* Must lock the step for VDD1P8 and VDD1p2 before enteing low power modes.
*
* @param base SPM peripheral base address.
* @param enable Enable the lock or not to VDDx stepping.
*/
void SPM_EnableVddxStepLock(SPM_Type *base, bool enable);
/*!
* @brief Set the DCDC drive strength.
*
* Do set the DCDC drive strength according to actuall loading.
* The related register bits are:
* - DCDCC3[DCDC_MINPWR_HALF_FETS]
* - DCDCC3[DCDC_MINPWR_DOUBLE_FETS]
* - DCDCC3[DCDC_MINPWR_EXTRA_DOUBLE_FETS]
* The more FETs are enabled, the more drive strength DCDC would provide.
*
* @param base SPM peripheral base address.
* @param strength Selection of setting, see to #spm_dcdc_drive_strength_t
*/
static inline void SPM_SetDcdcDriveStrength(SPM_Type *base, spm_dcdc_drive_strength_t strength)
{
base->DCDCC3 = (base->DCDCC3 & ~0xE000000U) | ((uint32_t)(strength) << 25);
}
/*!
* @brief Bypasses the ADC measure value
*
* Forces DCDC to bypass the adc measuring state and loads the user-defined value in this function.
*
* @param base SPM peripheral base address.
* @param enable Enable the bypass or not.
* @param value User-setting value to be available instead of ADC measured value.
*/
void SPM_BypassDcdcBattMonitor(SPM_Type *base, bool enable, uint32_t value);
/*!
* @brief Configure the DCDC integrator value.
*
* Integrator value can be loaded in pulsed mode. Software can program this value according to
* battery voltage and VDD1P2 output target value before goes to the pulsed mode.
*
@code
spm_dcdc_integrator_config_t SpmDcdcIntegratorConfigStruct =
{
.vdd1p2Value = 1.2f,
.vBatValue = 3.34f
};
@endcode
*
* @param base SPM peripheral base address.
* @param config Pointer to configuration structure, see to #spm_dcdc_integrator_config_t.
* Passing NULL would clear all user-defined setting and use hardware default setting.
*/
void SPM_SetDcdcIntegratorConfig(SPM_Type *base, const spm_dcdc_integrator_config_t *config);
/*!
* @brief Sets the target value of VDD1P2 in buck HSRUN mode.
*
* Sets target value of VDD1P2 in buck HSRUN mode. 25 mV each step from 0x00 to 0x0F. This value is
* automatically selected on entry into HSRUN. On exit from HSRUN, DCDC VDD1P2 trim values will
* default back to values set by DCDC_VDD1P2CTRL_TRG_BUCK register, which is operated with the API of
* SPM_SetDcdcVdd1p2ValueBuck().
*
* @param base SPM peripheral base address.
* @param value Setting value of VDD1P2 in buck HSRUN mode.
*/
static inline void SPM_SetDcdcVdd1p2ValueHsrun(SPM_Type *base, uint32_t value)
{
base->DCDCC6 = (base->DCDCC6 & ~SPM_DCDCC6_DCDC_HSVDD_TRIM_MASK) | SPM_DCDCC6_DCDC_HSVDD_TRIM(value);
}
/*!
* @brief Sets the target value of VDD1P2 in buck mode.
*
* Sets the target value of VDD1P2 in buck mode, 25 mV each step from 0x00 to 0x0F.
*
* @param base SPM peripheral base address.
* @param value Setting value of VDD1P2 in buck mode.
*/
static inline void SPM_SetDcdcVdd1p2ValueBuck(SPM_Type *base, uint32_t value)
{
base->DCDCC6 =
(base->DCDCC6 & ~SPM_DCDCC6_DCDC_VDD1P2CTRL_TRG_BUCK_MASK) | SPM_DCDCC6_DCDC_VDD1P2CTRL_TRG_BUCK(value);
}
/*!
* @brief Sets the target value of VDD1P8.
*
* Sets the target value of VDD1P8 in buck mode, 25 mV each step from 0x00 to 0x3F.
*
* @param base SPM peripheral base address.
* @param value Setting value of VDD1P8 output.
*/
static inline void SPM_SetDcdcVdd1p8Value(SPM_Type *base, uint32_t value)
{
base->DCDCC6 = (base->DCDCC6 & ~SPM_DCDCC6_DCDC_VDD1P8CTRL_TRG_MASK) | SPM_DCDCC6_DCDC_VDD1P8CTRL_TRG(value);
}
/*@}*/
/*! @name Misc */
/*@{*/
/*!
* @brief Configures the low power requeset output pin.
*
* @param base SPM peripheral base address.
* @param config Pointer to the configuration structure, see to #spm_low_power_req_out_pin_config_t.
*/
void SPM_SetLowPowerReqOutPinConfig(SPM_Type *base, const spm_low_power_req_out_pin_config_t *config);
/*@}*/
/*@}*/
#if defined(__cplusplus)
}
#endif /* __cplusplus*/
/*! @}*/
#endif /* _FSL_SPM_H_*/

View File

@ -0,0 +1,744 @@
/*
* Copyright (c) 2015, Freescale Semiconductor, Inc.
* Copyright 2016-2017 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include "fsl_tpm.h"
/*******************************************************************************
* Definitions
******************************************************************************/
#define TPM_COMBINE_SHIFT (8U)
/*******************************************************************************
* Prototypes
******************************************************************************/
/*!
* @brief Gets the instance from the base address
*
* @param base TPM peripheral base address
*
* @return The TPM instance
*/
static uint32_t TPM_GetInstance(TPM_Type *base);
/*******************************************************************************
* Variables
******************************************************************************/
/*! @brief Pointers to TPM bases for each instance. */
static TPM_Type *const s_tpmBases[] = TPM_BASE_PTRS;
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
/*! @brief Pointers to TPM clocks for each instance. */
static const clock_ip_name_t s_tpmClocks[] = TPM_CLOCKS;
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
/*******************************************************************************
* Code
******************************************************************************/
static uint32_t TPM_GetInstance(TPM_Type *base)
{
uint32_t instance;
uint32_t tpmArrayCount = (sizeof(s_tpmBases) / sizeof(s_tpmBases[0]));
/* Find the instance index from base address mappings. */
for (instance = 0; instance < tpmArrayCount; instance++)
{
if (s_tpmBases[instance] == base)
{
break;
}
}
assert(instance < tpmArrayCount);
return instance;
}
void TPM_Init(TPM_Type *base, const tpm_config_t *config)
{
assert(config);
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
/* Enable the module clock */
CLOCK_EnableClock(s_tpmClocks[TPM_GetInstance(base)]);
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
#if defined(FSL_FEATURE_TPM_HAS_GLOBAL) && FSL_FEATURE_TPM_HAS_GLOBAL
/* TPM reset is available on certain SoC's */
TPM_Reset(base);
#endif
/* Set the clock prescale factor */
base->SC = TPM_SC_PS(config->prescale);
/* Setup the counter operation */
base->CONF = TPM_CONF_DOZEEN(config->enableDoze) | TPM_CONF_GTBEEN(config->useGlobalTimeBase) |
TPM_CONF_CROT(config->enableReloadOnTrigger) | TPM_CONF_CSOT(config->enableStartOnTrigger) |
TPM_CONF_CSOO(config->enableStopOnOverflow) |
#if defined(FSL_FEATURE_TPM_HAS_PAUSE_COUNTER_ON_TRIGGER) && FSL_FEATURE_TPM_HAS_PAUSE_COUNTER_ON_TRIGGER
TPM_CONF_CPOT(config->enablePauseOnTrigger) |
#endif
#if defined(FSL_FEATURE_TPM_HAS_EXTERNAL_TRIGGER_SELECTION) && FSL_FEATURE_TPM_HAS_EXTERNAL_TRIGGER_SELECTION
TPM_CONF_TRGSRC(config->triggerSource) |
#endif
TPM_CONF_TRGSEL(config->triggerSelect);
if (config->enableDebugMode)
{
base->CONF |= TPM_CONF_DBGMODE_MASK;
}
else
{
base->CONF &= ~TPM_CONF_DBGMODE_MASK;
}
}
void TPM_Deinit(TPM_Type *base)
{
/* Stop the counter */
base->SC &= ~TPM_SC_CMOD_MASK;
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
/* Gate the TPM clock */
CLOCK_DisableClock(s_tpmClocks[TPM_GetInstance(base)]);
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
}
void TPM_GetDefaultConfig(tpm_config_t *config)
{
assert(config);
/* TPM clock divide by 1 */
config->prescale = kTPM_Prescale_Divide_1;
/* Use internal TPM counter as timebase */
config->useGlobalTimeBase = false;
/* TPM counter continues in doze mode */
config->enableDoze = false;
/* TPM counter pauses when in debug mode */
config->enableDebugMode = false;
/* TPM counter will not be reloaded on input trigger */
config->enableReloadOnTrigger = false;
/* TPM counter continues running after overflow */
config->enableStopOnOverflow = false;
/* TPM counter starts immediately once it is enabled */
config->enableStartOnTrigger = false;
#if defined(FSL_FEATURE_TPM_HAS_PAUSE_COUNTER_ON_TRIGGER) && FSL_FEATURE_TPM_HAS_PAUSE_COUNTER_ON_TRIGGER
config->enablePauseOnTrigger = false;
#endif
/* Choose trigger select 0 as input trigger for controlling counter operation */
config->triggerSelect = kTPM_Trigger_Select_0;
#if defined(FSL_FEATURE_TPM_HAS_EXTERNAL_TRIGGER_SELECTION) && FSL_FEATURE_TPM_HAS_EXTERNAL_TRIGGER_SELECTION
/* Choose external trigger source to control counter operation */
config->triggerSource = kTPM_TriggerSource_External;
#endif
}
status_t TPM_SetupPwm(TPM_Type *base,
const tpm_chnl_pwm_signal_param_t *chnlParams,
uint8_t numOfChnls,
tpm_pwm_mode_t mode,
uint32_t pwmFreq_Hz,
uint32_t srcClock_Hz)
{
assert(chnlParams);
assert(pwmFreq_Hz);
assert(numOfChnls);
assert(srcClock_Hz);
#if defined(FSL_FEATURE_TPM_HAS_COMBINE) && FSL_FEATURE_TPM_HAS_COMBINE
if(mode == kTPM_CombinedPwm)
{
assert(FSL_FEATURE_TPM_COMBINE_HAS_EFFECTn(base));
}
#endif
uint32_t mod;
uint32_t tpmClock = (srcClock_Hz / (1U << (base->SC & TPM_SC_PS_MASK)));
uint16_t cnv;
uint8_t i;
#if defined(FSL_FEATURE_TPM_HAS_QDCTRL) && FSL_FEATURE_TPM_HAS_QDCTRL
/* The TPM's QDCTRL register required to be effective */
if( FSL_FEATURE_TPM_QDCTRL_HAS_EFFECTn(base) )
{
/* Clear quadrature Decoder mode because in quadrature Decoder mode PWM doesn't operate*/
base->QDCTRL &= ~TPM_QDCTRL_QUADEN_MASK;
}
#endif
switch (mode)
{
case kTPM_EdgeAlignedPwm:
#if defined(FSL_FEATURE_TPM_HAS_COMBINE) && FSL_FEATURE_TPM_HAS_COMBINE
case kTPM_CombinedPwm:
#endif
base->SC &= ~TPM_SC_CPWMS_MASK;
mod = (tpmClock / pwmFreq_Hz) - 1;
break;
case kTPM_CenterAlignedPwm:
base->SC |= TPM_SC_CPWMS_MASK;
mod = tpmClock / (pwmFreq_Hz * 2);
break;
default:
return kStatus_Fail;
}
/* Return an error in case we overflow the registers, probably would require changing
* clock source to get the desired frequency */
if (mod > 65535U)
{
return kStatus_Fail;
}
/* Set the PWM period */
base->MOD = mod;
/* Setup each TPM channel */
for (i = 0; i < numOfChnls; i++)
{
/* Return error if requested dutycycle is greater than the max allowed */
if (chnlParams->dutyCyclePercent > 100)
{
return kStatus_Fail;
}
#if defined(FSL_FEATURE_TPM_HAS_COMBINE) && FSL_FEATURE_TPM_HAS_COMBINE
if (mode == kTPM_CombinedPwm)
{
uint16_t cnvFirstEdge;
/* This check is added for combined mode as the channel number should be the pair number */
if (chnlParams->chnlNumber >= (FSL_FEATURE_TPM_CHANNEL_COUNTn(base) / 2))
{
return kStatus_Fail;
}
/* Return error if requested value is greater than the max allowed */
if (chnlParams->firstEdgeDelayPercent > 100)
{
return kStatus_Fail;
}
/* Configure delay of the first edge */
if (chnlParams->firstEdgeDelayPercent == 0)
{
/* No delay for the first edge */
cnvFirstEdge = 0;
}
else
{
cnvFirstEdge = (mod * chnlParams->firstEdgeDelayPercent) / 100;
}
/* Configure dutycycle */
if (chnlParams->dutyCyclePercent == 0)
{
/* Signal stays low */
cnv = 0;
cnvFirstEdge = 0;
}
else
{
cnv = (mod * chnlParams->dutyCyclePercent) / 100;
/* For 100% duty cycle */
if (cnv >= mod)
{
cnv = mod + 1;
}
}
/* Set the combine bit for the channel pair */
base->COMBINE |= (1U << (TPM_COMBINE_COMBINE0_SHIFT + (TPM_COMBINE_SHIFT * chnlParams->chnlNumber)));
/* When switching mode, disable channel n first */
base->CONTROLS[chnlParams->chnlNumber * 2].CnSC &=
~(TPM_CnSC_MSA_MASK | TPM_CnSC_MSB_MASK | TPM_CnSC_ELSA_MASK | TPM_CnSC_ELSB_MASK);
/* Wait till mode change to disable channel is acknowledged */
while ((base->CONTROLS[chnlParams->chnlNumber * 2].CnSC &
(TPM_CnSC_MSA_MASK | TPM_CnSC_MSB_MASK | TPM_CnSC_ELSA_MASK | TPM_CnSC_ELSB_MASK)))
{
}
/* Set the requested PWM mode for channel n, PWM output requires mode select to be set to 2 */
base->CONTROLS[chnlParams->chnlNumber * 2].CnSC |=
((chnlParams->level << TPM_CnSC_ELSA_SHIFT) | (2U << TPM_CnSC_MSA_SHIFT));
/* Wait till mode change is acknowledged */
while (!(base->CONTROLS[chnlParams->chnlNumber * 2].CnSC &
(TPM_CnSC_MSA_MASK | TPM_CnSC_MSB_MASK | TPM_CnSC_ELSA_MASK | TPM_CnSC_ELSB_MASK)))
{
}
/* Set the channel pair values */
base->CONTROLS[chnlParams->chnlNumber * 2].CnV = cnvFirstEdge;
/* When switching mode, disable channel n + 1 first */
base->CONTROLS[(chnlParams->chnlNumber * 2) + 1].CnSC &=
~(TPM_CnSC_MSA_MASK | TPM_CnSC_MSB_MASK | TPM_CnSC_ELSA_MASK | TPM_CnSC_ELSB_MASK);
/* Wait till mode change to disable channel is acknowledged */
while ((base->CONTROLS[(chnlParams->chnlNumber * 2) + 1].CnSC &
(TPM_CnSC_MSA_MASK | TPM_CnSC_MSB_MASK | TPM_CnSC_ELSA_MASK | TPM_CnSC_ELSB_MASK)))
{
}
/* Set the requested PWM mode for channel n + 1, PWM output requires mode select to be set to 2 */
base->CONTROLS[(chnlParams->chnlNumber * 2) + 1].CnSC |=
((chnlParams->level << TPM_CnSC_ELSA_SHIFT) | (2U << TPM_CnSC_MSA_SHIFT));
/* Wait till mode change is acknowledged */
while (!(base->CONTROLS[(chnlParams->chnlNumber * 2) + 1].CnSC &
(TPM_CnSC_MSA_MASK | TPM_CnSC_MSB_MASK | TPM_CnSC_ELSA_MASK | TPM_CnSC_ELSB_MASK)))
{
}
/* Set the channel pair values */
base->CONTROLS[(chnlParams->chnlNumber * 2) + 1].CnV = cnvFirstEdge + cnv;
}
else
{
#endif
if (chnlParams->dutyCyclePercent == 0)
{
/* Signal stays low */
cnv = 0;
}
else
{
cnv = (mod * chnlParams->dutyCyclePercent) / 100;
/* For 100% duty cycle */
if (cnv >= mod)
{
cnv = mod + 1;
}
}
/* When switching mode, disable channel first */
base->CONTROLS[chnlParams->chnlNumber].CnSC &=
~(TPM_CnSC_MSA_MASK | TPM_CnSC_MSB_MASK | TPM_CnSC_ELSA_MASK | TPM_CnSC_ELSB_MASK);
/* Wait till mode change to disable channel is acknowledged */
while ((base->CONTROLS[chnlParams->chnlNumber].CnSC &
(TPM_CnSC_MSA_MASK | TPM_CnSC_MSB_MASK | TPM_CnSC_ELSA_MASK | TPM_CnSC_ELSB_MASK)))
{
}
/* Set the requested PWM mode, PWM output requires mode select to be set to 2 */
base->CONTROLS[chnlParams->chnlNumber].CnSC |=
((chnlParams->level << TPM_CnSC_ELSA_SHIFT) | (2U << TPM_CnSC_MSA_SHIFT));
/* Wait till mode change is acknowledged */
while (!(base->CONTROLS[chnlParams->chnlNumber].CnSC &
(TPM_CnSC_MSA_MASK | TPM_CnSC_MSB_MASK | TPM_CnSC_ELSA_MASK | TPM_CnSC_ELSB_MASK)))
{
}
base->CONTROLS[chnlParams->chnlNumber].CnV = cnv;
#if defined(FSL_FEATURE_TPM_HAS_COMBINE) && FSL_FEATURE_TPM_HAS_COMBINE
}
#endif
chnlParams++;
}
return kStatus_Success;
}
void TPM_UpdatePwmDutycycle(TPM_Type *base,
tpm_chnl_t chnlNumber,
tpm_pwm_mode_t currentPwmMode,
uint8_t dutyCyclePercent)
{
assert(chnlNumber < FSL_FEATURE_TPM_CHANNEL_COUNTn(base));
#if defined(FSL_FEATURE_TPM_HAS_COMBINE) && FSL_FEATURE_TPM_HAS_COMBINE
if(currentPwmMode == kTPM_CombinedPwm)
{
assert(FSL_FEATURE_TPM_COMBINE_HAS_EFFECTn(base));
}
#endif
uint16_t cnv, mod;
mod = base->MOD;
#if defined(FSL_FEATURE_TPM_HAS_COMBINE) && FSL_FEATURE_TPM_HAS_COMBINE
if (currentPwmMode == kTPM_CombinedPwm)
{
uint16_t cnvFirstEdge;
/* This check is added for combined mode as the channel number should be the pair number */
if (chnlNumber >= (FSL_FEATURE_TPM_CHANNEL_COUNTn(base) / 2))
{
return;
}
cnv = (mod * dutyCyclePercent) / 100;
cnvFirstEdge = base->CONTROLS[chnlNumber * 2].CnV;
/* For 100% duty cycle */
if (cnv >= mod)
{
cnv = mod + 1;
}
base->CONTROLS[(chnlNumber * 2) + 1].CnV = cnvFirstEdge + cnv;
}
else
{
#endif
cnv = (mod * dutyCyclePercent) / 100;
/* For 100% duty cycle */
if (cnv >= mod)
{
cnv = mod + 1;
}
base->CONTROLS[chnlNumber].CnV = cnv;
#if defined(FSL_FEATURE_TPM_HAS_COMBINE) && FSL_FEATURE_TPM_HAS_COMBINE
}
#endif
}
void TPM_UpdateChnlEdgeLevelSelect(TPM_Type *base, tpm_chnl_t chnlNumber, uint8_t level)
{
assert(chnlNumber < FSL_FEATURE_TPM_CHANNEL_COUNTn(base));
uint32_t reg = base->CONTROLS[chnlNumber].CnSC & ~(TPM_CnSC_CHF_MASK);
/* When switching mode, disable channel first */
base->CONTROLS[chnlNumber].CnSC &=
~(TPM_CnSC_MSA_MASK | TPM_CnSC_MSB_MASK | TPM_CnSC_ELSA_MASK | TPM_CnSC_ELSB_MASK);
/* Wait till mode change to disable channel is acknowledged */
while ((base->CONTROLS[chnlNumber].CnSC &
(TPM_CnSC_MSA_MASK | TPM_CnSC_MSB_MASK | TPM_CnSC_ELSA_MASK | TPM_CnSC_ELSB_MASK)))
{
}
/* Clear the field and write the new level value */
reg &= ~(TPM_CnSC_ELSA_MASK | TPM_CnSC_ELSB_MASK);
reg |= ((uint32_t)level << TPM_CnSC_ELSA_SHIFT) & (TPM_CnSC_ELSA_MASK | TPM_CnSC_ELSB_MASK);
base->CONTROLS[chnlNumber].CnSC = reg;
/* Wait till mode change is acknowledged */
reg &= (TPM_CnSC_MSA_MASK | TPM_CnSC_MSB_MASK | TPM_CnSC_ELSA_MASK | TPM_CnSC_ELSB_MASK);
while (reg != (base->CONTROLS[chnlNumber].CnSC &
(TPM_CnSC_MSA_MASK | TPM_CnSC_MSB_MASK | TPM_CnSC_ELSA_MASK | TPM_CnSC_ELSB_MASK)))
{
}
}
void TPM_SetupInputCapture(TPM_Type *base, tpm_chnl_t chnlNumber, tpm_input_capture_edge_t captureMode)
{
assert(chnlNumber < FSL_FEATURE_TPM_CHANNEL_COUNTn(base));
#if defined(FSL_FEATURE_TPM_HAS_QDCTRL) && FSL_FEATURE_TPM_HAS_QDCTRL
/* The TPM's QDCTRL register required to be effective */
if( FSL_FEATURE_TPM_QDCTRL_HAS_EFFECTn(base) )
{
/* Clear quadrature Decoder mode for channel 0 or 1*/
if ((chnlNumber == 0) || (chnlNumber == 1))
{
base->QDCTRL &= ~TPM_QDCTRL_QUADEN_MASK;
}
}
#endif
#if defined(FSL_FEATURE_TPM_HAS_COMBINE) && FSL_FEATURE_TPM_HAS_COMBINE
/* The TPM's COMBINE register required to be effective */
if( FSL_FEATURE_TPM_COMBINE_HAS_EFFECTn(base) )
{
/* Clear the combine bit for chnlNumber */
base->COMBINE &= ~(1U << TPM_COMBINE_SHIFT * (chnlNumber / 2));
}
#endif
/* When switching mode, disable channel first */
base->CONTROLS[chnlNumber].CnSC &=
~(TPM_CnSC_MSA_MASK | TPM_CnSC_MSB_MASK | TPM_CnSC_ELSA_MASK | TPM_CnSC_ELSB_MASK);
/* Wait till mode change to disable channel is acknowledged */
while ((base->CONTROLS[chnlNumber].CnSC &
(TPM_CnSC_MSA_MASK | TPM_CnSC_MSB_MASK | TPM_CnSC_ELSA_MASK | TPM_CnSC_ELSB_MASK)))
{
}
/* Set the requested input capture mode */
base->CONTROLS[chnlNumber].CnSC |= captureMode;
/* Wait till mode change is acknowledged */
while (!(base->CONTROLS[chnlNumber].CnSC &
(TPM_CnSC_MSA_MASK | TPM_CnSC_MSB_MASK | TPM_CnSC_ELSA_MASK | TPM_CnSC_ELSB_MASK)))
{
}
}
void TPM_SetupOutputCompare(TPM_Type *base,
tpm_chnl_t chnlNumber,
tpm_output_compare_mode_t compareMode,
uint32_t compareValue)
{
assert(chnlNumber < FSL_FEATURE_TPM_CHANNEL_COUNTn(base));
#if defined(FSL_FEATURE_TPM_HAS_QDCTRL) && FSL_FEATURE_TPM_HAS_QDCTRL
/* The TPM's QDCTRL register required to be effective */
if( FSL_FEATURE_TPM_QDCTRL_HAS_EFFECTn(base) )
{
/* Clear quadrature Decoder mode for channel 0 or 1 */
if ((chnlNumber == 0) || (chnlNumber == 1))
{
base->QDCTRL &= ~TPM_QDCTRL_QUADEN_MASK;
}
}
#endif
/* When switching mode, disable channel first */
base->CONTROLS[chnlNumber].CnSC &=
~(TPM_CnSC_MSA_MASK | TPM_CnSC_MSB_MASK | TPM_CnSC_ELSA_MASK | TPM_CnSC_ELSB_MASK);
/* Wait till mode change to disable channel is acknowledged */
while ((base->CONTROLS[chnlNumber].CnSC &
(TPM_CnSC_MSA_MASK | TPM_CnSC_MSB_MASK | TPM_CnSC_ELSA_MASK | TPM_CnSC_ELSB_MASK)))
{
}
/* Setup the channel output behaviour when a match occurs with the compare value */
base->CONTROLS[chnlNumber].CnSC |= compareMode;
/* Setup the compare value */
base->CONTROLS[chnlNumber].CnV = compareValue;
/* Wait till mode change is acknowledged */
while (!(base->CONTROLS[chnlNumber].CnSC &
(TPM_CnSC_MSA_MASK | TPM_CnSC_MSB_MASK | TPM_CnSC_ELSA_MASK | TPM_CnSC_ELSB_MASK)))
{
}
}
#if defined(FSL_FEATURE_TPM_HAS_COMBINE) && FSL_FEATURE_TPM_HAS_COMBINE
void TPM_SetupDualEdgeCapture(TPM_Type *base,
tpm_chnl_t chnlPairNumber,
const tpm_dual_edge_capture_param_t *edgeParam,
uint32_t filterValue)
{
assert(edgeParam);
assert(chnlPairNumber < FSL_FEATURE_TPM_CHANNEL_COUNTn(base) / 2);
assert(FSL_FEATURE_TPM_COMBINE_HAS_EFFECTn(base));
uint32_t reg;
#if defined(FSL_FEATURE_TPM_HAS_QDCTRL) && FSL_FEATURE_TPM_HAS_QDCTRL
/* The TPM's QDCTRL register required to be effective */
if( FSL_FEATURE_TPM_QDCTRL_HAS_EFFECTn(base) )
{
/* Clear quadrature Decoder mode for channel 0 or 1*/
if (chnlPairNumber == 0)
{
base->QDCTRL &= ~TPM_QDCTRL_QUADEN_MASK;
}
}
#endif
/* Unlock: When switching mode, disable channel first */
base->CONTROLS[chnlPairNumber * 2].CnSC &=
~(TPM_CnSC_MSA_MASK | TPM_CnSC_MSB_MASK | TPM_CnSC_ELSA_MASK | TPM_CnSC_ELSB_MASK);
/* Wait till mode change to disable channel is acknowledged */
while ((base->CONTROLS[chnlPairNumber * 2].CnSC &
(TPM_CnSC_MSA_MASK | TPM_CnSC_MSB_MASK | TPM_CnSC_ELSA_MASK | TPM_CnSC_ELSB_MASK)))
{
}
base->CONTROLS[chnlPairNumber * 2 + 1].CnSC &=
~(TPM_CnSC_MSA_MASK | TPM_CnSC_MSB_MASK | TPM_CnSC_ELSA_MASK | TPM_CnSC_ELSB_MASK);
/* Wait till mode change to disable channel is acknowledged */
while ((base->CONTROLS[chnlPairNumber * 2 + 1].CnSC &
(TPM_CnSC_MSA_MASK | TPM_CnSC_MSB_MASK | TPM_CnSC_ELSA_MASK | TPM_CnSC_ELSB_MASK)))
{
}
/* Now, the registers for input mode can be operated. */
if (edgeParam->enableSwap)
{
/* Set the combine and swap bits for the channel pair */
base->COMBINE |= (TPM_COMBINE_COMBINE0_MASK | TPM_COMBINE_COMSWAP0_MASK)
<< (TPM_COMBINE_SHIFT * chnlPairNumber);
/* Input filter setup for channel n+1 input */
reg = base->FILTER;
reg &= ~(TPM_FILTER_CH0FVAL_MASK << (TPM_FILTER_CH1FVAL_SHIFT * (chnlPairNumber + 1)));
reg |= (filterValue << (TPM_FILTER_CH1FVAL_SHIFT * (chnlPairNumber + 1)));
base->FILTER = reg;
}
else
{
reg = base->COMBINE;
/* Clear the swap bit for the channel pair */
reg &= ~(TPM_COMBINE_COMSWAP0_MASK << (TPM_COMBINE_COMSWAP0_SHIFT * chnlPairNumber));
/* Set the combine bit for the channel pair */
reg |= TPM_COMBINE_COMBINE0_MASK << (TPM_COMBINE_SHIFT * chnlPairNumber);
base->COMBINE = reg;
/* Input filter setup for channel n input */
reg = base->FILTER;
reg &= ~(TPM_FILTER_CH0FVAL_MASK << (TPM_FILTER_CH1FVAL_SHIFT * chnlPairNumber));
reg |= (filterValue << (TPM_FILTER_CH1FVAL_SHIFT * chnlPairNumber));
base->FILTER = reg;
}
/* Setup the edge detection from channel n */
base->CONTROLS[chnlPairNumber * 2].CnSC |= edgeParam->currChanEdgeMode;
/* Wait till mode change is acknowledged */
while (!(base->CONTROLS[chnlPairNumber * 2].CnSC &
(TPM_CnSC_MSA_MASK | TPM_CnSC_MSB_MASK | TPM_CnSC_ELSA_MASK | TPM_CnSC_ELSB_MASK)))
{
}
/* Setup the edge detection from channel n+1 */
base->CONTROLS[(chnlPairNumber * 2) + 1].CnSC |= edgeParam->nextChanEdgeMode;
/* Wait till mode change is acknowledged */
while (!(base->CONTROLS[(chnlPairNumber * 2) + 1].CnSC &
(TPM_CnSC_MSA_MASK | TPM_CnSC_MSB_MASK | TPM_CnSC_ELSA_MASK | TPM_CnSC_ELSB_MASK)))
{
}
}
#endif
#if defined(FSL_FEATURE_TPM_HAS_QDCTRL) && FSL_FEATURE_TPM_HAS_QDCTRL
void TPM_SetupQuadDecode(TPM_Type *base,
const tpm_phase_params_t *phaseAParams,
const tpm_phase_params_t *phaseBParams,
tpm_quad_decode_mode_t quadMode)
{
assert(phaseAParams);
assert(phaseBParams);
assert(FSL_FEATURE_TPM_QDCTRL_HAS_EFFECTn(base));
base->CONTROLS[0].CnSC &= ~(TPM_CnSC_MSA_MASK | TPM_CnSC_MSB_MASK | TPM_CnSC_ELSA_MASK | TPM_CnSC_ELSB_MASK);
/* Wait till mode change to disable channel is acknowledged */
while ((base->CONTROLS[0].CnSC & (TPM_CnSC_MSA_MASK | TPM_CnSC_MSB_MASK | TPM_CnSC_ELSA_MASK | TPM_CnSC_ELSB_MASK)))
{
}
uint32_t reg;
/* Set Phase A filter value */
reg = base->FILTER;
reg &= ~(TPM_FILTER_CH0FVAL_MASK);
reg |= TPM_FILTER_CH0FVAL(phaseAParams->phaseFilterVal);
base->FILTER = reg;
#if defined(FSL_FEATURE_TPM_HAS_POL) && FSL_FEATURE_TPM_HAS_POL
/* Set Phase A polarity */
if (phaseAParams->phasePolarity)
{
base->POL |= TPM_POL_POL0_MASK;
}
else
{
base->POL &= ~TPM_POL_POL0_MASK;
}
#endif
base->CONTROLS[1].CnSC &= ~(TPM_CnSC_MSA_MASK | TPM_CnSC_MSB_MASK | TPM_CnSC_ELSA_MASK | TPM_CnSC_ELSB_MASK);
/* Wait till mode change to disable channel is acknowledged */
while ((base->CONTROLS[1].CnSC & (TPM_CnSC_MSA_MASK | TPM_CnSC_MSB_MASK | TPM_CnSC_ELSA_MASK | TPM_CnSC_ELSB_MASK)))
{
}
/* Set Phase B filter value */
reg = base->FILTER;
reg &= ~(TPM_FILTER_CH1FVAL_MASK);
reg |= TPM_FILTER_CH1FVAL(phaseBParams->phaseFilterVal);
base->FILTER = reg;
#if defined(FSL_FEATURE_TPM_HAS_POL) && FSL_FEATURE_TPM_HAS_POL
/* Set Phase B polarity */
if (phaseBParams->phasePolarity)
{
base->POL |= TPM_POL_POL1_MASK;
}
else
{
base->POL &= ~TPM_POL_POL1_MASK;
}
#endif
/* Set Quadrature mode */
reg = base->QDCTRL;
reg &= ~(TPM_QDCTRL_QUADMODE_MASK);
reg |= TPM_QDCTRL_QUADMODE(quadMode);
base->QDCTRL = reg;
/* Enable Quad decode */
base->QDCTRL |= TPM_QDCTRL_QUADEN_MASK;
}
#endif
void TPM_EnableInterrupts(TPM_Type *base, uint32_t mask)
{
uint32_t chnlInterrupts = (mask & 0xFF);
uint8_t chnlNumber = 0;
/* Enable the timer overflow interrupt */
if (mask & kTPM_TimeOverflowInterruptEnable)
{
base->SC |= TPM_SC_TOIE_MASK;
}
/* Enable the channel interrupts */
while (chnlInterrupts)
{
if (chnlInterrupts & 0x1)
{
base->CONTROLS[chnlNumber].CnSC |= TPM_CnSC_CHIE_MASK;
}
chnlNumber++;
chnlInterrupts = chnlInterrupts >> 1U;
}
}
void TPM_DisableInterrupts(TPM_Type *base, uint32_t mask)
{
uint32_t chnlInterrupts = (mask & 0xFF);
uint8_t chnlNumber = 0;
/* Disable the timer overflow interrupt */
if (mask & kTPM_TimeOverflowInterruptEnable)
{
base->SC &= ~TPM_SC_TOIE_MASK;
}
/* Disable the channel interrupts */
while (chnlInterrupts)
{
if (chnlInterrupts & 0x1)
{
base->CONTROLS[chnlNumber].CnSC &= ~TPM_CnSC_CHIE_MASK;
}
chnlNumber++;
chnlInterrupts = chnlInterrupts >> 1U;
}
}
uint32_t TPM_GetEnabledInterrupts(TPM_Type *base)
{
uint32_t enabledInterrupts = 0;
int8_t chnlCount = FSL_FEATURE_TPM_CHANNEL_COUNTn(base);
/* The CHANNEL_COUNT macro returns -1 if it cannot match the TPM instance */
assert(chnlCount != -1);
/* Check if timer overflow interrupt is enabled */
if (base->SC & TPM_SC_TOIE_MASK)
{
enabledInterrupts |= kTPM_TimeOverflowInterruptEnable;
}
/* Check if the channel interrupts are enabled */
while (chnlCount > 0)
{
chnlCount--;
if (base->CONTROLS[chnlCount].CnSC & TPM_CnSC_CHIE_MASK)
{
enabledInterrupts |= (1U << chnlCount);
}
}
return enabledInterrupts;
}

View File

@ -0,0 +1,607 @@
/*
* Copyright (c) 2015, Freescale Semiconductor, Inc.
* Copyright 2016-2017 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef _FSL_TPM_H_
#define _FSL_TPM_H_
#include "fsl_common.h"
/*!
* @addtogroup tpm
* @{
*/
/*******************************************************************************
* Definitions
******************************************************************************/
/*! @name Driver version */
/*@{*/
#define FSL_TPM_DRIVER_VERSION (MAKE_VERSION(2, 0, 2)) /*!< Version 2.0.2 */
/*@}*/
/*!
* @brief List of TPM channels.
* @note Actual number of available channels is SoC dependent
*/
typedef enum _tpm_chnl
{
kTPM_Chnl_0 = 0U, /*!< TPM channel number 0*/
kTPM_Chnl_1, /*!< TPM channel number 1 */
kTPM_Chnl_2, /*!< TPM channel number 2 */
kTPM_Chnl_3, /*!< TPM channel number 3 */
kTPM_Chnl_4, /*!< TPM channel number 4 */
kTPM_Chnl_5, /*!< TPM channel number 5 */
kTPM_Chnl_6, /*!< TPM channel number 6 */
kTPM_Chnl_7 /*!< TPM channel number 7 */
} tpm_chnl_t;
/*! @brief TPM PWM operation modes */
typedef enum _tpm_pwm_mode
{
kTPM_EdgeAlignedPwm = 0U, /*!< Edge aligned PWM */
kTPM_CenterAlignedPwm, /*!< Center aligned PWM */
#if defined(FSL_FEATURE_TPM_HAS_COMBINE) && FSL_FEATURE_TPM_HAS_COMBINE
kTPM_CombinedPwm /*!< Combined PWM */
#endif
} tpm_pwm_mode_t;
/*! @brief TPM PWM output pulse mode: high-true, low-true or no output */
typedef enum _tpm_pwm_level_select
{
kTPM_NoPwmSignal = 0U, /*!< No PWM output on pin */
kTPM_LowTrue, /*!< Low true pulses */
kTPM_HighTrue /*!< High true pulses */
} tpm_pwm_level_select_t;
/*! @brief Options to configure a TPM channel's PWM signal */
typedef struct _tpm_chnl_pwm_signal_param
{
tpm_chnl_t chnlNumber; /*!< TPM channel to configure.
In combined mode (available in some SoC's, this represents the
channel pair number */
tpm_pwm_level_select_t level; /*!< PWM output active level select */
uint8_t dutyCyclePercent; /*!< PWM pulse width, value should be between 0 to 100
0=inactive signal(0% duty cycle)...
100=always active signal (100% duty cycle)*/
#if defined(FSL_FEATURE_TPM_HAS_COMBINE) && FSL_FEATURE_TPM_HAS_COMBINE
uint8_t firstEdgeDelayPercent; /*!< Used only in combined PWM mode to generate asymmetrical PWM.
Specifies the delay to the first edge in a PWM period.
If unsure, leave as 0; Should be specified as
percentage of the PWM period */
#endif
} tpm_chnl_pwm_signal_param_t;
/*!
* @brief Trigger options available.
*
* This is used for both internal & external trigger sources (external option available in certain SoC's)
*
* @note The actual trigger options available is SoC-specific.
*/
typedef enum _tpm_trigger_select
{
kTPM_Trigger_Select_0 = 0U,
kTPM_Trigger_Select_1,
kTPM_Trigger_Select_2,
kTPM_Trigger_Select_3,
kTPM_Trigger_Select_4,
kTPM_Trigger_Select_5,
kTPM_Trigger_Select_6,
kTPM_Trigger_Select_7,
kTPM_Trigger_Select_8,
kTPM_Trigger_Select_9,
kTPM_Trigger_Select_10,
kTPM_Trigger_Select_11,
kTPM_Trigger_Select_12,
kTPM_Trigger_Select_13,
kTPM_Trigger_Select_14,
kTPM_Trigger_Select_15
} tpm_trigger_select_t;
#if defined(FSL_FEATURE_TPM_HAS_EXTERNAL_TRIGGER_SELECTION) && FSL_FEATURE_TPM_HAS_EXTERNAL_TRIGGER_SELECTION
/*!
* @brief Trigger source options available
*
* @note This selection is available only on some SoC's. For SoC's without this selection, the only
* trigger source available is internal triger.
*/
typedef enum _tpm_trigger_source
{
kTPM_TriggerSource_External = 0U, /*!< Use external trigger input */
kTPM_TriggerSource_Internal /*!< Use internal trigger */
} tpm_trigger_source_t;
#endif
/*! @brief TPM output compare modes */
typedef enum _tpm_output_compare_mode
{
kTPM_NoOutputSignal = (1U << TPM_CnSC_MSA_SHIFT), /*!< No channel output when counter reaches CnV */
kTPM_ToggleOnMatch = ((1U << TPM_CnSC_MSA_SHIFT) | (1U << TPM_CnSC_ELSA_SHIFT)), /*!< Toggle output */
kTPM_ClearOnMatch = ((1U << TPM_CnSC_MSA_SHIFT) | (2U << TPM_CnSC_ELSA_SHIFT)), /*!< Clear output */
kTPM_SetOnMatch = ((1U << TPM_CnSC_MSA_SHIFT) | (3U << TPM_CnSC_ELSA_SHIFT)), /*!< Set output */
kTPM_HighPulseOutput = ((3U << TPM_CnSC_MSA_SHIFT) | (1U << TPM_CnSC_ELSA_SHIFT)), /*!< Pulse output high */
kTPM_LowPulseOutput = ((3U << TPM_CnSC_MSA_SHIFT) | (2U << TPM_CnSC_ELSA_SHIFT)) /*!< Pulse output low */
} tpm_output_compare_mode_t;
/*! @brief TPM input capture edge */
typedef enum _tpm_input_capture_edge
{
kTPM_RisingEdge = (1U << TPM_CnSC_ELSA_SHIFT), /*!< Capture on rising edge only */
kTPM_FallingEdge = (2U << TPM_CnSC_ELSA_SHIFT), /*!< Capture on falling edge only */
kTPM_RiseAndFallEdge = (3U << TPM_CnSC_ELSA_SHIFT) /*!< Capture on rising or falling edge */
} tpm_input_capture_edge_t;
#if defined(FSL_FEATURE_TPM_HAS_COMBINE) && FSL_FEATURE_TPM_HAS_COMBINE
/*!
* @brief TPM dual edge capture parameters
*
* @note This mode is available only on some SoC's.
*/
typedef struct _tpm_dual_edge_capture_param
{
bool enableSwap; /*!< true: Use channel n+1 input, channel n input is ignored;
false: Use channel n input, channel n+1 input is ignored */
tpm_input_capture_edge_t currChanEdgeMode; /*!< Input capture edge select for channel n */
tpm_input_capture_edge_t nextChanEdgeMode; /*!< Input capture edge select for channel n+1 */
} tpm_dual_edge_capture_param_t;
#endif
#if defined(FSL_FEATURE_TPM_HAS_QDCTRL) && FSL_FEATURE_TPM_HAS_QDCTRL
/*!
* @brief TPM quadrature decode modes
*
* @note This mode is available only on some SoC's.
*/
typedef enum _tpm_quad_decode_mode
{
kTPM_QuadPhaseEncode = 0U, /*!< Phase A and Phase B encoding mode */
kTPM_QuadCountAndDir /*!< Count and direction encoding mode */
} tpm_quad_decode_mode_t;
/*! @brief TPM quadrature phase polarities */
typedef enum _tpm_phase_polarity
{
kTPM_QuadPhaseNormal = 0U, /*!< Phase input signal is not inverted */
kTPM_QuadPhaseInvert /*!< Phase input signal is inverted */
} tpm_phase_polarity_t;
/*! @brief TPM quadrature decode phase parameters */
typedef struct _tpm_phase_param
{
uint32_t phaseFilterVal; /*!< Filter value, filter is disabled when the value is zero */
tpm_phase_polarity_t phasePolarity; /*!< Phase polarity */
} tpm_phase_params_t;
#endif
/*! @brief TPM clock source selection*/
typedef enum _tpm_clock_source
{
kTPM_SystemClock = 1U, /*!< System clock */
kTPM_ExternalClock /*!< External clock */
} tpm_clock_source_t;
/*! @brief TPM prescale value selection for the clock source*/
typedef enum _tpm_clock_prescale
{
kTPM_Prescale_Divide_1 = 0U, /*!< Divide by 1 */
kTPM_Prescale_Divide_2, /*!< Divide by 2 */
kTPM_Prescale_Divide_4, /*!< Divide by 4 */
kTPM_Prescale_Divide_8, /*!< Divide by 8 */
kTPM_Prescale_Divide_16, /*!< Divide by 16 */
kTPM_Prescale_Divide_32, /*!< Divide by 32 */
kTPM_Prescale_Divide_64, /*!< Divide by 64 */
kTPM_Prescale_Divide_128 /*!< Divide by 128 */
} tpm_clock_prescale_t;
/*!
* @brief TPM config structure
*
* This structure holds the configuration settings for the TPM peripheral. To initialize this
* structure to reasonable defaults, call the TPM_GetDefaultConfig() function and pass a
* pointer to your config structure instance.
*
* The config struct can be made const so it resides in flash
*/
typedef struct _tpm_config
{
tpm_clock_prescale_t prescale; /*!< Select TPM clock prescale value */
bool useGlobalTimeBase; /*!< true: Use of an external global time base is enabled;
false: disabled */
tpm_trigger_select_t triggerSelect; /*!< Input trigger to use for controlling the counter operation */
#if defined(FSL_FEATURE_TPM_HAS_EXTERNAL_TRIGGER_SELECTION) && FSL_FEATURE_TPM_HAS_EXTERNAL_TRIGGER_SELECTION
tpm_trigger_source_t triggerSource; /*!< Decides if we use external or internal trigger. */
#endif
bool enableDoze; /*!< true: TPM counter is paused in doze mode;
false: TPM counter continues in doze mode */
bool enableDebugMode; /*!< true: TPM counter continues in debug mode;
false: TPM counter is paused in debug mode */
bool enableReloadOnTrigger; /*!< true: TPM counter is reloaded on trigger;
false: TPM counter not reloaded */
bool enableStopOnOverflow; /*!< true: TPM counter stops after overflow;
false: TPM counter continues running after overflow */
bool enableStartOnTrigger; /*!< true: TPM counter only starts when a trigger is detected;
false: TPM counter starts immediately */
#if defined(FSL_FEATURE_TPM_HAS_PAUSE_COUNTER_ON_TRIGGER) && FSL_FEATURE_TPM_HAS_PAUSE_COUNTER_ON_TRIGGER
bool enablePauseOnTrigger; /*!< true: TPM counter will pause while trigger remains asserted;
false: TPM counter continues running */
#endif
} tpm_config_t;
/*! @brief List of TPM interrupts */
typedef enum _tpm_interrupt_enable
{
kTPM_Chnl0InterruptEnable = (1U << 0), /*!< Channel 0 interrupt.*/
kTPM_Chnl1InterruptEnable = (1U << 1), /*!< Channel 1 interrupt.*/
kTPM_Chnl2InterruptEnable = (1U << 2), /*!< Channel 2 interrupt.*/
kTPM_Chnl3InterruptEnable = (1U << 3), /*!< Channel 3 interrupt.*/
kTPM_Chnl4InterruptEnable = (1U << 4), /*!< Channel 4 interrupt.*/
kTPM_Chnl5InterruptEnable = (1U << 5), /*!< Channel 5 interrupt.*/
kTPM_Chnl6InterruptEnable = (1U << 6), /*!< Channel 6 interrupt.*/
kTPM_Chnl7InterruptEnable = (1U << 7), /*!< Channel 7 interrupt.*/
kTPM_TimeOverflowInterruptEnable = (1U << 8) /*!< Time overflow interrupt.*/
} tpm_interrupt_enable_t;
/*! @brief List of TPM flags */
typedef enum _tpm_status_flags
{
kTPM_Chnl0Flag = (1U << 0), /*!< Channel 0 flag */
kTPM_Chnl1Flag = (1U << 1), /*!< Channel 1 flag */
kTPM_Chnl2Flag = (1U << 2), /*!< Channel 2 flag */
kTPM_Chnl3Flag = (1U << 3), /*!< Channel 3 flag */
kTPM_Chnl4Flag = (1U << 4), /*!< Channel 4 flag */
kTPM_Chnl5Flag = (1U << 5), /*!< Channel 5 flag */
kTPM_Chnl6Flag = (1U << 6), /*!< Channel 6 flag */
kTPM_Chnl7Flag = (1U << 7), /*!< Channel 7 flag */
kTPM_TimeOverflowFlag = (1U << 8) /*!< Time overflow flag */
} tpm_status_flags_t;
/*******************************************************************************
* API
******************************************************************************/
#if defined(__cplusplus)
extern "C" {
#endif
/*!
* @name Initialization and deinitialization
* @{
*/
/*!
* @brief Ungates the TPM clock and configures the peripheral for basic operation.
*
* @note This API should be called at the beginning of the application using the TPM driver.
*
* @param base TPM peripheral base address
* @param config Pointer to user's TPM config structure.
*/
void TPM_Init(TPM_Type *base, const tpm_config_t *config);
/*!
* @brief Stops the counter and gates the TPM clock
*
* @param base TPM peripheral base address
*/
void TPM_Deinit(TPM_Type *base);
/*!
* @brief Fill in the TPM config struct with the default settings
*
* The default values are:
* @code
* config->prescale = kTPM_Prescale_Divide_1;
* config->useGlobalTimeBase = false;
* config->dozeEnable = false;
* config->dbgMode = false;
* config->enableReloadOnTrigger = false;
* config->enableStopOnOverflow = false;
* config->enableStartOnTrigger = false;
*#if FSL_FEATURE_TPM_HAS_PAUSE_COUNTER_ON_TRIGGER
* config->enablePauseOnTrigger = false;
*#endif
* config->triggerSelect = kTPM_Trigger_Select_0;
*#if FSL_FEATURE_TPM_HAS_EXTERNAL_TRIGGER_SELECTION
* config->triggerSource = kTPM_TriggerSource_External;
*#endif
* @endcode
* @param config Pointer to user's TPM config structure.
*/
void TPM_GetDefaultConfig(tpm_config_t *config);
/*! @}*/
/*!
* @name Channel mode operations
* @{
*/
/*!
* @brief Configures the PWM signal parameters
*
* User calls this function to configure the PWM signals period, mode, dutycycle and edge. Use this
* function to configure all the TPM channels that will be used to output a PWM signal
*
* @param base TPM peripheral base address
* @param chnlParams Array of PWM channel parameters to configure the channel(s)
* @param numOfChnls Number of channels to configure, this should be the size of the array passed in
* @param mode PWM operation mode, options available in enumeration ::tpm_pwm_mode_t
* @param pwmFreq_Hz PWM signal frequency in Hz
* @param srcClock_Hz TPM counter clock in Hz
*
* @return kStatus_Success if the PWM setup was successful,
* kStatus_Error on failure
*/
status_t TPM_SetupPwm(TPM_Type *base,
const tpm_chnl_pwm_signal_param_t *chnlParams,
uint8_t numOfChnls,
tpm_pwm_mode_t mode,
uint32_t pwmFreq_Hz,
uint32_t srcClock_Hz);
/*!
* @brief Update the duty cycle of an active PWM signal
*
* @param base TPM peripheral base address
* @param chnlNumber The channel number. In combined mode, this represents
* the channel pair number
* @param currentPwmMode The current PWM mode set during PWM setup
* @param dutyCyclePercent New PWM pulse width, value should be between 0 to 100
* 0=inactive signal(0% duty cycle)...
* 100=active signal (100% duty cycle)
*/
void TPM_UpdatePwmDutycycle(TPM_Type *base,
tpm_chnl_t chnlNumber,
tpm_pwm_mode_t currentPwmMode,
uint8_t dutyCyclePercent);
/*!
* @brief Update the edge level selection for a channel
*
* @param base TPM peripheral base address
* @param chnlNumber The channel number
* @param level The level to be set to the ELSnB:ELSnA field; valid values are 00, 01, 10, 11.
* See the appropriate SoC reference manual for details about this field.
*/
void TPM_UpdateChnlEdgeLevelSelect(TPM_Type *base, tpm_chnl_t chnlNumber, uint8_t level);
/*!
* @brief Enables capturing an input signal on the channel using the function parameters.
*
* When the edge specified in the captureMode argument occurs on the channel, the TPM counter is captured into
* the CnV register. The user has to read the CnV register separately to get this value.
*
* @param base TPM peripheral base address
* @param chnlNumber The channel number
* @param captureMode Specifies which edge to capture
*/
void TPM_SetupInputCapture(TPM_Type *base, tpm_chnl_t chnlNumber, tpm_input_capture_edge_t captureMode);
/*!
* @brief Configures the TPM to generate timed pulses.
*
* When the TPM counter matches the value of compareVal argument (this is written into CnV reg), the channel
* output is changed based on what is specified in the compareMode argument.
*
* @param base TPM peripheral base address
* @param chnlNumber The channel number
* @param compareMode Action to take on the channel output when the compare condition is met
* @param compareValue Value to be programmed in the CnV register.
*/
void TPM_SetupOutputCompare(TPM_Type *base,
tpm_chnl_t chnlNumber,
tpm_output_compare_mode_t compareMode,
uint32_t compareValue);
#if defined(FSL_FEATURE_TPM_HAS_COMBINE) && FSL_FEATURE_TPM_HAS_COMBINE
/*!
* @brief Configures the dual edge capture mode of the TPM.
*
* This function allows to measure a pulse width of the signal on the input of channel of a
* channel pair. The filter function is disabled if the filterVal argument passed is zero.
*
* @param base TPM peripheral base address
* @param chnlPairNumber The TPM channel pair number; options are 0, 1, 2, 3
* @param edgeParam Sets up the dual edge capture function
* @param filterValue Filter value, specify 0 to disable filter.
*/
void TPM_SetupDualEdgeCapture(TPM_Type *base,
tpm_chnl_t chnlPairNumber,
const tpm_dual_edge_capture_param_t *edgeParam,
uint32_t filterValue);
#endif
#if defined(FSL_FEATURE_TPM_HAS_QDCTRL) && FSL_FEATURE_TPM_HAS_QDCTRL
/*!
* @brief Configures the parameters and activates the quadrature decode mode.
*
* @param base TPM peripheral base address
* @param phaseAParams Phase A configuration parameters
* @param phaseBParams Phase B configuration parameters
* @param quadMode Selects encoding mode used in quadrature decoder mode
*/
void TPM_SetupQuadDecode(TPM_Type *base,
const tpm_phase_params_t *phaseAParams,
const tpm_phase_params_t *phaseBParams,
tpm_quad_decode_mode_t quadMode);
#endif
/*! @}*/
/*!
* @name Interrupt Interface
* @{
*/
/*!
* @brief Enables the selected TPM interrupts.
*
* @param base TPM peripheral base address
* @param mask The interrupts to enable. This is a logical OR of members of the
* enumeration ::tpm_interrupt_enable_t
*/
void TPM_EnableInterrupts(TPM_Type *base, uint32_t mask);
/*!
* @brief Disables the selected TPM interrupts.
*
* @param base TPM peripheral base address
* @param mask The interrupts to disable. This is a logical OR of members of the
* enumeration ::tpm_interrupt_enable_t
*/
void TPM_DisableInterrupts(TPM_Type *base, uint32_t mask);
/*!
* @brief Gets the enabled TPM interrupts.
*
* @param base TPM peripheral base address
*
* @return The enabled interrupts. This is the logical OR of members of the
* enumeration ::tpm_interrupt_enable_t
*/
uint32_t TPM_GetEnabledInterrupts(TPM_Type *base);
/*! @}*/
/*!
* @name Status Interface
* @{
*/
/*!
* @brief Gets the TPM status flags
*
* @param base TPM peripheral base address
*
* @return The status flags. This is the logical OR of members of the
* enumeration ::tpm_status_flags_t
*/
static inline uint32_t TPM_GetStatusFlags(TPM_Type *base)
{
return base->STATUS;
}
/*!
* @brief Clears the TPM status flags
*
* @param base TPM peripheral base address
* @param mask The status flags to clear. This is a logical OR of members of the
* enumeration ::tpm_status_flags_t
*/
static inline void TPM_ClearStatusFlags(TPM_Type *base, uint32_t mask)
{
/* Clear the status flags */
base->STATUS = mask;
}
/*! @}*/
/*!
* @name Read and write the timer period
* @{
*/
/*!
* @brief Sets the timer period in units of ticks.
*
* Timers counts from 0 until it equals the count value set here. The count value is written to
* the MOD register.
*
* @note
* 1. This API allows the user to use the TPM module as a timer. Do not mix usage
* of this API with TPM's PWM setup API's.
* 2. Call the utility macros provided in the fsl_common.h to convert usec or msec to ticks.
*
* @param base TPM peripheral base address
* @param ticks A timer period in units of ticks, which should be equal or greater than 1.
*/
static inline void TPM_SetTimerPeriod(TPM_Type *base, uint32_t ticks)
{
base->MOD = ticks;
}
/*!
* @brief Reads the current timer counting value.
*
* This function returns the real-time timer counting value in a range from 0 to a
* timer period.
*
* @note Call the utility macros provided in the fsl_common.h to convert ticks to usec or msec.
*
* @param base TPM peripheral base address
*
* @return The current counter value in ticks
*/
static inline uint32_t TPM_GetCurrentTimerCount(TPM_Type *base)
{
return (uint32_t)((base->CNT & TPM_CNT_COUNT_MASK) >> TPM_CNT_COUNT_SHIFT);
}
/*!
* @name Timer Start and Stop
* @{
*/
/*!
* @brief Starts the TPM counter.
*
*
* @param base TPM peripheral base address
* @param clockSource TPM clock source; once clock source is set the counter will start running
*/
static inline void TPM_StartTimer(TPM_Type *base, tpm_clock_source_t clockSource)
{
uint32_t reg = base->SC;
reg &= ~(TPM_SC_CMOD_MASK);
reg |= TPM_SC_CMOD(clockSource);
base->SC = reg;
}
/*!
* @brief Stops the TPM counter.
*
* @param base TPM peripheral base address
*/
static inline void TPM_StopTimer(TPM_Type *base)
{
/* Set clock source to none to disable counter */
base->SC &= ~(TPM_SC_CMOD_MASK);
/* Wait till this reads as zero acknowledging the counter is disabled */
while (base->SC & TPM_SC_CMOD_MASK)
{
}
}
/*! @}*/
#if defined(FSL_FEATURE_TPM_HAS_GLOBAL) && FSL_FEATURE_TPM_HAS_GLOBAL
/*!
* @brief Performs a software reset on the TPM module.
*
* Reset all internal logic and registers, except the Global Register. Remains set until cleared by software..
*
* @note TPM software reset is available on certain SoC's only
*
* @param base TPM peripheral base address
*/
static inline void TPM_Reset(TPM_Type *base)
{
base->GLOBAL |= TPM_GLOBAL_RST_MASK;
base->GLOBAL &= ~TPM_GLOBAL_RST_MASK;
}
#endif
#if defined(__cplusplus)
}
#endif
/*! @}*/
#endif /* _FSL_TPM_H_ */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,217 @@
/*
* Copyright (c) 2015-2016, Freescale Semiconductor, Inc.
* Copyright 2016-2017 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef _FSL_TRNG_DRIVER_H_
#define _FSL_TRNG_DRIVER_H_
#include "fsl_common.h"
#if defined(FSL_FEATURE_SOC_TRNG_COUNT) && FSL_FEATURE_SOC_TRNG_COUNT
/*!
* @addtogroup trng
* @{
*/
/*******************************************************************************
* Definitions
*******************************************************************************/
/*! @name Driver version */
/*@{*/
/*! @brief TRNG driver version 2.0.1.
*
* Current version: 2.0.1
*
* Change log:
* - Version 2.0.1
* - add support for KL8x and KL28Z
* - update default OSCDIV for K81 to divide by 2
*/
#define FSL_TRNG_DRIVER_VERSION (MAKE_VERSION(2, 0, 1))
/*@}*/
/*! @brief TRNG sample mode. Used by trng_config_t. */
typedef enum _trng_sample_mode
{
kTRNG_SampleModeVonNeumann = 0U, /*!< Use von Neumann data in both Entropy shifter and Statistical Checker. */
kTRNG_SampleModeRaw = 1U, /*!< Use raw data into both Entropy shifter and Statistical Checker. */
kTRNG_SampleModeVonNeumannRaw =
2U /*!< Use von Neumann data in Entropy shifter. Use raw data into Statistical Checker. */
} trng_sample_mode_t;
/*! @brief TRNG clock mode. Used by trng_config_t. */
typedef enum _trng_clock_mode
{
kTRNG_ClockModeRingOscillator = 0U, /*!< Ring oscillator is used to operate the TRNG (default). */
kTRNG_ClockModeSystem = 1U /*!< System clock is used to operate the TRNG. This is for test use only, and
indeterminate results may occur. */
} trng_clock_mode_t;
/*! @brief TRNG ring oscillator divide. Used by trng_config_t. */
typedef enum _trng_ring_osc_div
{
kTRNG_RingOscDiv0 = 0U, /*!< Ring oscillator with no divide */
kTRNG_RingOscDiv2 = 1U, /*!< Ring oscillator divided-by-2. */
kTRNG_RingOscDiv4 = 2U, /*!< Ring oscillator divided-by-4. */
kTRNG_RingOscDiv8 = 3U /*!< Ring oscillator divided-by-8. */
} trng_ring_osc_div_t;
/*! @brief Data structure for definition of statistical check limits. Used by trng_config_t. */
typedef struct _trng_statistical_check_limit
{
uint32_t maximum; /*!< Maximum limit.*/
uint32_t minimum; /*!< Minimum limit.*/
} trng_statistical_check_limit_t;
/*!
* @brief Data structure for the TRNG initialization
*
* This structure initializes the TRNG by calling the TRNG_Init() function.
* It contains all TRNG configurations.
*/
typedef struct _trng_user_config
{
bool lock; /*!< @brief Disable programmability of TRNG registers. */
trng_clock_mode_t clockMode; /*!< @brief Clock mode used to operate TRNG.*/
trng_ring_osc_div_t ringOscDiv; /*!< @brief Ring oscillator divide used by TRNG. */
trng_sample_mode_t sampleMode; /*!< @brief Sample mode of the TRNG ring oscillator. */
/* Seed Control*/
uint16_t
entropyDelay; /*!< @brief Entropy Delay. Defines the length (in system clocks) of each Entropy sample taken. */
uint16_t sampleSize; /*!< @brief Sample Size. Defines the total number of Entropy samples that will be taken during
Entropy generation. */
uint16_t
sparseBitLimit; /*!< @brief Sparse Bit Limit which defines the maximum number of
* consecutive samples that may be discarded before an error is generated.
* This limit is used only for during von Neumann sampling (enabled by TRNG_HAL_SetSampleMode()).
* Samples are discarded if two consecutive raw samples are both 0 or both 1. If
* this discarding occurs for a long period of time, it indicates that there is
* insufficient Entropy. */
/* Statistical Check Parameters.*/
uint8_t retryCount; /*!< @brief Retry count. It defines the number of times a statistical check may fails
* during the TRNG Entropy Generation before generating an error. */
uint8_t longRunMaxLimit; /*!< @brief Largest allowable number of consecutive samples of all 1, or all 0,
* that is allowed during the Entropy generation. */
trng_statistical_check_limit_t
monobitLimit; /*!< @brief Maximum and minimum limits for statistical check of number of ones/zero detected
during entropy generation. */
trng_statistical_check_limit_t
runBit1Limit; /*!< @brief Maximum and minimum limits for statistical check of number of runs of length 1
detected during entropy generation. */
trng_statistical_check_limit_t
runBit2Limit; /*!< @brief Maximum and minimum limits for statistical check of number of runs of length 2
detected during entropy generation. */
trng_statistical_check_limit_t
runBit3Limit; /*!< @brief Maximum and minimum limits for statistical check of number of runs of length 3
detected during entropy generation. */
trng_statistical_check_limit_t
runBit4Limit; /*!< @brief Maximum and minimum limits for statistical check of number of runs of length 4
detected during entropy generation. */
trng_statistical_check_limit_t
runBit5Limit; /*!< @brief Maximum and minimum limits for statistical check of number of runs of length 5
detected during entropy generation. */
trng_statistical_check_limit_t runBit6PlusLimit; /*!< @brief Maximum and minimum limits for statistical check of
number of runs of length 6 or more detected during entropy
generation. */
trng_statistical_check_limit_t
pokerLimit; /*!< @brief Maximum and minimum limits for statistical check of "Poker Test". */
trng_statistical_check_limit_t
frequencyCountLimit; /*!< @brief Maximum and minimum limits for statistical check of entropy sample frequency
count. */
} trng_config_t;
/*******************************************************************************
* API
*******************************************************************************/
#if defined(__cplusplus)
extern "C" {
#endif
/*!
* @brief Initializes the user configuration structure to default values.
*
* This function initializes the configuration structure to default values. The default
* values are as follows.
* @code
* user_config->lock = 0;
* user_config->clockMode = kTRNG_ClockModeRingOscillator;
* user_config->ringOscDiv = kTRNG_RingOscDiv0; Or to other kTRNG_RingOscDiv[2|8] depending on the platform.
* user_config->sampleMode = kTRNG_SampleModeRaw;
* user_config->entropyDelay = 3200;
* user_config->sampleSize = 2500;
* user_config->sparseBitLimit = TRNG_USER_CONFIG_DEFAULT_SPARSE_BIT_LIMIT;
* user_config->retryCount = 63;
* user_config->longRunMaxLimit = 34;
* user_config->monobitLimit.maximum = 1384;
* user_config->monobitLimit.minimum = 1116;
* user_config->runBit1Limit.maximum = 405;
* user_config->runBit1Limit.minimum = 227;
* user_config->runBit2Limit.maximum = 220;
* user_config->runBit2Limit.minimum = 98;
* user_config->runBit3Limit.maximum = 125;
* user_config->runBit3Limit.minimum = 37;
* user_config->runBit4Limit.maximum = 75;
* user_config->runBit4Limit.minimum = 11;
* user_config->runBit5Limit.maximum = 47;
* user_config->runBit5Limit.minimum = 1;
* user_config->runBit6PlusLimit.maximum = 47;
* user_config->runBit6PlusLimit.minimum = 1;
* user_config->pokerLimit.maximum = 26912;
* user_config->pokerLimit.minimum = 24445;
* user_config->frequencyCountLimit.maximum = 0x3fffff;
* user_config->frequencyCountLimit.minimum = 1600;
* @endcode
*
* @param user_config User configuration structure.
* @return If successful, returns the kStatus_TRNG_Success. Otherwise, it returns an error.
*/
status_t TRNG_GetDefaultConfig(trng_config_t *userConfig);
/*!
* @brief Initializes the TRNG.
*
* This function initializes the TRNG.
* When called, the TRNG entropy generation starts immediately.
*
* @param base TRNG base address
* @param userConfig Pointer to the initialization configuration structure.
* @return If successful, returns the kStatus_TRNG_Success. Otherwise, it returns an error.
*/
status_t TRNG_Init(TRNG_Type *base, const trng_config_t *userConfig);
/*!
* @brief Shuts down the TRNG.
*
* This function shuts down the TRNG.
*
* @param base TRNG base address.
*/
void TRNG_Deinit(TRNG_Type *base);
/*!
* @brief Gets random data.
*
* This function gets random data from the TRNG.
*
* @param base TRNG base address.
* @param data Pointer address used to store random data.
* @param dataSize Size of the buffer pointed by the data parameter.
* @return random data
*/
status_t TRNG_GetRandomData(TRNG_Type *base, void *data, size_t dataSize);
#if defined(__cplusplus)
}
#endif
/*! @}*/
#endif /* FSL_FEATURE_SOC_TRNG_COUNT */
#endif /*_FSL_TRNG_H_*/

View File

@ -0,0 +1,79 @@
/*
* Copyright (c) 2015, Freescale Semiconductor, Inc.
* Copyright 2016-2017 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef _FSL_TSTMR_H_
#define _FSL_TSTMR_H_
#include "fsl_common.h"
/*!
* @addtogroup tstmr_driver
* @{
*/
/*******************************************************************************
* Definitions
******************************************************************************/
/*! @name Driver version */
/*@{*/
#define FSL_TSTMR_DRIVER_VERSION (MAKE_VERSION(2, 0, 0)) /*!< Version 2.0.0 */
/*@}*/
/*******************************************************************************
* API
******************************************************************************/
#if defined(__cplusplus)
extern "C" {
#endif
/*!
* @brief Reads the time stamp.
*
* This function reads the low and high registers and returns the 56-bit free running
* counter value. This can be read by software at any time to determine the software ticks.
*
* @param base TSTMR peripheral base address.
*
* @return The 56-bit time stamp value.
*/
static inline uint64_t TSTMR_ReadTimeStamp(TSTMR_Type* base)
{
return *(volatile uint64_t*)(base);
}
/*!
* @brief Delays for a specified number of microseconds.
*
* This function repeatedly reads the timestamp register and waits for the user-specified
* delay value.
*
* @param base TSTMR peripheral base address.
* @param delayInUs Delay value in microseconds.
*/
static inline void TSTMR_DelayUs(TSTMR_Type* base, uint32_t delayInUs)
{
uint64_t startTime = TSTMR_ReadTimeStamp(base);
#if defined(FSL_FEATURE_TSTMR_CLOCK_FREQUENCY_1MHZ) && FSL_FEATURE_TSTMR_CLOCK_FREQUENCY_1MHZ
while (TSTMR_ReadTimeStamp(base) - startTime < delayInUs)
#elif defined(FSL_FEATURE_TSTMR_CLOCK_FREQUENCY_8MHZ) && FSL_FEATURE_TSTMR_CLOCK_FREQUENCY_8MHZ
while (TSTMR_ReadTimeStamp(base) - startTime < 8 * delayInUs)
#else
assert(0);
#endif
{
}
}
#if defined(__cplusplus)
}
#endif
/*! @}*/
#endif /* _FSL_TSTMR_H_ */

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,73 @@
/*
* Copyright (c) 2015, Freescale Semiconductor, Inc.
* Copyright 2016-2017 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include "fsl_wdog32.h"
/*******************************************************************************
* Code
******************************************************************************/
void WDOG32_ClearStatusFlags(WDOG_Type *base, uint32_t mask)
{
if (mask & kWDOG32_InterruptFlag)
{
base->CS |= WDOG_CS_FLG_MASK;
}
}
void WDOG32_GetDefaultConfig(wdog32_config_t *config)
{
assert(config);
config->enableWdog32 = true;
config->clockSource = kWDOG32_ClockSource1;
config->prescaler = kWDOG32_ClockPrescalerDivide1;
config->workMode.enableWait = true;
config->workMode.enableStop = false;
config->workMode.enableDebug = false;
config->testMode = kWDOG32_TestModeDisabled;
config->enableUpdate = true;
config->enableInterrupt = false;
config->enableWindowMode = false;
config->windowValue = 0U;
config->timeoutValue = 0xFFFFU;
}
void WDOG32_Init(WDOG_Type *base, const wdog32_config_t *config)
{
assert(config);
uint32_t value = 0U;
uint32_t primaskValue = 0U;
value = WDOG_CS_EN(config->enableWdog32) | WDOG_CS_CLK(config->clockSource) | WDOG_CS_INT(config->enableInterrupt) |
WDOG_CS_WIN(config->enableWindowMode) | WDOG_CS_UPDATE(config->enableUpdate) |
WDOG_CS_DBG(config->workMode.enableDebug) | WDOG_CS_STOP(config->workMode.enableStop) |
WDOG_CS_WAIT(config->workMode.enableWait) | WDOG_CS_PRES(config->prescaler) | WDOG_CS_CMD32EN(true) |
WDOG_CS_TST(config->testMode);
/* Disable the global interrupts. Otherwise, an interrupt could effectively invalidate the unlock sequence
* and the WCT may expire. After the configuration finishes, re-enable the global interrupts. */
primaskValue = DisableGlobalIRQ();
WDOG32_Unlock(base);
base->WIN = config->windowValue;
base->TOVAL = config->timeoutValue;
base->CS = value;
EnableGlobalIRQ(primaskValue);
}
void WDOG32_Deinit(WDOG_Type *base)
{
uint32_t primaskValue = 0U;
/* Disable the global interrupts */
primaskValue = DisableGlobalIRQ();
WDOG32_Unlock(base);
WDOG32_Disable(base);
EnableGlobalIRQ(primaskValue);
}

View File

@ -0,0 +1,378 @@
/*
* Copyright (c) 2015, Freescale Semiconductor, Inc.
* Copyright 2016-2017 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef _FSL_WDOG32_H_
#define _FSL_WDOG32_H_
#include "fsl_common.h"
/*!
* @addtogroup wdog32
* @{
*/
/*******************************************************************************
* Definitions
*******************************************************************************/
/*! @name Unlock sequence */
/*@{*/
#define WDOG_FIRST_WORD_OF_UNLOCK (WDOG_UPDATE_KEY & 0xFFFFU) /*!< First word of unlock sequence */
#define WDOG_SECOND_WORD_OF_UNLOCK ((WDOG_UPDATE_KEY >> 16U)& 0xFFFFU) /*!< Second word of unlock sequence */
/*@}*/
/*! @name Refresh sequence */
/*@{*/
#define WDOG_FIRST_WORD_OF_REFRESH (WDOG_REFRESH_KEY & 0xFFFFU) /*!< First word of refresh sequence */
#define WDOG_SECOND_WORD_OF_REFRESH ((WDOG_REFRESH_KEY >> 16U)& 0xFFFFU) /*!< Second word of refresh sequence */
/*@}*/
/*! @name Driver version */
/*@{*/
/*! @brief WDOG32 driver version 2.0.0. */
#define FSL_WDOG32_DRIVER_VERSION (MAKE_VERSION(2, 0, 0))
/*@}*/
/*! @brief Describes WDOG32 clock source. */
typedef enum _wdog32_clock_source
{
kWDOG32_ClockSource0 = 0U, /*!< Clock source 0 */
kWDOG32_ClockSource1 = 1U, /*!< Clock source 1 */
kWDOG32_ClockSource2 = 2U, /*!< Clock source 2 */
kWDOG32_ClockSource3 = 3U, /*!< Clock source 3 */
} wdog32_clock_source_t;
/*! @brief Describes the selection of the clock prescaler. */
typedef enum _wdog32_clock_prescaler
{
kWDOG32_ClockPrescalerDivide1 = 0x0U, /*!< Divided by 1 */
kWDOG32_ClockPrescalerDivide256 = 0x1U, /*!< Divided by 256 */
} wdog32_clock_prescaler_t;
/*! @brief Defines WDOG32 work mode. */
typedef struct _wdog32_work_mode
{
bool enableWait; /*!< Enables or disables WDOG32 in wait mode */
bool enableStop; /*!< Enables or disables WDOG32 in stop mode */
bool enableDebug; /*!< Enables or disables WDOG32 in debug mode */
} wdog32_work_mode_t;
/*! @brief Describes WDOG32 test mode. */
typedef enum _wdog32_test_mode
{
kWDOG32_TestModeDisabled = 0U, /*!< Test Mode disabled */
kWDOG32_UserModeEnabled = 1U, /*!< User Mode enabled */
kWDOG32_LowByteTest = 2U, /*!< Test Mode enabled, only low byte is used */
kWDOG32_HighByteTest = 3U, /*!< Test Mode enabled, only high byte is used */
} wdog32_test_mode_t;
/*! @brief Describes WDOG32 configuration structure. */
typedef struct _wdog32_config
{
bool enableWdog32; /*!< Enables or disables WDOG32 */
wdog32_clock_source_t clockSource; /*!< Clock source select */
wdog32_clock_prescaler_t prescaler; /*!< Clock prescaler value */
wdog32_work_mode_t workMode; /*!< Configures WDOG32 work mode in debug stop and wait mode */
wdog32_test_mode_t testMode; /*!< Configures WDOG32 test mode */
bool enableUpdate; /*!< Update write-once register enable */
bool enableInterrupt; /*!< Enables or disables WDOG32 interrupt */
bool enableWindowMode; /*!< Enables or disables WDOG32 window mode */
uint16_t windowValue; /*!< Window value */
uint16_t timeoutValue; /*!< Timeout value */
} wdog32_config_t;
/*!
* @brief WDOG32 interrupt configuration structure.
*
* This structure contains the settings for all of the WDOG32 interrupt configurations.
*/
enum _wdog32_interrupt_enable_t
{
kWDOG32_InterruptEnable = WDOG_CS_INT_MASK, /*!< Interrupt is generated before forcing a reset */
};
/*!
* @brief WDOG32 status flags.
*
* This structure contains the WDOG32 status flags for use in the WDOG32 functions.
*/
enum _wdog32_status_flags_t
{
kWDOG32_RunningFlag = WDOG_CS_EN_MASK, /*!< Running flag, set when WDOG32 is enabled */
kWDOG32_InterruptFlag = WDOG_CS_FLG_MASK, /*!< Interrupt flag, set when interrupt occurs */
};
/*******************************************************************************
* API
*******************************************************************************/
#if defined(__cplusplus)
extern "C" {
#endif /* __cplusplus */
/*!
* @name WDOG32 Initialization and De-initialization
* @{
*/
/*!
* @brief Initializes the WDOG32 configuration structure.
*
* This function initializes the WDOG32 configuration structure to default values. The default
* values are:
* @code
* wdog32Config->enableWdog32 = true;
* wdog32Config->clockSource = kWDOG32_ClockSource1;
* wdog32Config->prescaler = kWDOG32_ClockPrescalerDivide1;
* wdog32Config->workMode.enableWait = true;
* wdog32Config->workMode.enableStop = false;
* wdog32Config->workMode.enableDebug = false;
* wdog32Config->testMode = kWDOG32_TestModeDisabled;
* wdog32Config->enableUpdate = true;
* wdog32Config->enableInterrupt = false;
* wdog32Config->enableWindowMode = false;
* wdog32Config->windowValue = 0U;
* wdog32Config->timeoutValue = 0xFFFFU;
* @endcode
*
* @param config Pointer to the WDOG32 configuration structure.
* @see wdog32_config_t
*/
void WDOG32_GetDefaultConfig(wdog32_config_t *config);
/*!
* @brief Initializes the WDOG32 module.
*
* This function initializes the WDOG32.
* To reconfigure the WDOG32 without forcing a reset first, enableUpdate must be set to true
* in the configuration.
*
* Example:
* @code
* wdog32_config_t config;
* WDOG32_GetDefaultConfig(&config);
* config.timeoutValue = 0x7ffU;
* config.enableUpdate = true;
* WDOG32_Init(wdog_base,&config);
* @endcode
*
* @param base WDOG32 peripheral base address.
* @param config The configuration of the WDOG32.
*/
void WDOG32_Init(WDOG_Type *base, const wdog32_config_t *config);
/*!
* @brief De-initializes the WDOG32 module.
*
* This function shuts down the WDOG32.
* Ensure that the WDOG_CS.UPDATE is 1, which means that the register update is enabled.
*
* @param base WDOG32 peripheral base address.
*/
void WDOG32_Deinit(WDOG_Type *base);
/* @} */
/*!
* @name WDOG32 functional Operation
* @{
*/
/*!
* @brief Enables the WDOG32 module.
*
* This function writes a value into the WDOG_CS register to enable the WDOG32.
* The WDOG_CS register is a write-once register. Ensure that the WCT window is still open and
* this register has not been written in this WCT while the function is called.
*
* @param base WDOG32 peripheral base address.
*/
static inline void WDOG32_Enable(WDOG_Type *base)
{
base->CS |= WDOG_CS_EN_MASK;
}
/*!
* @brief Disables the WDOG32 module.
*
* This function writes a value into the WDOG_CS register to disable the WDOG32.
* The WDOG_CS register is a write-once register. Ensure that the WCT window is still open and
* this register has not been written in this WCT while the function is called.
*
* @param base WDOG32 peripheral base address
*/
static inline void WDOG32_Disable(WDOG_Type *base)
{
base->CS &= ~WDOG_CS_EN_MASK;
}
/*!
* @brief Enables the WDOG32 interrupt.
*
* This function writes a value into the WDOG_CS register to enable the WDOG32 interrupt.
* The WDOG_CS register is a write-once register. Ensure that the WCT window is still open and
* this register has not been written in this WCT while the function is called.
*
* @param base WDOG32 peripheral base address.
* @param mask The interrupts to enable.
* The parameter can be a combination of the following source if defined:
* @arg kWDOG32_InterruptEnable
*/
static inline void WDOG32_EnableInterrupts(WDOG_Type *base, uint32_t mask)
{
base->CS |= mask;
}
/*!
* @brief Disables the WDOG32 interrupt.
*
* This function writes a value into the WDOG_CS register to disable the WDOG32 interrupt.
* The WDOG_CS register is a write-once register. Ensure that the WCT window is still open and
* this register has not been written in this WCT while the function is called.
*
* @param base WDOG32 peripheral base address.
* @param mask The interrupts to disabled.
* The parameter can be a combination of the following source if defined:
* @arg kWDOG32_InterruptEnable
*/
static inline void WDOG32_DisableInterrupts(WDOG_Type *base, uint32_t mask)
{
base->CS &= ~mask;
}
/*!
* @brief Gets the WDOG32 all status flags.
*
* This function gets all status flags.
*
* Example to get the running flag:
* @code
* uint32_t status;
* status = WDOG32_GetStatusFlags(wdog_base) & kWDOG32_RunningFlag;
* @endcode
* @param base WDOG32 peripheral base address
* @return State of the status flag: asserted (true) or not-asserted (false). @see _wdog32_status_flags_t
* - true: related status flag has been set.
* - false: related status flag is not set.
*/
static inline uint32_t WDOG32_GetStatusFlags(WDOG_Type *base)
{
return (base->CS & (WDOG_CS_EN_MASK | WDOG_CS_FLG_MASK));
}
/*!
* @brief Clears the WDOG32 flag.
*
* This function clears the WDOG32 status flag.
*
* Example to clear an interrupt flag:
* @code
* WDOG32_ClearStatusFlags(wdog_base,kWDOG32_InterruptFlag);
* @endcode
* @param base WDOG32 peripheral base address.
* @param mask The status flags to clear.
* The parameter can be any combination of the following values:
* @arg kWDOG32_InterruptFlag
*/
void WDOG32_ClearStatusFlags(WDOG_Type *base, uint32_t mask);
/*!
* @brief Sets the WDOG32 timeout value.
*
* This function writes a timeout value into the WDOG_TOVAL register.
* The WDOG_TOVAL register is a write-once register. Ensure that the WCT window is still open and
* this register has not been written in this WCT while the function is called.
*
* @param base WDOG32 peripheral base address
* @param timeoutCount WDOG32 timeout value, count of WDOG32 clock ticks.
*/
static inline void WDOG32_SetTimeoutValue(WDOG_Type *base, uint16_t timeoutCount)
{
base->TOVAL = timeoutCount;
}
/*!
* @brief Sets the WDOG32 window value.
*
* This function writes a window value into the WDOG_WIN register.
* The WDOG_WIN register is a write-once register. Ensure that the WCT window is still open and
* this register has not been written in this WCT while the function is called.
*
* @param base WDOG32 peripheral base address.
* @param windowValue WDOG32 window value.
*/
static inline void WDOG32_SetWindowValue(WDOG_Type *base, uint16_t windowValue)
{
base->WIN = windowValue;
}
/*!
* @brief Unlocks the WDOG32 register written.
*
* This function unlocks the WDOG32 register written.
*
* Before starting the unlock sequence and following the configuration, disable the global interrupts.
* Otherwise, an interrupt could effectively invalidate the unlock sequence and the WCT may expire.
* After the configuration finishes, re-enable the global interrupts.
*
* @param base WDOG32 peripheral base address
*/
static inline void WDOG32_Unlock(WDOG_Type *base)
{
if ((base->CS) & WDOG_CS_CMD32EN_MASK)
{
base->CNT = WDOG_UPDATE_KEY;
}
else
{
base->CNT = WDOG_FIRST_WORD_OF_UNLOCK;
base->CNT = WDOG_SECOND_WORD_OF_UNLOCK;
}
}
/*!
* @brief Refreshes the WDOG32 timer.
*
* This function feeds the WDOG32.
* This function should be called before the Watchdog timer is in timeout. Otherwise, a reset is asserted.
*
* @param base WDOG32 peripheral base address
*/
static inline void WDOG32_Refresh(WDOG_Type *base)
{
if ((base->CS) & WDOG_CS_CMD32EN_MASK)
{
base->CNT = WDOG_REFRESH_KEY;
}
else
{
base->CNT = WDOG_FIRST_WORD_OF_REFRESH;
base->CNT = WDOG_SECOND_WORD_OF_REFRESH;
}
}
/*!
* @brief Gets the WDOG32 counter value.
*
* This function gets the WDOG32 counter value.
*
* @param base WDOG32 peripheral base address.
* @return Current WDOG32 counter value.
*/
static inline uint16_t WDOG32_GetCounterValue(WDOG_Type *base)
{
return base->CNT;
}
/*@}*/
#if defined(__cplusplus)
}
#endif /* __cplusplus */
/*! @}*/
#endif /* _FSL_WDOG32_H_ */

View File

@ -0,0 +1,453 @@
/*
* Copyright (c) 2015, Freescale Semiconductor, Inc.
* Copyright 2016-2017 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include "fsl_xrdc.h"
/*******************************************************************************
* Definitions
******************************************************************************/
#define XRDC_DERR_W1_EST_VAL(w1) ((w1 & XRDC_DERR_W_EST_MASK) >> XRDC_DERR_W_EST_SHIFT)
#define XRDC_DERR_W1_EPORT_VAL(w1) ((w1 & XRDC_DERR_W_EPORT_MASK) >> XRDC_DERR_W_EPORT_SHIFT)
#define XRDC_DERR_W1_ERW_VAL(w1) ((w1 & XRDC_DERR_W_ERW_MASK) >> XRDC_DERR_W_ERW_SHIFT)
#define XRDC_DERR_W1_EATR_VAL(w1) ((w1 & XRDC_DERR_W_EATR_MASK) >> XRDC_DERR_W_EATR_SHIFT)
#define XRDC_DERR_W1_EDID_VAL(w1) ((w1 & XRDC_DERR_W_EDID_MASK) >> XRDC_DERR_W_EDID_SHIFT)
#if !(defined(FSL_FEATURE_XRDC_NO_MRGD_DXACP) && FSL_FEATURE_XRDC_NO_MRGD_DXACP)
#define XRDC_MRGD_DXACP_WIDTH (3U) /* The width of XRDC_MRDG_DxACP. */
#elif(defined(FSL_FEATURE_XRDC_HAS_MRGD_DXSEL) && FSL_FEATURE_XRDC_HAS_MRGD_DXSEL)
#define XRDC_MRGD_DXSEL_WIDTH (3U) /* The width of XRDC_MRDG_DxSEL. */
#endif
#define XRDC_PDAC_DXACP_WIDTH (3U) /* The width of XRDC_PDAC_DxACP. */
/* For the force exclusive accesss lock release procedure. */
#define XRDC_FORCE_EXCL_ACS_LOCK_REL_VAL1 (0x02000046U) /* The width of XRDC_MRDG_DxACP. */
#define XRDC_FORCE_EXCL_ACS_LOCK_REL_VAL2 (0x02000052U) /* The width of XRDC_PDAC_DxACP. */
/*******************************************************************************
* Variables
******************************************************************************/
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
/* Clock name of XRDC. */
#if (FSL_CLOCK_XRDC_GATE_COUNT > 1)
static const clock_ip_name_t s_xrdcClock[] = XRDC_CLOCKS;
#endif
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
/*******************************************************************************
* Code
******************************************************************************/
#if (((__CORTEX_M == 0U) && (defined(__ICCARM__))) || defined(__riscv))
/*!
* @brief Count the leading zeros.
*
* Count the leading zeros of an 32-bit data. This function is only defined
* for CM0 and CM0+ for IAR, because other cortex series have the clz instruction,
* KEIL and ARMGCC have toolchain build in function for this purpose.
*
* @param data The data to process.
* @return Count of the leading zeros.
*/
static uint32_t XRDC_CountLeadingZeros(uint32_t data)
{
uint32_t count = 0U;
uint32_t mask = 0x80000000U;
while ((data & mask) == 0U)
{
count++;
mask >>= 1U;
}
return count;
}
#endif
void XRDC_Init(XRDC_Type *base)
{
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
#if FSL_CLOCK_XRDC_GATE_COUNT
#if (FSL_CLOCK_XRDC_GATE_COUNT == 1)
CLOCK_EnableClock(kCLOCK_Xrdc0);
#else
uint8_t i;
for (i = 0; i < ARRAY_SIZE(s_xrdcClock); i++)
{
CLOCK_EnableClock(s_xrdcClock[i]);
}
#endif
#endif
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
}
void XRDC_Deinit(XRDC_Type *base)
{
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
#if FSL_CLOCK_XRDC_GATE_COUNT
#if (FSL_CLOCK_XRDC_GATE_COUNT == 1)
CLOCK_EnableClock(kCLOCK_Xrdc0);
#else
uint8_t i;
for (i = 0; i < ARRAY_SIZE(s_xrdcClock); i++)
{
CLOCK_DisableClock(s_xrdcClock[i]);
}
#endif
#endif
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
}
void XRDC_GetHardwareConfig(XRDC_Type *base, xrdc_hardware_config_t *config)
{
assert(config);
config->masterNumber = ((base->HWCFG0 & XRDC_HWCFG0_NMSTR_MASK) >> XRDC_HWCFG0_NMSTR_SHIFT) + 1U;
config->domainNumber = ((base->HWCFG0 & XRDC_HWCFG0_NDID_MASK) >> XRDC_HWCFG0_NDID_SHIFT) + 1U;
config->pacNumber = ((base->HWCFG0 & XRDC_HWCFG0_NPAC_MASK) >> XRDC_HWCFG0_NPAC_SHIFT) + 1U;
config->mrcNumber = ((base->HWCFG0 & XRDC_HWCFG0_NMRC_MASK) >> XRDC_HWCFG0_NMRC_SHIFT) + 1U;
}
status_t XRDC_GetAndClearFirstDomainError(XRDC_Type *base, xrdc_error_t *error)
{
return XRDC_GetAndClearFirstSpecificDomainError(base, error, XRDC_GetCurrentMasterDomainId(base));
}
status_t XRDC_GetAndClearFirstSpecificDomainError(XRDC_Type *base, xrdc_error_t *error, uint8_t domainId)
{
assert(error);
uint32_t errorBitMap; /* Domain error location bit map. */
uint32_t errorIndex; /* The index of first domain error. */
uint32_t regW1; /* To save XRDC_DERR_W1. */
/* Get the error bitmap. */
errorBitMap = base->DERRLOC[domainId];
if (!errorBitMap) /* No error captured. */
{
return kStatus_XRDC_NoError;
}
/* Get the first error controller index. */
#if (((__CORTEX_M == 0U) && (defined(__ICCARM__))) || defined(__riscv))
errorIndex = 31U - XRDC_CountLeadingZeros(errorBitMap);
#else
errorIndex = 31U - __CLZ(errorBitMap);
#endif
#if (defined(FSL_FEATURE_XRDC_HAS_FDID) && FSL_FEATURE_XRDC_HAS_FDID)
/* Must write FDID[FDID] with the domain ID before reading the Domain Error registers. */
base->FDID = XRDC_FDID_FDID(domainId);
#endif /* FSL_FEATURE_XRDC_HAS_FDID */
/* Get the error information. */
regW1 = base->DERR_W[errorIndex][1];
error->controller = (xrdc_controller_t)errorIndex;
error->address = base->DERR_W[errorIndex][0];
error->errorState = (xrdc_error_state_t)XRDC_DERR_W1_EST_VAL(regW1);
error->errorAttr = (xrdc_error_attr_t)XRDC_DERR_W1_EATR_VAL(regW1);
error->errorType = (xrdc_error_type_t)XRDC_DERR_W1_ERW_VAL(regW1);
error->errorPort = XRDC_DERR_W1_EPORT_VAL(regW1);
error->domainId = XRDC_DERR_W1_EDID_VAL(regW1);
/* Clear error pending. */
base->DERR_W[errorIndex][3] = XRDC_DERR_W_RECR(0x01U);
return kStatus_Success;
}
void XRDC_GetMemAccessDefaultConfig(xrdc_mem_access_config_t *config)
{
assert(config);
uint8_t i;
#if !(defined(FSL_FEATURE_XRDC_NO_MRGD_SE) && FSL_FEATURE_XRDC_NO_MRGD_SE)
config->enableSema = false;
config->semaNum = 0U;
#endif /* FSL_FEATURE_XRDC_NO_MRGD_SE */
#if !(defined(FSL_FEATURE_XRDC_NO_MRGD_SZ) && FSL_FEATURE_XRDC_NO_MRGD_SZ)
config->size = kXRDC_MemSizeNone;
#endif /* FSL_FEATURE_XRDC_NO_MRGD_SZ */
#if !(defined(FSL_FEATURE_XRDC_NO_MRGD_SRD) && FSL_FEATURE_XRDC_NO_MRGD_SRD)
config->subRegionDisableMask = 0U;
#endif /* FSL_FEATURE_XRDC_NO_MRGD_SRD */
#if (defined(FSL_FEATURE_XRDC_HAS_MRGD_CR) && FSL_FEATURE_XRDC_HAS_MRGD_CR)
config->codeRegion = kXRDC_MemCodeRegion0;
#endif /* FSL_FEATURE_XRDC_HAS_MRGD_CR */
#if (defined(FSL_FEATURE_XRDC_HAS_MRGD_ACCSET) && FSL_FEATURE_XRDC_HAS_MRGD_ACCSET)
config->enableAccset1Lock = false;
config->enableAccset2Lock = false;
config->accset1 = 0x000U;
config->accset2 = 0x000U;
#endif /* FSL_FEATURE_XRDC_HAS_MRGD_ACCSET */
config->lockMode = kXRDC_AccessConfigLockWritable;
config->baseAddress = 0U;
#if (defined(FSL_FEATURE_XRDC_HAS_MRGD_ENDADDR) && FSL_FEATURE_XRDC_HAS_MRGD_ENDADDR)
config->endAddress = 0U;
#endif /* FSL_FEATURE_XRDC_HAS_MRGD_ENDADDR */
for (i = 0U; i < FSL_FEATURE_XRDC_DOMAIN_COUNT; i++)
{
#if !(defined(FSL_FEATURE_XRDC_NO_MRGD_DXACP) && FSL_FEATURE_XRDC_NO_MRGD_DXACP)
config->policy[i] = kXRDC_AccessPolicyNone;
#elif(defined(FSL_FEATURE_XRDC_HAS_MRGD_DXSEL) && FSL_FEATURE_XRDC_HAS_MRGD_DXSEL)
config->policy[i] = kXRDC_AccessFlagsNone;
#endif
}
#if (defined(FSL_FEATURE_XRDC_HAS_MRGD_EAL) && FSL_FEATURE_XRDC_HAS_MRGD_EAL)
config->exclAccessLockMode = kXRDC_ExclAccessLockDisabled;
#endif /* FSL_FEATURE_XRDC_HAS_MRGD_EAL */
}
void XRDC_SetMemAccessConfig(XRDC_Type *base, const xrdc_mem_access_config_t *config)
{
assert(config);
#if !(defined(FSL_FEATURE_XRDC_NO_MRGD_SZ) && FSL_FEATURE_XRDC_NO_MRGD_SZ)
/* Not allowed to set sub-region disable mask for memory region smaller than 256-bytes. */
assert(!((config->size < kXRDC_MemSize256B) && (config->subRegionDisableMask)));
/* Memory region minimum size = 32 bytes and base address must be aligned to 0-module-2**(SZ+1). */
assert(config->size >= kXRDC_MemSize32B);
assert(!(config->baseAddress & ((1U << (config->size + 1U)) - 1U)));
#endif /* FSL_FEATURE_XRDC_NO_MRGD_SZ */
uint32_t i;
uint32_t regValue;
uint8_t index = (uint8_t)config->mem;
/* Set MRGD_W0. */
base->MRGD[index].MRGD_W[0] = config->baseAddress;
/* Set MRGD_W1. */
#if !(defined(FSL_FEATURE_XRDC_NO_MRGD_SZ) && FSL_FEATURE_XRDC_NO_MRGD_SZ)
base->MRGD[index].MRGD_W[1] = XRDC_MRGD_W_SZ(config->size) | XRDC_MRGD_W_SRD(config->subRegionDisableMask);
#endif /* FSL_FEATURE_XRDC_NO_MRGD_SZ */
#if (defined(FSL_FEATURE_XRDC_HAS_MRGD_ENDADDR) && FSL_FEATURE_XRDC_HAS_MRGD_ENDADDR)
base->MRGD[index].MRGD_W[1] = config->endAddress;
#endif /* FSL_FEATURE_XRDC_HAS_MRGD_ENDADDR */
/* Set MRGD_W2. */
regValue = 0U;
/* Set MRGD_W2[D0ACP ~ D7ACP] or MRGD_W2[D0SEL ~ D2SEL]. */
#if (FSL_FEATURE_XRDC_DOMAIN_COUNT <= 8U)
i = FSL_FEATURE_XRDC_DOMAIN_COUNT;
#elif(FSL_FEATURE_XRDC_DOMAIN_COUNT <= 16U)
i = 8U;
#else
#error Does not support more than 16 domain.
#endif
while (i--)
{
#if !(defined(FSL_FEATURE_XRDC_NO_MRGD_DXACP) && FSL_FEATURE_XRDC_NO_MRGD_DXACP)
regValue <<= XRDC_MRGD_DXACP_WIDTH;
#elif(defined(FSL_FEATURE_XRDC_HAS_MRGD_DXSEL) && FSL_FEATURE_XRDC_HAS_MRGD_DXSEL)
regValue <<= XRDC_MRGD_DXSEL_WIDTH;
#endif
regValue |= config->policy[i];
}
#if !(defined(FSL_FEATURE_XRDC_NO_MRGD_SE) && FSL_FEATURE_XRDC_NO_MRGD_SE)
regValue |= XRDC_MRGD_W_SE(config->enableSema) | XRDC_MRGD_W_SNUM(config->semaNum);
#endif /* FSL_FEATURE_XRDC_NO_MRGD_SE */
base->MRGD[index].MRGD_W[2] = regValue;
/* Set MRGD_W3. */
regValue = 0U;
#if ((FSL_FEATURE_XRDC_DOMAIN_COUNT > 8U) && (FSL_FEATURE_XRDC_DOMAIN_COUNT <= 16))
/* Set MRGD_W3[D8ACP ~ D15ACP]. */
for (i = FSL_FEATURE_XRDC_DOMAIN_COUNT - 1U; i > 7U; i--)
{
regValue <<= XRDC_MRGD_DXACP_WIDTH;
regValue |= config->policy[i];
}
#endif
#if (defined(FSL_FEATURE_XRDC_HAS_MRGD_CR) && FSL_FEATURE_XRDC_HAS_MRGD_CR)
regValue |= XRDC_MRGD_W_CR(config->codeRegion);
#endif
#if !(defined(FSL_FEATURE_XRDC_NO_MRGD_W3_VLD) && FSL_FEATURE_XRDC_NO_MRGD_W3_VLD)
regValue |= XRDC_MRGD_W_VLD_MASK | XRDC_MRGD_W_LK2(config->lockMode);
#endif
base->MRGD[index].MRGD_W[3] = regValue;
#if (defined(FSL_FEATURE_XRDC_HAS_MRGD_EAL) && FSL_FEATURE_XRDC_HAS_MRGD_EAL)
/*
* Set MRGD_W3[EAL].
* If write with a value of MRGD_W3[EAL]=0, then the other fields of MRGD_W3 are updated.
* If write with a value of MRGD_W3[EAL]!=0, then only the EAL is updated.
*/
if (kXRDC_ExclAccessLockDisabled != config->exclAccessLockMode)
{
base->MRGD[index].MRGD_W[3] = XRDC_MRGD_W_EAL(config->exclAccessLockMode);
}
#endif
#if (defined(FSL_FEATURE_XRDC_HAS_MRGD_ACCSET) && FSL_FEATURE_XRDC_HAS_MRGD_ACCSET)
/* Set MRGD_W4. */
base->MRGD[index].MRGD_W[4] = XRDC_MRGD_W_LKAS1(config->enableAccset1Lock) | XRDC_MRGD_W_ACCSET1(config->accset1) |
XRDC_MRGD_W_LKAS2(config->enableAccset2Lock) | XRDC_MRGD_W_ACCSET2(config->accset2) |
XRDC_MRGD_W_VLD_MASK | XRDC_MRGD_W_LK2(config->lockMode);
#endif
}
#if (defined(FSL_FEATURE_XRDC_HAS_MRGD_EAL) && FSL_FEATURE_XRDC_HAS_MRGD_EAL)
void XRDC_SetMemExclAccessLockMode(XRDC_Type *base, xrdc_mem_t mem, xrdc_excl_access_lock_config_t lockMode)
{
/* Write kXRDC_ExclAccessLockDisabled is not allowed. */
assert(kXRDC_ExclAccessLockDisabled != lockMode);
uint32_t reg = base->MRGD[mem].MRGD_W[4];
/* Step 1. Set the memory region exclusive access lock mode configuration. */
base->MRGD[mem].MRGD_W[3] = XRDC_MRGD_W_EAL(lockMode);
/* Step 2. Set MRGD_W3 will clear the MRGD_W4[VLD]. So should re-assert it. */
base->MRGD[mem].MRGD_W[4] = reg;
}
void XRDC_ForceMemExclAccessLockRelease(XRDC_Type *base, xrdc_mem_t mem)
{
uint32_t primask;
primask = DisableGlobalIRQ();
base->MRGD[mem].MRGD_W[3] = XRDC_FORCE_EXCL_ACS_LOCK_REL_VAL1;
base->MRGD[mem].MRGD_W[3] = XRDC_FORCE_EXCL_ACS_LOCK_REL_VAL2;
EnableGlobalIRQ(primask);
}
#endif /* FSL_FEATURE_XRDC_HAS_MRGD_EAL */
#if (defined(FSL_FEATURE_XRDC_HAS_MRGD_ACCSET) && FSL_FEATURE_XRDC_HAS_MRGD_ACCSET)
void XRDC_SetMemAccsetLock(XRDC_Type *base, xrdc_mem_t mem, xrdc_mem_accset_t accset, bool lock)
{
uint32_t lkasMask = 0U;
switch (accset)
{
case kXRDC_MemAccset1:
lkasMask = XRDC_MRGD_W_LKAS1_MASK;
break;
case kXRDC_MemAccset2:
lkasMask = XRDC_MRGD_W_LKAS2_MASK;
break;
default:
break;
}
if (lock)
{
base->MRGD[mem].MRGD_W[4] |= lkasMask;
}
else
{
base->MRGD[mem].MRGD_W[4] &= ~lkasMask;
}
}
#endif /* FSL_FEATURE_XRDC_HAS_MRGD_ACCSET */
void XRDC_GetPeriphAccessDefaultConfig(xrdc_periph_access_config_t *config)
{
assert(config);
uint8_t i;
#if !(defined(FSL_FEATURE_XRDC_NO_PDAC_SE) && FSL_FEATURE_XRDC_NO_PDAC_SE)
config->enableSema = false;
config->semaNum = 0U;
#endif /* FSL_FEATURE_XRDC_NO_PDAC_SE */
config->lockMode = kXRDC_AccessConfigLockWritable;
#if (defined(FSL_FEATURE_XRDC_HAS_PDAC_EAL) && FSL_FEATURE_XRDC_HAS_PDAC_EAL)
config->exclAccessLockMode = kXRDC_ExclAccessLockDisabled;
#endif /* FSL_FEATURE_XRDC_HAS_PDAC_EAL */
for (i = 0U; i < FSL_FEATURE_XRDC_DOMAIN_COUNT; i++)
{
config->policy[i] = kXRDC_AccessPolicyNone;
}
}
void XRDC_SetPeriphAccessConfig(XRDC_Type *base, const xrdc_periph_access_config_t *config)
{
assert(config);
uint32_t i;
uint32_t regValue;
uint8_t index = (uint8_t)config->periph;
/* Set PDAC_W0[D0ACP ~ D7ACP]. */
regValue = 0U;
#if (FSL_FEATURE_XRDC_DOMAIN_COUNT <= 8U)
i = FSL_FEATURE_XRDC_DOMAIN_COUNT;
#elif(FSL_FEATURE_XRDC_DOMAIN_COUNT <= 16U)
i = 8U;
#else
#error Does not support more than 16 domain.
#endif
while (i--)
{
regValue <<= XRDC_PDAC_DXACP_WIDTH;
regValue |= config->policy[i];
}
#if !(defined(FSL_FEATURE_XRDC_NO_MRGD_SE) && FSL_FEATURE_XRDC_NO_MRGD_SE)
regValue |= (XRDC_PDAC_W_SE(config->enableSema) | XRDC_PDAC_W_SNUM(config->semaNum));
#endif /* FSL_FEATURE_XRDC_NO_MRGD_SE */
/* Set PDAC_W0. */
base->PDAC_W[index][0U] = regValue;
#if (defined(FSL_FEATURE_XRDC_HAS_PDAC_EAL) && FSL_FEATURE_XRDC_HAS_PDAC_EAL)
/*
* If write with a value of PDAC_W1[EAL]=0, then the other fields of PDAC_W1 are updated.
* If write with a value of PDAC_W1[EAL]!=0, then only the EAL is updated.
*/
base->PDAC_W[index][1U] = XRDC_PDAC_W_EAL(config->exclAccessLockMode);
#endif
regValue = 0U;
#if ((FSL_FEATURE_XRDC_DOMAIN_COUNT > 8U) && (FSL_FEATURE_XRDC_DOMAIN_COUNT <= 16))
/* Set PDAC_W1[D8ACP ~ D15ACP]. */
for (i = FSL_FEATURE_XRDC_DOMAIN_COUNT - 1U; i > 7U; i--)
{
regValue <<= XRDC_PDAC_DXACP_WIDTH;
regValue |= config->policy[i];
}
#endif
/* Set PDAC_W1. */
base->PDAC_W[index][1] = regValue | XRDC_PDAC_W_VLD_MASK | XRDC_PDAC_W_LK2(config->lockMode);
}
#if (defined(FSL_FEATURE_XRDC_HAS_PDAC_EAL) && FSL_FEATURE_XRDC_HAS_PDAC_EAL)
void XRDC_ForcePeriphExclAccessLockRelease(XRDC_Type *base, xrdc_periph_t periph)
{
uint32_t primask;
primask = DisableGlobalIRQ();
base->PDAC_W[periph][1] = XRDC_FORCE_EXCL_ACS_LOCK_REL_VAL1;
base->PDAC_W[periph][1] = XRDC_FORCE_EXCL_ACS_LOCK_REL_VAL2;
EnableGlobalIRQ(primask);
}
#endif /* FSL_FEATURE_XRDC_HAS_PDAC_EAL */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,62 @@
/*
* Copyright 2014-2016 Freescale Semiconductor, Inc.
* Copyright 2016-2018 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*
*/
#ifndef __FSL_DEVICE_REGISTERS_H__
#define __FSL_DEVICE_REGISTERS_H__
/*
* Include the cpu specific register header files.
*
* The CPU macro should be declared in the project or makefile.
*/
#if defined(CPU_RV32M1_cm0plus)
#define RV32M1_cm0plus_SERIES
/* CMSIS-style register definitions */
#include "RV32M1_cm0plus.h"
/* CPU specific feature definitions */
#include "RV32M1_cm0plus_features.h"
#elif defined(CPU_RV32M1_cm4)
#define RV32M1_cm4_SERIES
/* CMSIS-style register definitions */
#include "RV32M1_cm4.h"
/* CPU specific feature definitions */
#include "RV32M1_cm4_features.h"
#elif defined(CPU_RV32M1_zero_riscy)
#define RV32M1_zero_riscy_SERIES
/* CMSIS-style register definitions */
#include "RV32M1_zero_riscy.h"
/* CPU specific feature definitions */
#include "RV32M1_zero_riscy_features.h"
#elif defined(CPU_RV32M1_ri5cy)
#define RV32M1_ri5cy_SERIES
/* CMSIS-style register definitions */
#include "RV32M1_ri5cy.h"
/* CPU specific feature definitions */
#include "RV32M1_ri5cy_features.h"
#else
#error "No valid CPU defined!"
#endif
#endif /* __FSL_DEVICE_REGISTERS_H__ */
/*******************************************************************************
* EOF
******************************************************************************/

View File

@ -0,0 +1,226 @@
/* ------------------------------------------------------------------------- */
/* @file: startup_RV32M1_ri5cy.s */
/* @purpose: RI5CY Core Device Startup File */
/* RV32M1_ri5cy */
/* @version: 1.0 */
/* @date: 2018-10-2 */
/* @build: b180926 */
/* ------------------------------------------------------------------------- */
/* */
/* Copyright 1997-2016 Freescale Semiconductor, Inc. */
/* Copyright 2016-2018 NXP */
/* All rights reserved. */
/* */
/* SPDX-License-Identifier: BSD-3-Clause */
// Copyright 2017 ETH Zurich and University of Bologna.
// Copyright and related rights are licensed under the Solderpad Hardware
// License, Version 0.51 (the "License"); you may not use this file except in
// compliance with the License. You may obtain a copy of the License at
// http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law
// or agreed to in writing, software, hardware and materials distributed under
// this 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.
#define EXCEPTION_STACK_SIZE 0x58
.text
.section .vectors, "ax"
.option norvc;
jal x0, IRQ_Handler
jal x0, IRQ_Handler
jal x0, IRQ_Handler
jal x0, IRQ_Handler
jal x0, IRQ_Handler
jal x0, IRQ_Handler
jal x0, IRQ_Handler
jal x0, IRQ_Handler
jal x0, IRQ_Handler
jal x0, IRQ_Handler
jal x0, IRQ_Handler
jal x0, IRQ_Handler
jal x0, IRQ_Handler
jal x0, IRQ_Handler
jal x0, IRQ_Handler
jal x0, IRQ_Handler
jal x0, IRQ_Handler
jal x0, IRQ_Handler
jal x0, IRQ_Handler
jal x0, IRQ_Handler
jal x0, IRQ_Handler
jal x0, IRQ_Handler
jal x0, IRQ_Handler
jal x0, IRQ_Handler
jal x0, IRQ_Handler
jal x0, IRQ_Handler
jal x0, IRQ_Handler
jal x0, IRQ_Handler
jal x0, IRQ_Handler
jal x0, IRQ_Handler
jal x0, IRQ_Handler
jal x0, IRQ_Handler
// reset vector
jal x0, Reset_Handler
// Illegal instrution exception
jal x0, IllegalInstruction_Handler
// ecall handler
jal x0, Ecall_Handler
// LSU error
jal x0, LSU_Handler
.section .startup
/* Reset Handler */
Reset_Handler:
# Disable global interrupt. */
csrci mstatus, 8
# initialize stack pointer
la sp, __StackTop
# initialize global pointer
la gp, __global_pointer
#ifndef __NO_SYSTEM_INIT
jal SystemInit
#endif
# call __libc_init_array
# Enable global interrupt. */
# csrsi mstatus, 8
jal entry
ebreak
.size Reset_Handler, . - Reset_Handler
.global _init
.global _fini
_init:
_fini:
ret
// saves all caller-saved registers (except return address)
store_regs:
sw x3, 0x00(x2) // gp
sw x4, 0x04(x2) // tp
sw x5, 0x08(x2) // t0
sw x6, 0x0c(x2) // t1
sw x7, 0x10(x2) // t2
sw x10, 0x14(x2) // a0
sw x11, 0x18(x2) // a1
sw x12, 0x1c(x2) // a2
sw x13, 0x20(x2) // a3
sw x14, 0x24(x2) // a4
sw x15, 0x28(x2) // a5
sw x16, 0x2c(x2) // a6
sw x17, 0x30(x2) // a7
csrr a0, 0x7B0
csrr a1, 0x7B1
csrr a2, 0x7B2
sw a0, 0x34(x2) // lpstart[0]
sw a1, 0x38(x2) // lpend[0]
sw a2, 0x3c(x2) // lpcount[0]
csrr a0, 0x7B4
csrr a1, 0x7B5
csrr a2, 0x7B6
sw a0, 0x40(x2) // lpstart[1]
sw a1, 0x44(x2) // lpend[1]
sw a2, 0x48(x2) // lpcount[1]
csrr a0, 0x341
sw a0, 0x4c(x2) // mepc
csrr a1, 0x300
sw a1, 0x50(x2) // mstatus
jalr x0, x1
// load back registers from stack
end_except:
lw a1, 0x50(x2) // mstatus
csrrw x0, 0x300, a1
lw a0, 0x4c(x2) // mepc
csrrw x0, 0x341, a0
lw a0, 0x40(x2) // lpstart[1]
lw a1, 0x44(x2) // lpend[1]
lw a2, 0x48(x2) // lpcount[1]
csrrw x0, 0x7B4, a0
csrrw x0, 0x7B5, a1
csrrw x0, 0x7B6, a2
lw a0, 0x34(x2) // lpstart[0]
lw a1, 0x38(x2) // lpend[0]
lw a2, 0x3c(x2) // lpcount[0]
csrrw x0, 0x7B0, a0
csrrw x0, 0x7B1, a1
csrrw x0, 0x7B2, a2
lw x3, 0x00(x2) // gp
lw x4, 0x04(x2) // tp
lw x5, 0x08(x2) // t0
lw x6, 0x0c(x2) // t1
lw x7, 0x10(x2) // t2
lw x10, 0x14(x2) // a0
lw x11, 0x18(x2) // a1
lw x12, 0x1c(x2) // a2
lw x13, 0x20(x2) // a3
lw x14, 0x24(x2) // a4
lw x15, 0x28(x2) // a5
lw x16, 0x2c(x2) // a6
lw x17, 0x30(x2) // a7
lw x1, 0x54(x2)
addi x2, x2, EXCEPTION_STACK_SIZE
mret
.weak IRQ_Handler
.type IRQ_Handler, %function
IRQ_Handler:
addi x2, x2, -EXCEPTION_STACK_SIZE
sw x1, 0x54(x2)
jal x1, store_regs
la x1, end_except
csrr a0, mcause
jal x0, SystemIrqHandler
.size IRQ_Handler, . - IRQ_Handler
.macro define_exception_entry entry_name handler_name
.weak \entry_name
\entry_name:
addi x2, x2, -EXCEPTION_STACK_SIZE
sw x1, 0x54(x2)
jal x1, store_regs
la x1, end_except
jal x0, \handler_name
.endm
define_exception_entry IllegalInstruction_Handler IllegalInstruction_HandlerFunc
define_exception_entry Ecall_Handler Ecall_HandlerFunc
define_exception_entry LSU_Handler LSU_HandlerFunc
.weak IllegalInstruction_HandlerFunc
.type IllegalInstruction_HandlerFunc, %function
IllegalInstruction_HandlerFunc:
j .
.size IllegalInstruction_HandlerFunc, . - IllegalInstruction_HandlerFunc
.weak Ecall_HandlerFunc
.type Ecall_HandlerFunc, %function
Ecall_HandlerFunc:
j .
.size Ecall_HandlerFunc, . - Ecall_HandlerFunc
.weak LSU_HandlerFunc
.type LSU_HandlerFunc, %function
LSU_HandlerFunc:
j .
.size LSU_HandlerFunc, . - LSU_HandlerFunc

View File

@ -0,0 +1,225 @@
/* ------------------------------------------------------------------------- */
/* @file: startup_RV32M1_zero_riscy.s */
/* @purpose: ZERO_RISCY Core Device Startup File */
/* RV32M1_zero_riscy */
/* @version: 1.0 */
/* @date: 2018-10-2 */
/* @build: b180926 */
/* ------------------------------------------------------------------------- */
/* */
/* Copyright 1997-2016 Freescale Semiconductor, Inc. */
/* Copyright 2016-2018 NXP */
/* All rights reserved. */
/* */
/* SPDX-License-Identifier: BSD-3-Clause */
// Copyright 2017 ETH Zurich and University of Bologna.
// Copyright and related rights are licensed under the Solderpad Hardware
// License, Version 0.51 (the "License"); you may not use this file except in
// compliance with the License. You may obtain a copy of the License at
// http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law
// or agreed to in writing, software, hardware and materials distributed under
// this 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.
#define EXCEPTION_STACK_SIZE 0x58
.text
.section .vectors, "ax"
.option norvc;
jal x0, IRQ_Handler
jal x0, IRQ_Handler
jal x0, IRQ_Handler
jal x0, IRQ_Handler
jal x0, IRQ_Handler
jal x0, IRQ_Handler
jal x0, IRQ_Handler
jal x0, IRQ_Handler
jal x0, IRQ_Handler
jal x0, IRQ_Handler
jal x0, IRQ_Handler
jal x0, IRQ_Handler
jal x0, IRQ_Handler
jal x0, IRQ_Handler
jal x0, IRQ_Handler
jal x0, IRQ_Handler
jal x0, IRQ_Handler
jal x0, IRQ_Handler
jal x0, IRQ_Handler
jal x0, IRQ_Handler
jal x0, IRQ_Handler
jal x0, IRQ_Handler
jal x0, IRQ_Handler
jal x0, IRQ_Handler
jal x0, IRQ_Handler
jal x0, IRQ_Handler
jal x0, IRQ_Handler
jal x0, IRQ_Handler
jal x0, IRQ_Handler
jal x0, IRQ_Handler
jal x0, IRQ_Handler
jal x0, IRQ_Handler
// reset vector
jal x0, Reset_Handler
// Illegal instrution exception
jal x0, IllegalInstruction_Handler
// ecall handler
jal x0, Ecall_Handler
// LSU error
jal x0, LSU_Handler
.section .startup
/* Reset Handler */
Reset_Handler:
# Disable global interrupt. */
csrci mstatus, 8
# initialize stack pointer
la sp, __StackTop
# initialize global pointer
la gp, __global_pointer
#ifndef __NO_SYSTEM_INIT
jal SystemInit
#endif
call __libc_init_array
# Enable global interrupt. */
csrsi mstatus, 8
jal main
ebreak
.size Reset_Handler, . - Reset_Handler
.global _init
.global _fini
_init:
_fini:
ret
// saves all caller-saved registers (except return address)
store_regs:
sw x3, 0x00(x2) // gp
sw x4, 0x04(x2) // tp
sw x5, 0x08(x2) // t0
sw x6, 0x0c(x2) // t1
sw x7, 0x10(x2) // t2
sw x10, 0x14(x2) // a0
sw x11, 0x18(x2) // a1
sw x12, 0x1c(x2) // a2
sw x13, 0x20(x2) // a3
sw x14, 0x24(x2) // a4
sw x15, 0x28(x2) // a5
sw x16, 0x2c(x2) // a6
sw x17, 0x30(x2) // a7
csrr a0, 0x7B0
csrr a1, 0x7B1
csrr a2, 0x7B2
sw a0, 0x34(x2) // lpstart[0]
sw a1, 0x38(x2) // lpend[0]
sw a2, 0x3c(x2) // lpcount[0]
csrr a0, 0x7B4
csrr a1, 0x7B5
csrr a2, 0x7B6
sw a0, 0x40(x2) // lpstart[1]
sw a1, 0x44(x2) // lpend[1]
sw a2, 0x48(x2) // lpcount[1]
csrr a0, 0x341
sw a0, 0x4c(x2) // mepc
csrr a1, 0x300
sw a1, 0x50(x2) // mstatus
jalr x0, x1
// load back registers from stack
end_except:
lw a1, 0x50(x2) // mstatus
csrrw x0, 0x300, a1
lw a0, 0x4c(x2) // mepc
csrrw x0, 0x341, a0
lw a0, 0x40(x2) // lpstart[1]
lw a1, 0x44(x2) // lpend[1]
lw a2, 0x48(x2) // lpcount[1]
csrrw x0, 0x7B4, a0
csrrw x0, 0x7B5, a1
csrrw x0, 0x7B6, a2
lw a0, 0x34(x2) // lpstart[0]
lw a1, 0x38(x2) // lpend[0]
lw a2, 0x3c(x2) // lpcount[0]
csrrw x0, 0x7B0, a0
csrrw x0, 0x7B1, a1
csrrw x0, 0x7B2, a2
lw x3, 0x00(x2) // gp
lw x4, 0x04(x2) // tp
lw x5, 0x08(x2) // t0
lw x6, 0x0c(x2) // t1
lw x7, 0x10(x2) // t2
lw x10, 0x14(x2) // a0
lw x11, 0x18(x2) // a1
lw x12, 0x1c(x2) // a2
lw x13, 0x20(x2) // a3
lw x14, 0x24(x2) // a4
lw x15, 0x28(x2) // a5
lw x16, 0x2c(x2) // a6
lw x17, 0x30(x2) // a7
lw x1, 0x54(x2)
addi x2, x2, EXCEPTION_STACK_SIZE
mret
.weak IRQ_Handler
.type IRQ_Handler, %function
IRQ_Handler:
addi x2, x2, -EXCEPTION_STACK_SIZE
sw x1, 0x54(x2)
jal x1, store_regs
la x1, end_except
csrr a0, mcause
jal x0, SystemIrqHandler
.size IRQ_Handler, . - IRQ_Handler
.macro define_exception_entry entry_name handler_name
.weak \entry_name
\entry_name:
addi x2, x2, -EXCEPTION_STACK_SIZE
sw x1, 0x54(x2)
jal x1, store_regs
la x1, end_except
jal x0, \handler_name
.endm
define_exception_entry IllegalInstruction_Handler IllegalInstruction_HandlerFunc
define_exception_entry Ecall_Handler Ecall_HandlerFunc
define_exception_entry LSU_Handler LSU_HandlerFunc
.weak IllegalInstruction_HandlerFunc
.type IllegalInstruction_HandlerFunc, %function
IllegalInstruction_HandlerFunc:
j .
.size IllegalInstruction_HandlerFunc, . - IllegalInstruction_HandlerFunc
.weak Ecall_HandlerFunc
.type Ecall_HandlerFunc, %function
Ecall_HandlerFunc:
j .
.size Ecall_HandlerFunc, . - Ecall_HandlerFunc
.weak LSU_HandlerFunc
.type LSU_HandlerFunc, %function
LSU_HandlerFunc:
j .
.size LSU_HandlerFunc, . - LSU_HandlerFunc

View File

@ -0,0 +1,556 @@
/*
** ###################################################################
** Processors: RV32M1_ri5cy
** RV32M1_ri5cy
**
** Compilers: Keil ARM C/C++ Compiler
** GNU C Compiler
** IAR ANSI C/C++ Compiler for ARM
** MCUXpresso Compiler
**
** Reference manual: RV32M1 Series Reference Manual, Rev. 1 , 8/10/2018
** Version: rev. 1.0, 2018-10-02
** Build: b180926
**
** Abstract:
** Provides a system configuration function and a global variable that
** contains the system frequency. It configures the device and initializes
** the oscillator (PLL) that is part of the microcontroller device.
**
** Copyright 2016 Freescale Semiconductor, Inc.
** Copyright 2016-2018 NXP
** All rights reserved.
**
** SPDX-License-Identifier: BSD-3-Clause
**
** http: www.nxp.com
** mail: support@nxp.com
**
** Revisions:
** - rev. 1.0 (2018-10-02)
** Initial version.
**
** ###################################################################
*/
/*!
* @file RV32M1_ri5cy
* @version 1.0
* @date 2018-10-02
* @brief Device specific configuration file for RV32M1_ri5cy
* (implementation file)
*
* Provides a system configuration function and a global variable that contains
* the system frequency. It configures the device and initializes the oscillator
* (PLL) that is part of the microcontroller device.
*/
#include <stdint.h>
#include "fsl_device_registers.h"
#include "fsl_common.h"
typedef void (*irq_handler_t)(void);
extern void DMA0_0_4_8_12_DriverIRQHandler(void);
extern void DMA0_1_5_9_13_DriverIRQHandler(void);
extern void DMA0_2_6_10_14_DriverIRQHandler(void);
extern void DMA0_3_7_11_15_DriverIRQHandler(void);
extern void DMA0_Error_IRQHandler(void);
extern void CMC0_IRQHandler(void);
extern void EWM_IRQHandler(void);
extern void FTFE_Command_Complete_IRQHandler(void);
extern void FTFE_Read_Collision_IRQHandler(void);
extern void LLWU0_IRQHandler(void);
extern void MUA_IRQHandler(void);
extern void SPM_IRQHandler(void);
extern void WDOG0_IRQHandler(void);
extern void SCG_IRQHandler(void);
extern void LPIT0_IRQHandler(void);
extern void RTC_IRQHandler(void);
extern void LPTMR0_IRQHandler(void);
extern void LPTMR1_IRQHandler(void);
extern void TPM0_IRQHandler(void);
extern void TPM1_IRQHandler(void);
extern void TPM2_IRQHandler(void);
extern void EMVSIM0_IRQHandler(void);
extern void FLEXIO0_DriverIRQHandler(void);
extern void LPI2C0_DriverIRQHandler(void);
extern void LPI2C1_DriverIRQHandler(void);
extern void LPI2C2_DriverIRQHandler(void);
extern void I2S0_DriverIRQHandler(void);
extern void USDHC0_DriverIRQHandler(void);
extern void LPSPI0_DriverIRQHandler(void);
extern void LPSPI1_DriverIRQHandler(void);
extern void LPSPI2_DriverIRQHandler(void);
extern void LPUART0_DriverIRQHandler(void);
extern void LPUART1_DriverIRQHandler(void);
extern void LPUART2_DriverIRQHandler(void);
extern void USB0_IRQHandler(void);
extern void PORTA_IRQHandler(void);
extern void PORTB_IRQHandler(void);
extern void PORTC_IRQHandler(void);
extern void PORTD_IRQHandler(void);
extern void ADC0_IRQHandler(void);
extern void LPCMP0_IRQHandler(void);
extern void LPDAC0_IRQHandler(void);
extern void CAU3_Task_Complete_IRQHandler(void);
extern void CAU3_Security_Violation_IRQHandler(void);
extern void TRNG_IRQHandler(void);
extern void LPIT1_IRQHandler(void);
extern void LPTMR2_IRQHandler(void);
extern void TPM3_IRQHandler(void);
extern void LPI2C3_DriverIRQHandler(void);
extern void LPSPI3_DriverIRQHandler(void);
extern void LPUART3_DriverIRQHandler(void);
extern void PORTE_IRQHandler(void);
extern void LPCMP1_IRQHandler(void);
extern void RF0_0_IRQHandler(void);
extern void RF0_1_IRQHandler(void);
extern void INTMUX0_0_DriverIRQHandler(void);
extern void INTMUX0_1_DriverIRQHandler(void);
extern void INTMUX0_2_DriverIRQHandler(void);
extern void INTMUX0_3_DriverIRQHandler(void);
extern void INTMUX0_4_DriverIRQHandler(void);
extern void INTMUX0_5_DriverIRQHandler(void);
extern void INTMUX0_6_DriverIRQHandler(void);
extern void INTMUX0_7_DriverIRQHandler(void);
extern void INTMUX0_8_DriverIRQHandler(void);
extern void DMA0_0_4_8_12_IRQHandler(void);
extern void DMA0_1_5_9_13_IRQHandler(void);
extern void DMA0_2_6_10_14_IRQHandler(void);
extern void DMA0_3_7_11_15_IRQHandler(void);
extern void FLEXIO0_IRQHandler(void);
extern void LPI2C0_IRQHandler(void);
extern void LPI2C1_IRQHandler(void);
extern void LPI2C2_IRQHandler(void);
extern void I2S0_IRQHandler(void);
extern void USDHC0_IRQHandler(void);
extern void LPSPI0_IRQHandler(void);
extern void LPSPI1_IRQHandler(void);
extern void LPSPI2_IRQHandler(void);
extern void LPUART0_IRQHandler(void);
extern void LPUART1_IRQHandler(void);
extern void LPUART2_IRQHandler(void);
extern void LPI2C3_IRQHandler(void);
extern void LPSPI3_IRQHandler(void);
extern void LPUART3_IRQHandler(void);
extern void INTMUX0_0_IRQHandler(void);
extern void INTMUX0_1_IRQHandler(void);
extern void INTMUX0_2_IRQHandler(void);
extern void INTMUX0_3_IRQHandler(void);
extern void INTMUX0_4_IRQHandler(void);
extern void INTMUX0_5_IRQHandler(void);
extern void INTMUX0_6_IRQHandler(void);
extern void INTMUX0_7_IRQHandler(void);
/* ----------------------------------------------------------------------------
-- Core clock
---------------------------------------------------------------------------- */
uint32_t SystemCoreClock = DEFAULT_SYSTEM_CLOCK;
extern uint32_t __etext;
extern uint32_t __data_start__;
extern uint32_t __data_end__;
extern uint32_t __bss_start__;
extern uint32_t __bss_end__;
static void copy_section(uint32_t * p_load, uint32_t * p_vma, uint32_t * p_vma_end)
{
while(p_vma <= p_vma_end)
{
*p_vma = *p_load;
++p_load;
++p_vma;
}
}
static void zero_section(uint32_t * start, uint32_t * end)
{
uint32_t * p_zero = start;
while(p_zero <= end)
{
*p_zero = 0;
++p_zero;
}
}
#define DEFINE_IRQ_HANDLER(irq_handler, driver_irq_handler) \
void __attribute__((weak)) irq_handler(void) { driver_irq_handler();}
#define DEFINE_DEFAULT_IRQ_HANDLER(irq_handler) void irq_handler() __attribute__((weak, alias("DefaultIRQHandler")))
DEFINE_DEFAULT_IRQ_HANDLER(DMA0_0_4_8_12_DriverIRQHandler);
DEFINE_DEFAULT_IRQ_HANDLER(DMA0_1_5_9_13_DriverIRQHandler);
DEFINE_DEFAULT_IRQ_HANDLER(DMA0_2_6_10_14_DriverIRQHandler);
DEFINE_DEFAULT_IRQ_HANDLER(DMA0_3_7_11_15_DriverIRQHandler);
DEFINE_DEFAULT_IRQ_HANDLER(DMA0_Error_IRQHandler);
DEFINE_DEFAULT_IRQ_HANDLER(CMC0_IRQHandler);
DEFINE_DEFAULT_IRQ_HANDLER(EWM_IRQHandler);
DEFINE_DEFAULT_IRQ_HANDLER(FTFE_Command_Complete_IRQHandler);
DEFINE_DEFAULT_IRQ_HANDLER(FTFE_Read_Collision_IRQHandler);
DEFINE_DEFAULT_IRQ_HANDLER(LLWU0_IRQHandler);
DEFINE_DEFAULT_IRQ_HANDLER(MUA_IRQHandler);
DEFINE_DEFAULT_IRQ_HANDLER(SPM_IRQHandler);
DEFINE_DEFAULT_IRQ_HANDLER(WDOG0_IRQHandler);
DEFINE_DEFAULT_IRQ_HANDLER(SCG_IRQHandler);
DEFINE_DEFAULT_IRQ_HANDLER(LPIT0_IRQHandler);
DEFINE_DEFAULT_IRQ_HANDLER(RTC_IRQHandler);
DEFINE_DEFAULT_IRQ_HANDLER(LPTMR0_IRQHandler);
DEFINE_DEFAULT_IRQ_HANDLER(LPTMR1_IRQHandler);
DEFINE_DEFAULT_IRQ_HANDLER(TPM0_IRQHandler);
DEFINE_DEFAULT_IRQ_HANDLER(TPM1_IRQHandler);
DEFINE_DEFAULT_IRQ_HANDLER(TPM2_IRQHandler);
DEFINE_DEFAULT_IRQ_HANDLER(EMVSIM0_IRQHandler);
DEFINE_DEFAULT_IRQ_HANDLER(FLEXIO0_DriverIRQHandler);
DEFINE_DEFAULT_IRQ_HANDLER(LPI2C0_DriverIRQHandler);
DEFINE_DEFAULT_IRQ_HANDLER(LPI2C1_DriverIRQHandler);
DEFINE_DEFAULT_IRQ_HANDLER(LPI2C2_DriverIRQHandler);
DEFINE_DEFAULT_IRQ_HANDLER(I2S0_DriverIRQHandler);
DEFINE_DEFAULT_IRQ_HANDLER(USDHC0_DriverIRQHandler);
DEFINE_DEFAULT_IRQ_HANDLER(LPSPI0_DriverIRQHandler);
DEFINE_DEFAULT_IRQ_HANDLER(LPSPI1_DriverIRQHandler);
DEFINE_DEFAULT_IRQ_HANDLER(LPSPI2_DriverIRQHandler);
DEFINE_DEFAULT_IRQ_HANDLER(LPUART0_DriverIRQHandler);
DEFINE_DEFAULT_IRQ_HANDLER(LPUART1_DriverIRQHandler);
DEFINE_DEFAULT_IRQ_HANDLER(LPUART2_DriverIRQHandler);
DEFINE_DEFAULT_IRQ_HANDLER(USB0_IRQHandler);
DEFINE_DEFAULT_IRQ_HANDLER(PORTA_IRQHandler);
DEFINE_DEFAULT_IRQ_HANDLER(PORTB_IRQHandler);
DEFINE_DEFAULT_IRQ_HANDLER(PORTC_IRQHandler);
DEFINE_DEFAULT_IRQ_HANDLER(PORTD_IRQHandler);
DEFINE_DEFAULT_IRQ_HANDLER(ADC0_IRQHandler);
DEFINE_DEFAULT_IRQ_HANDLER(LPCMP0_IRQHandler);
DEFINE_DEFAULT_IRQ_HANDLER(LPDAC0_IRQHandler);
DEFINE_DEFAULT_IRQ_HANDLER(CAU3_Task_Complete_IRQHandler);
DEFINE_DEFAULT_IRQ_HANDLER(CAU3_Security_Violation_IRQHandler);
DEFINE_DEFAULT_IRQ_HANDLER(TRNG_IRQHandler);
DEFINE_DEFAULT_IRQ_HANDLER(LPIT1_IRQHandler);
DEFINE_DEFAULT_IRQ_HANDLER(LPTMR2_IRQHandler);
DEFINE_DEFAULT_IRQ_HANDLER(TPM3_IRQHandler);
DEFINE_DEFAULT_IRQ_HANDLER(LPI2C3_DriverIRQHandler);
DEFINE_DEFAULT_IRQ_HANDLER(LPSPI3_DriverIRQHandler);
DEFINE_DEFAULT_IRQ_HANDLER(LPUART3_DriverIRQHandler);
DEFINE_DEFAULT_IRQ_HANDLER(PORTE_IRQHandler);
DEFINE_DEFAULT_IRQ_HANDLER(LPCMP1_IRQHandler);
DEFINE_DEFAULT_IRQ_HANDLER(RF0_0_IRQHandler);
DEFINE_DEFAULT_IRQ_HANDLER(RF0_1_IRQHandler);
DEFINE_DEFAULT_IRQ_HANDLER(INTMUX0_0_DriverIRQHandler);
DEFINE_DEFAULT_IRQ_HANDLER(INTMUX0_1_DriverIRQHandler);
DEFINE_DEFAULT_IRQ_HANDLER(INTMUX0_2_DriverIRQHandler);
DEFINE_DEFAULT_IRQ_HANDLER(INTMUX0_3_DriverIRQHandler);
DEFINE_DEFAULT_IRQ_HANDLER(INTMUX0_4_DriverIRQHandler);
DEFINE_DEFAULT_IRQ_HANDLER(INTMUX0_5_DriverIRQHandler);
DEFINE_DEFAULT_IRQ_HANDLER(INTMUX0_6_DriverIRQHandler);
DEFINE_DEFAULT_IRQ_HANDLER(INTMUX0_7_DriverIRQHandler);
DEFINE_DEFAULT_IRQ_HANDLER(INTMUX0_8_DriverIRQHandler);
DEFINE_IRQ_HANDLER(DMA0_0_4_8_12_IRQHandler, DMA0_0_4_8_12_DriverIRQHandler);
DEFINE_IRQ_HANDLER(DMA0_1_5_9_13_IRQHandler, DMA0_1_5_9_13_DriverIRQHandler);
DEFINE_IRQ_HANDLER(DMA0_2_6_10_14_IRQHandler, DMA0_2_6_10_14_DriverIRQHandler);
DEFINE_IRQ_HANDLER(DMA0_3_7_11_15_IRQHandler, DMA0_3_7_11_15_DriverIRQHandler);
DEFINE_IRQ_HANDLER(FLEXIO0_IRQHandler, FLEXIO0_DriverIRQHandler);
DEFINE_IRQ_HANDLER(LPI2C0_IRQHandler, LPI2C0_DriverIRQHandler);
DEFINE_IRQ_HANDLER(LPI2C1_IRQHandler, LPI2C1_DriverIRQHandler);
DEFINE_IRQ_HANDLER(LPI2C2_IRQHandler, LPI2C2_DriverIRQHandler);
DEFINE_IRQ_HANDLER(I2S0_IRQHandler, I2S0_DriverIRQHandler);
DEFINE_IRQ_HANDLER(USDHC0_IRQHandler, USDHC0_DriverIRQHandler);
DEFINE_IRQ_HANDLER(LPSPI0_IRQHandler, LPSPI0_DriverIRQHandler);
DEFINE_IRQ_HANDLER(LPSPI1_IRQHandler, LPSPI1_DriverIRQHandler);
DEFINE_IRQ_HANDLER(LPSPI2_IRQHandler, LPSPI2_DriverIRQHandler);
DEFINE_IRQ_HANDLER(LPUART0_IRQHandler, LPUART0_DriverIRQHandler);
DEFINE_IRQ_HANDLER(LPUART1_IRQHandler, LPUART1_DriverIRQHandler);
DEFINE_IRQ_HANDLER(LPUART2_IRQHandler, LPUART2_DriverIRQHandler);
DEFINE_IRQ_HANDLER(LPI2C3_IRQHandler, LPI2C3_DriverIRQHandler);
DEFINE_IRQ_HANDLER(LPSPI3_IRQHandler, LPSPI3_DriverIRQHandler);
DEFINE_IRQ_HANDLER(LPUART3_IRQHandler, LPUART3_DriverIRQHandler);
DEFINE_IRQ_HANDLER(INTMUX0_0_IRQHandler, INTMUX0_0_DriverIRQHandler);
DEFINE_IRQ_HANDLER(INTMUX0_1_IRQHandler, INTMUX0_1_DriverIRQHandler);
DEFINE_IRQ_HANDLER(INTMUX0_2_IRQHandler, INTMUX0_2_DriverIRQHandler);
DEFINE_IRQ_HANDLER(INTMUX0_3_IRQHandler, INTMUX0_3_DriverIRQHandler);
DEFINE_IRQ_HANDLER(INTMUX0_4_IRQHandler, INTMUX0_4_DriverIRQHandler);
DEFINE_IRQ_HANDLER(INTMUX0_5_IRQHandler, INTMUX0_5_DriverIRQHandler);
DEFINE_IRQ_HANDLER(INTMUX0_6_IRQHandler, INTMUX0_6_DriverIRQHandler);
DEFINE_IRQ_HANDLER(INTMUX0_7_IRQHandler, INTMUX0_7_DriverIRQHandler);
__attribute__((section("user_vectors"))) const irq_handler_t isrTable[] =
{
DMA0_0_4_8_12_IRQHandler,
DMA0_1_5_9_13_IRQHandler,
DMA0_2_6_10_14_IRQHandler,
DMA0_3_7_11_15_IRQHandler,
DMA0_Error_IRQHandler,
CMC0_IRQHandler,
MUA_IRQHandler,
USB0_IRQHandler,
USDHC0_IRQHandler,
I2S0_IRQHandler,
FLEXIO0_IRQHandler,
EMVSIM0_IRQHandler,
LPIT0_IRQHandler,
LPSPI0_IRQHandler,
LPSPI1_IRQHandler,
LPI2C0_IRQHandler,
LPI2C1_IRQHandler,
LPUART0_IRQHandler,
PORTA_IRQHandler,
TPM0_IRQHandler,
LPDAC0_IRQHandler,
ADC0_IRQHandler,
LPCMP0_IRQHandler,
RTC_IRQHandler,
INTMUX0_0_IRQHandler,
INTMUX0_1_IRQHandler,
INTMUX0_2_IRQHandler,
INTMUX0_3_IRQHandler,
INTMUX0_4_IRQHandler,
INTMUX0_5_IRQHandler,
INTMUX0_6_IRQHandler,
INTMUX0_7_IRQHandler,
EWM_IRQHandler,
FTFE_Command_Complete_IRQHandler,
FTFE_Read_Collision_IRQHandler,
LLWU0_IRQHandler,
SPM_IRQHandler,
WDOG0_IRQHandler,
SCG_IRQHandler,
LPTMR0_IRQHandler,
LPTMR1_IRQHandler,
TPM1_IRQHandler,
TPM2_IRQHandler,
LPI2C2_IRQHandler,
LPSPI2_IRQHandler,
LPUART1_IRQHandler,
LPUART2_IRQHandler,
PORTB_IRQHandler,
PORTC_IRQHandler,
PORTD_IRQHandler,
CAU3_Task_Complete_IRQHandler,
CAU3_Security_Violation_IRQHandler,
TRNG_IRQHandler,
LPIT1_IRQHandler,
LPTMR2_IRQHandler,
TPM3_IRQHandler,
LPI2C3_IRQHandler,
LPSPI3_IRQHandler,
LPUART3_IRQHandler,
PORTE_IRQHandler,
LPCMP1_IRQHandler,
RF0_0_IRQHandler,
RF0_1_IRQHandler,
};
extern uint32_t __VECTOR_TABLE[];
static uint32_t irqNesting = 0;
static void DefaultIRQHandler(void)
{
for (;;)
{
}
}
/* ----------------------------------------------------------------------------
-- SystemInit()
---------------------------------------------------------------------------- */
void SystemInit (void) {
#if (DISABLE_WDOG)
WDOG0->CNT = 0xD928C520U;
WDOG0->TOVAL = 0xFFFF;
WDOG0->CS = (uint32_t) ((WDOG0->CS) & ~WDOG_CS_EN_MASK) | WDOG_CS_UPDATE_MASK;
#endif /* (DISABLE_WDOG) */
SystemInitHook();
copy_section(&__etext, &__data_start__, &__data_end__);
zero_section(&__bss_start__, &__bss_end__);
/* Setup the vector table address. */
irqNesting = 0;
__ASM volatile("csrw 0x305, %0" :: "r"((uint32_t)__VECTOR_TABLE)); /* MTVEC */
__ASM volatile("csrw 0x005, %0" :: "r"((uint32_t)__VECTOR_TABLE)); /* UTVEC */
/* Clear all pending flags. */
EVENT_UNIT->INTPTPENDCLEAR = 0xFFFFFFFF;
EVENT_UNIT->EVTPENDCLEAR = 0xFFFFFFFF;
/* Set all interrupt as secure interrupt. */
EVENT_UNIT->INTPTSECURE = 0xFFFFFFFF;
}
/* ----------------------------------------------------------------------------
-- SystemCoreClockUpdate()
---------------------------------------------------------------------------- */
void SystemCoreClockUpdate (void) {
uint32_t SCGOUTClock; /* Variable to store output clock frequency of the SCG module */
uint16_t Divider;
Divider = ((SCG->CSR & SCG_CSR_DIVCORE_MASK) >> SCG_CSR_DIVCORE_SHIFT) + 1;
switch ((SCG->CSR & SCG_CSR_SCS_MASK) >> SCG_CSR_SCS_SHIFT) {
case 0x1:
/* System OSC */
SCGOUTClock = CPU_XTAL_CLK_HZ;
break;
case 0x2:
/* Slow IRC */
SCGOUTClock = (((SCG->SIRCCFG & SCG_SIRCCFG_RANGE_MASK) >> SCG_SIRCCFG_RANGE_SHIFT) ? 8000000 : 2000000);
break;
case 0x3:
/* Fast IRC */
SCGOUTClock = 48000000 + ((SCG->FIRCCFG & SCG_FIRCCFG_RANGE_MASK) >> SCG_FIRCCFG_RANGE_SHIFT) * 4000000;
break;
case 0x5:
/* Low Power FLL */
SCGOUTClock = 48000000 + ((SCG->LPFLLCFG & SCG_LPFLLCFG_FSEL_MASK) >> SCG_LPFLLCFG_FSEL_SHIFT) * 24000000;
break;
default:
return;
}
SystemCoreClock = (SCGOUTClock / Divider);
}
/* ----------------------------------------------------------------------------
-- SystemInitHook()
---------------------------------------------------------------------------- */
__attribute__ ((weak)) void SystemInitHook (void) {
/* Void implementation of the weak function. */
}
#if defined(__IAR_SYSTEMS_ICC__)
#pragma weak SystemIrqHandler
void SystemIrqHandler(uint32_t mcause) {
#elif defined(__GNUC__)
__attribute__((weak)) void SystemIrqHandler(uint32_t mcause) {
#else
#error Not supported compiler type
#endif
uint32_t intNum;
if (mcause & 0x80000000) /* For external interrupt. */
{
intNum = mcause & 0x1FUL;
irqNesting++;
/* Clear pending flag in EVENT unit .*/
EVENT_UNIT->INTPTPENDCLEAR = (1U << intNum);
/* Read back to make sure write finished. */
(void)(EVENT_UNIT->INTPTPENDCLEAR);
__enable_irq(); /* Support nesting interrupt */
/* Now call the real irq handler for intNum */
isrTable[intNum]();
__disable_irq();
irqNesting--;
}
}
/* Use LIPT0 channel 0 for systick. */
#define SYSTICK_LPIT LPIT0
#define SYSTICK_LPIT_CH 0
#define SYSTICK_LPIT_IRQn LPIT0_IRQn
/* Leverage LPIT0 to provide Systick */
void SystemSetupSystick(uint32_t tickRateHz, uint32_t intPriority)
{
/* Init pit module */
CLOCK_EnableClock(kCLOCK_Lpit0);
/* Reset the timer channels and registers except the MCR register */
SYSTICK_LPIT->MCR |= LPIT_MCR_SW_RST_MASK;
SYSTICK_LPIT->MCR &= ~LPIT_MCR_SW_RST_MASK;
/* Setup timer operation in debug and doze modes and enable the module */
SYSTICK_LPIT->MCR = LPIT_MCR_DBG_EN_MASK | LPIT_MCR_DOZE_EN_MASK | LPIT_MCR_M_CEN_MASK;
/* Set timer period for channel 0 */
SYSTICK_LPIT->CHANNEL[SYSTICK_LPIT_CH].TVAL = (CLOCK_GetIpFreq(kCLOCK_Lpit0) / tickRateHz) - 1;
/* Enable timer interrupts for channel 0 */
SYSTICK_LPIT->MIER |= (1U << SYSTICK_LPIT_CH);
/* Set interrupt priority. */
EVENT_SetIRQPriority(SYSTICK_LPIT_IRQn, intPriority);
/* Enable interrupt at the EVENT unit */
EnableIRQ(SYSTICK_LPIT_IRQn);
/* Start channel 0 */
SYSTICK_LPIT->SETTEN |= (LPIT_SETTEN_SET_T_EN_0_MASK << SYSTICK_LPIT_CH);
}
uint32_t SystemGetIRQNestingLevel(void)
{
return irqNesting;
}
void SystemClearSystickFlag(void)
{
/* Channel 0. */
SYSTICK_LPIT->MSR = (1U << SYSTICK_LPIT_CH);
}
void EVENT_SetIRQPriority(IRQn_Type IRQn, uint8_t intPriority)
{
uint8_t regIdx;
uint8_t regOffset;
if ((IRQn < 32) && (intPriority < 8))
{
/*
* 4 priority control registers, each register controls 8 interrupts.
* Bit 0-2: interrupt 0
* Bit 4-7: interrupt 1
* ...
* Bit 28-30: interrupt 7
*/
regIdx = IRQn >> 3U;
regOffset = (IRQn & 0x07U) * 4U;
EVENT_UNIT->INTPTPRI[regIdx] = (EVENT_UNIT->INTPTPRI[regIdx] & ~(0x0F << regOffset)) | (intPriority << regOffset);
}
}
uint8_t EVENT_GetIRQPriority(IRQn_Type IRQn)
{
uint8_t regIdx;
uint8_t regOffset;
int32_t intPriority;
if ((IRQn < 32))
{
/*
* 4 priority control registers, each register controls 8 interrupts.
* Bit 0-2: interrupt 0
* Bit 4-7: interrupt 1
* ...
* Bit 28-30: interrupt 7
*/
regIdx = IRQn >> 3U;
regOffset = (IRQn & 0x07U) << 2U;
intPriority = (EVENT_UNIT->INTPTPRI[regIdx] >> regOffset) & 0xF;
return (uint8_t)intPriority;
}
return 0;
}
bool SystemInISR(void)
{
return ((EVENT_UNIT->INTPTENACTIVE) != 0);;
}
void EVENT_SystemReset(void)
{
EVENT_UNIT->SLPCTRL |= EVENT_SLPCTRL_SYSRSTREQST_MASK;
}

View File

@ -0,0 +1,182 @@
/*
** ###################################################################
** Processors: RV32M1_ri5cy
** RV32M1_ri5cy
**
** Compilers: Keil ARM C/C++ Compiler
** GNU C Compiler
** IAR ANSI C/C++ Compiler for ARM
** MCUXpresso Compiler
**
** Reference manual: RV32M1 Series Reference Manual, Rev. 1 , 8/10/2018
** Version: rev. 1.0, 2018-10-02
** Build: b180926
**
** Abstract:
** Provides a system configuration function and a global variable that
** contains the system frequency. It configures the device and initializes
** the oscillator (PLL) that is part of the microcontroller device.
**
** Copyright 2016 Freescale Semiconductor, Inc.
** Copyright 2016-2018 NXP
** All rights reserved.
**
** SPDX-License-Identifier: BSD-3-Clause
**
** http: www.nxp.com
** mail: support@nxp.com
**
** Revisions:
** - rev. 1.0 (2018-10-02)
** Initial version.
**
** ###################################################################
*/
/*!
* @file RV32M1_ri5cy
* @version 1.0
* @date 2018-10-02
* @brief Device specific configuration file for RV32M1_ri5cy (header file)
*
* Provides a system configuration function and a global variable that contains
* the system frequency. It configures the device and initializes the oscillator
* (PLL) that is part of the microcontroller device.
*/
#ifndef _SYSTEM_RV32M1_ri5cy_H_
#define _SYSTEM_RV32M1_ri5cy_H_ /**< Symbol preventing repeated inclusion */
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h>
#include <stdbool.h>
#ifndef DISABLE_WDOG
#define DISABLE_WDOG 1
#endif
/* Define clock source values */
#define CPU_XTAL_CLK_HZ 8000000u /* Value of the external crystal or oscillator clock frequency in Hz */
/* Low power mode enable */
/* SMC_PMPROT: AHSRUN=1, AVLP=1,ALLS=1,AVLLS=0x3 */
#define SYSTEM_SMC_PMPROT_VALUE 0xABu /* SMC_PMPROT */
#define SYSTEM_SMC_PMCTRL_VALUE 0x0u /* SMC_PMCTRL */
#define DEFAULT_SYSTEM_CLOCK 48000000u /* Default System clock value */
/**
* @brief System clock frequency (core clock)
*
* The system clock frequency supplied to the SysTick timer and the processor
* core clock. This variable can be used by the user application to setup the
* SysTick timer or configure other parameters. It may also be used by debugger to
* query the frequency of the debug timer or configure the trace clock speed
* SystemCoreClock is initialized with a correct predefined value.
*/
extern uint32_t SystemCoreClock;
/**
* @brief Setup the microcontroller system.
*
* Typically this function configures the oscillator (PLL) that is part of the
* microcontroller device. For systems with variable clock speed it also updates
* the variable SystemCoreClock. SystemInit is called from startup_device file.
*/
void SystemInit (void);
/**
* @brief Updates the SystemCoreClock variable.
*
* It must be called whenever the core clock is changed during program
* execution. SystemCoreClockUpdate() evaluates the clock register settings and calculates
* the current core clock.
*/
void SystemCoreClockUpdate (void);
/**
* @brief SystemInit function hook.
*
* This weak function allows to call specific initialization code during the
* SystemInit() execution.This can be used when an application specific code needs
* to be called as close to the reset entry as possible (for example the Multicore
* Manager MCMGR_EarlyInit() function call).
* NOTE: No global r/w variables can be used in this hook function because the
* initialization of these variables happens after this function.
*/
void SystemInitHook (void);
/**
* @brief System IRQ handler which dispatches specific IRQ to corresponding registered handler.
*
* It is called from IRQ exception context and dispatches to registered handler according to
* MCAUSE interrupt number.
*
* @param mcause IRQ acknowledge value read from MCAUSE
*/
void SystemIrqHandler(uint32_t mcause);
/**
* @brief Get IRQ nesting level of current context.
*
* If the return value is 0, then the context is not ISR, otherwise the context is ISR.
*
* @return IRQ nesting level
*/
uint32_t SystemGetIRQNestingLevel (void);
/**
* @brief Setup systick for RTOS system.
*
* @param tickRateHz Tick number per second
* @param intPriority IRQ interrupt priority (the smaller, the higher priority)
*/
void SystemSetupSystick (uint32_t tickRateHz, uint32_t intPriority);
/**
* @brief Clear systick flag status so that next tick interrupt may occur.
*/
void SystemClearSystickFlag (void);
/**
* @brief Sysem is in ISR or not.
*/
bool SystemInISR(void);
#define SysTick_Handler LPIT0_IRQHandler
/**
* @brief Set interrupt priority in Event unit.
*/
void EVENT_SetIRQPriority(IRQn_Type IRQn, uint8_t intPriority);
/**
* @brief Get interrupt priority in Event unit.
*/
uint8_t EVENT_GetIRQPriority(IRQn_Type IRQn);
/**
* @brief Reset the system.
*/
void EVENT_SystemReset(void);
#define NVIC_SystemReset EVENT_SystemReset
/* Priority setting macro remap. */
#define NVIC_SetPriority EVENT_SetIRQPriority
/* Priority getting macro remap. */
#define NVIC_GetPriority EVENT_GetIRQPriority
#ifdef __cplusplus
}
#endif
#endif /* _SYSTEM_RV32M1_ri5cy_H_ */

View File

@ -0,0 +1,535 @@
/*
** ###################################################################
** Processors: RV32M1_zero_riscy
** RV32M1_zero_riscy
**
** Compilers: Keil ARM C/C++ Compiler
** GNU C Compiler
** IAR ANSI C/C++ Compiler for ARM
** MCUXpresso Compiler
**
** Reference manual: RV32M1 Series Reference Manual, Rev. 1 , 8/10/2018
** Version: rev. 1.0, 2018-10-02
** Build: b180926
**
** Abstract:
** Provides a system configuration function and a global variable that
** contains the system frequency. It configures the device and initializes
** the oscillator (PLL) that is part of the microcontroller device.
**
** Copyright 2016 Freescale Semiconductor, Inc.
** Copyright 2016-2018 NXP
** All rights reserved.
**
** SPDX-License-Identifier: BSD-3-Clause
**
** http: www.nxp.com
** mail: support@nxp.com
**
** Revisions:
** - rev. 1.0 (2018-10-02)
** Initial version.
**
** ###################################################################
*/
/*!
* @file RV32M1_zero_riscy
* @version 1.0
* @date 2018-10-02
* @brief Device specific configuration file for RV32M1_zero_riscy
* (implementation file)
*
* Provides a system configuration function and a global variable that contains
* the system frequency. It configures the device and initializes the oscillator
* (PLL) that is part of the microcontroller device.
*/
#include <stdint.h>
#include "fsl_device_registers.h"
#include "fsl_common.h"
typedef void (*irq_handler_t)(void);
extern void CTI1_IRQHandler(void);
extern void DMA1_04_DriverIRQHandler(void);
extern void DMA1_15_DriverIRQHandler(void);
extern void DMA1_26_DriverIRQHandler(void);
extern void DMA1_37_DriverIRQHandler(void);
extern void DMA1_Error_DriverIRQHandler(void);
extern void CMC1_IRQHandler(void);
extern void LLWU1_IRQHandler(void);
extern void MUB_IRQHandler(void);
extern void WDOG1_IRQHandler(void);
extern void CAU3_Task_Complete_IRQHandler(void);
extern void CAU3_Security_Violation_IRQHandler(void);
extern void TRNG_IRQHandler(void);
extern void LPIT1_IRQHandler(void);
extern void LPTMR2_IRQHandler(void);
extern void TPM3_IRQHandler(void);
extern void LPI2C3_DriverIRQHandler(void);
extern void RF0_0_IRQHandler(void);
extern void RF0_1_IRQHandler(void);
extern void LPSPI3_DriverIRQHandler(void);
extern void LPUART3_DriverIRQHandler(void);
extern void PORTE_IRQHandler(void);
extern void LPCMP1_IRQHandler(void);
extern void RTC_IRQHandler(void);
extern void INTMUX1_0_DriverIRQHandler(void);
extern void INTMUX1_1_DriverIRQHandler(void);
extern void INTMUX1_2_DriverIRQHandler(void);
extern void INTMUX1_3_DriverIRQHandler(void);
extern void INTMUX1_4_DriverIRQHandler(void);
extern void INTMUX1_5_DriverIRQHandler(void);
extern void INTMUX1_6_DriverIRQHandler(void);
extern void INTMUX1_7_DriverIRQHandler(void);
extern void EWM_IRQHandler(void);
extern void FTFE_Command_Complete_IRQHandler(void);
extern void FTFE_Read_Collision_IRQHandler(void);
extern void SPM_IRQHandler(void);
extern void SCG_IRQHandler(void);
extern void LPIT0_IRQHandler(void);
extern void LPTMR0_IRQHandler(void);
extern void LPTMR1_IRQHandler(void);
extern void TPM0_IRQHandler(void);
extern void TPM1_IRQHandler(void);
extern void TPM2_IRQHandler(void);
extern void EMVSIM0_IRQHandler(void);
extern void FLEXIO0_DriverIRQHandler(void);
extern void LPI2C0_DriverIRQHandler(void);
extern void LPI2C1_DriverIRQHandler(void);
extern void LPI2C2_DriverIRQHandler(void);
extern void I2S0_DriverIRQHandler(void);
extern void USDHC0_DriverIRQHandler(void);
extern void LPSPI0_DriverIRQHandler(void);
extern void LPSPI1_DriverIRQHandler(void);
extern void LPSPI2_DriverIRQHandler(void);
extern void LPUART0_DriverIRQHandler(void);
extern void LPUART1_DriverIRQHandler(void);
extern void LPUART2_DriverIRQHandler(void);
extern void USB0_IRQHandler(void);
extern void PORTA_IRQHandler(void);
extern void PORTB_IRQHandler(void);
extern void PORTC_IRQHandler(void);
extern void PORTD_IRQHandler(void);
extern void ADC0_IRQHandler(void);
extern void LPCMP0_IRQHandler(void);
extern void LPDAC0_IRQHandler(void);
extern void DMA1_15_IRQHandler(void);
extern void DMA1_26_IRQHandler(void);
extern void DMA1_37_IRQHandler(void);
extern void DMA1_Error_IRQHandler(void);
extern void LPI2C3_IRQHandler(void);
extern void LPSPI3_IRQHandler(void);
extern void LPUART3_IRQHandler(void);
extern void INTMUX1_0_IRQHandler(void);
extern void INTMUX1_1_IRQHandler(void);
extern void INTMUX1_2_IRQHandler(void);
extern void INTMUX1_3_IRQHandler(void);
extern void INTMUX1_4_IRQHandler(void);
extern void INTMUX1_5_IRQHandler(void);
extern void INTMUX1_6_IRQHandler(void);
extern void INTMUX1_7_IRQHandler(void);
extern void FLEXIO0_IRQHandler(void);
extern void LPI2C0_IRQHandler(void);
extern void LPI2C1_IRQHandler(void);
extern void LPI2C2_IRQHandler(void);
extern void I2S0_IRQHandler(void);
extern void USDHC0_IRQHandler(void);
extern void LPSPI0_IRQHandler(void);
extern void LPSPI1_IRQHandler(void);
extern void LPSPI2_IRQHandler(void);
extern void LPUART0_IRQHandler(void);
extern void LPUART1_IRQHandler(void);
extern void LPUART2_IRQHandler(void);
/* ----------------------------------------------------------------------------
-- Core clock
---------------------------------------------------------------------------- */
uint32_t SystemCoreClock = DEFAULT_SYSTEM_CLOCK;
extern uint32_t __etext;
extern uint32_t __data_start__;
extern uint32_t __data_end__;
extern uint32_t __bss_start__;
extern uint32_t __bss_end__;
static void copy_section(uint32_t * p_load, uint32_t * p_vma, uint32_t * p_vma_end)
{
while(p_vma <= p_vma_end)
{
*p_vma = *p_load;
++p_load;
++p_vma;
}
}
static void zero_section(uint32_t * start, uint32_t * end)
{
uint32_t * p_zero = start;
while(p_zero <= end)
{
*p_zero = 0;
++p_zero;
}
}
#define DEFINE_IRQ_HANDLER(irq_handler, driver_irq_handler) \
void __attribute__((weak)) irq_handler(void) { driver_irq_handler();}
#define DEFINE_DEFAULT_IRQ_HANDLER(irq_handler) void irq_handler() __attribute__((weak, alias("DefaultIRQHandler")))
DEFINE_DEFAULT_IRQ_HANDLER(CTI1_IRQHandler);
DEFINE_DEFAULT_IRQ_HANDLER(DMA1_04_DriverIRQHandler);
DEFINE_DEFAULT_IRQ_HANDLER(DMA1_15_DriverIRQHandler);
DEFINE_DEFAULT_IRQ_HANDLER(DMA1_26_DriverIRQHandler);
DEFINE_DEFAULT_IRQ_HANDLER(DMA1_37_DriverIRQHandler);
DEFINE_DEFAULT_IRQ_HANDLER(DMA1_Error_DriverIRQHandler);
DEFINE_DEFAULT_IRQ_HANDLER(CMC1_IRQHandler);
DEFINE_DEFAULT_IRQ_HANDLER(LLWU1_IRQHandler);
DEFINE_DEFAULT_IRQ_HANDLER(MUB_IRQHandler);
DEFINE_DEFAULT_IRQ_HANDLER(WDOG1_IRQHandler);
DEFINE_DEFAULT_IRQ_HANDLER(CAU3_Task_Complete_IRQHandler);
DEFINE_DEFAULT_IRQ_HANDLER(CAU3_Security_Violation_IRQHandler);
DEFINE_DEFAULT_IRQ_HANDLER(TRNG_IRQHandler);
DEFINE_DEFAULT_IRQ_HANDLER(LPIT1_IRQHandler);
DEFINE_DEFAULT_IRQ_HANDLER(LPTMR2_IRQHandler);
DEFINE_DEFAULT_IRQ_HANDLER(TPM3_IRQHandler);
DEFINE_DEFAULT_IRQ_HANDLER(LPI2C3_DriverIRQHandler);
DEFINE_DEFAULT_IRQ_HANDLER(RF0_0_IRQHandler);
DEFINE_DEFAULT_IRQ_HANDLER(RF0_1_IRQHandler);
DEFINE_DEFAULT_IRQ_HANDLER(LPSPI3_DriverIRQHandler);
DEFINE_DEFAULT_IRQ_HANDLER(LPUART3_DriverIRQHandler);
DEFINE_DEFAULT_IRQ_HANDLER(PORTE_IRQHandler);
DEFINE_DEFAULT_IRQ_HANDLER(LPCMP1_IRQHandler);
DEFINE_DEFAULT_IRQ_HANDLER(RTC_IRQHandler);
DEFINE_DEFAULT_IRQ_HANDLER(INTMUX1_0_DriverIRQHandler);
DEFINE_DEFAULT_IRQ_HANDLER(INTMUX1_1_DriverIRQHandler);
DEFINE_DEFAULT_IRQ_HANDLER(INTMUX1_2_DriverIRQHandler);
DEFINE_DEFAULT_IRQ_HANDLER(INTMUX1_3_DriverIRQHandler);
DEFINE_DEFAULT_IRQ_HANDLER(INTMUX1_4_DriverIRQHandler);
DEFINE_DEFAULT_IRQ_HANDLER(INTMUX1_5_DriverIRQHandler);
DEFINE_DEFAULT_IRQ_HANDLER(INTMUX1_6_DriverIRQHandler);
DEFINE_DEFAULT_IRQ_HANDLER(INTMUX1_7_DriverIRQHandler);
DEFINE_DEFAULT_IRQ_HANDLER(EWM_IRQHandler);
DEFINE_DEFAULT_IRQ_HANDLER(FTFE_Command_Complete_IRQHandler);
DEFINE_DEFAULT_IRQ_HANDLER(FTFE_Read_Collision_IRQHandler);
DEFINE_DEFAULT_IRQ_HANDLER(SPM_IRQHandler);
DEFINE_DEFAULT_IRQ_HANDLER(SCG_IRQHandler);
DEFINE_DEFAULT_IRQ_HANDLER(LPIT0_IRQHandler);
DEFINE_DEFAULT_IRQ_HANDLER(LPTMR0_IRQHandler);
DEFINE_DEFAULT_IRQ_HANDLER(LPTMR1_IRQHandler);
DEFINE_DEFAULT_IRQ_HANDLER(TPM0_IRQHandler);
DEFINE_DEFAULT_IRQ_HANDLER(TPM1_IRQHandler);
DEFINE_DEFAULT_IRQ_HANDLER(TPM2_IRQHandler);
DEFINE_DEFAULT_IRQ_HANDLER(EMVSIM0_IRQHandler);
DEFINE_DEFAULT_IRQ_HANDLER(FLEXIO0_DriverIRQHandler);
DEFINE_DEFAULT_IRQ_HANDLER(LPI2C0_DriverIRQHandler);
DEFINE_DEFAULT_IRQ_HANDLER(LPI2C1_DriverIRQHandler);
DEFINE_DEFAULT_IRQ_HANDLER(LPI2C2_DriverIRQHandler);
DEFINE_DEFAULT_IRQ_HANDLER(I2S0_DriverIRQHandler);
DEFINE_DEFAULT_IRQ_HANDLER(USDHC0_DriverIRQHandler);
DEFINE_DEFAULT_IRQ_HANDLER(LPSPI0_DriverIRQHandler);
DEFINE_DEFAULT_IRQ_HANDLER(LPSPI1_DriverIRQHandler);
DEFINE_DEFAULT_IRQ_HANDLER(LPSPI2_DriverIRQHandler);
DEFINE_DEFAULT_IRQ_HANDLER(LPUART0_DriverIRQHandler);
DEFINE_DEFAULT_IRQ_HANDLER(LPUART1_DriverIRQHandler);
DEFINE_DEFAULT_IRQ_HANDLER(LPUART2_DriverIRQHandler);
DEFINE_DEFAULT_IRQ_HANDLER(USB0_IRQHandler);
DEFINE_DEFAULT_IRQ_HANDLER(PORTA_IRQHandler);
DEFINE_DEFAULT_IRQ_HANDLER(PORTB_IRQHandler);
DEFINE_DEFAULT_IRQ_HANDLER(PORTC_IRQHandler);
DEFINE_DEFAULT_IRQ_HANDLER(PORTD_IRQHandler);
DEFINE_DEFAULT_IRQ_HANDLER(ADC0_IRQHandler);
DEFINE_DEFAULT_IRQ_HANDLER(LPCMP0_IRQHandler);
DEFINE_DEFAULT_IRQ_HANDLER(LPDAC0_IRQHandler);
DEFINE_IRQ_HANDLER(DMA1_04_IRQHandler, DMA1_04_DriverIRQHandler);
DEFINE_IRQ_HANDLER(DMA1_15_IRQHandler, DMA1_15_DriverIRQHandler);
DEFINE_IRQ_HANDLER(DMA1_26_IRQHandler, DMA1_26_DriverIRQHandler);
DEFINE_IRQ_HANDLER(DMA1_37_IRQHandler, DMA1_37_DriverIRQHandler);
DEFINE_IRQ_HANDLER(DMA1_Error_IRQHandler, DMA1_Error_DriverIRQHandler);
DEFINE_IRQ_HANDLER(LPI2C3_IRQHandler, LPI2C3_DriverIRQHandler);
DEFINE_IRQ_HANDLER(LPSPI3_IRQHandler, LPSPI3_DriverIRQHandler);
DEFINE_IRQ_HANDLER(LPUART3_IRQHandler, LPUART3_DriverIRQHandler);
DEFINE_IRQ_HANDLER(INTMUX1_0_IRQHandler, INTMUX1_0_DriverIRQHandler);
DEFINE_IRQ_HANDLER(INTMUX1_1_IRQHandler, INTMUX1_1_DriverIRQHandler);
DEFINE_IRQ_HANDLER(INTMUX1_2_IRQHandler, INTMUX1_2_DriverIRQHandler);
DEFINE_IRQ_HANDLER(INTMUX1_3_IRQHandler, INTMUX1_3_DriverIRQHandler);
DEFINE_IRQ_HANDLER(INTMUX1_4_IRQHandler, INTMUX1_4_DriverIRQHandler);
DEFINE_IRQ_HANDLER(INTMUX1_5_IRQHandler, INTMUX1_5_DriverIRQHandler);
DEFINE_IRQ_HANDLER(INTMUX1_6_IRQHandler, INTMUX1_6_DriverIRQHandler);
DEFINE_IRQ_HANDLER(INTMUX1_7_IRQHandler, INTMUX1_7_DriverIRQHandler);
DEFINE_IRQ_HANDLER(FLEXIO0_IRQHandler, FLEXIO0_DriverIRQHandler);
DEFINE_IRQ_HANDLER(LPI2C0_IRQHandler, LPI2C0_DriverIRQHandler);
DEFINE_IRQ_HANDLER(LPI2C1_IRQHandler, LPI2C1_DriverIRQHandler);
DEFINE_IRQ_HANDLER(LPI2C2_IRQHandler, LPI2C2_DriverIRQHandler);
DEFINE_IRQ_HANDLER(I2S0_IRQHandler, I2S0_DriverIRQHandler);
DEFINE_IRQ_HANDLER(USDHC0_IRQHandler, USDHC0_DriverIRQHandler);
DEFINE_IRQ_HANDLER(LPSPI0_IRQHandler, LPSPI0_DriverIRQHandler);
DEFINE_IRQ_HANDLER(LPSPI1_IRQHandler, LPSPI1_DriverIRQHandler);
DEFINE_IRQ_HANDLER(LPSPI2_IRQHandler, LPSPI2_DriverIRQHandler);
DEFINE_IRQ_HANDLER(LPUART0_IRQHandler, LPUART0_DriverIRQHandler);
DEFINE_IRQ_HANDLER(LPUART1_IRQHandler, LPUART1_DriverIRQHandler);
DEFINE_IRQ_HANDLER(LPUART2_IRQHandler, LPUART2_DriverIRQHandler);
__attribute__((section("user_vectors"))) const irq_handler_t isrTable[] =
{
CTI1_IRQHandler,
DMA1_04_IRQHandler,
DMA1_15_IRQHandler,
DMA1_26_IRQHandler,
DMA1_37_IRQHandler,
DMA1_Error_IRQHandler,
CMC1_IRQHandler,
LLWU1_IRQHandler,
MUB_IRQHandler,
WDOG1_IRQHandler,
CAU3_Task_Complete_IRQHandler,
CAU3_Security_Violation_IRQHandler,
TRNG_IRQHandler,
LPIT1_IRQHandler,
LPTMR2_IRQHandler,
TPM3_IRQHandler,
LPI2C3_IRQHandler,
RF0_0_IRQHandler,
RF0_1_IRQHandler,
LPSPI3_IRQHandler,
LPUART3_IRQHandler,
PORTE_IRQHandler,
LPCMP1_IRQHandler,
RTC_IRQHandler,
INTMUX1_0_IRQHandler,
INTMUX1_1_IRQHandler,
INTMUX1_2_IRQHandler,
INTMUX1_3_IRQHandler,
INTMUX1_4_IRQHandler,
INTMUX1_5_IRQHandler,
INTMUX1_6_IRQHandler,
INTMUX1_7_IRQHandler,
EWM_IRQHandler,
FTFE_Command_Complete_IRQHandler,
FTFE_Read_Collision_IRQHandler,
SPM_IRQHandler,
SCG_IRQHandler,
LPIT0_IRQHandler,
LPTMR0_IRQHandler,
LPTMR1_IRQHandler,
TPM0_IRQHandler,
TPM1_IRQHandler,
TPM2_IRQHandler,
EMVSIM0_IRQHandler,
FLEXIO0_IRQHandler,
LPI2C0_IRQHandler,
LPI2C1_IRQHandler,
LPI2C2_IRQHandler,
I2S0_IRQHandler,
USDHC0_IRQHandler,
LPSPI0_IRQHandler,
LPSPI1_IRQHandler,
LPSPI2_IRQHandler,
LPUART0_IRQHandler,
LPUART1_IRQHandler,
LPUART2_IRQHandler,
USB0_IRQHandler,
PORTA_IRQHandler,
PORTB_IRQHandler,
PORTC_IRQHandler,
PORTD_IRQHandler,
ADC0_IRQHandler,
LPCMP0_IRQHandler,
LPDAC0_IRQHandler,
};
extern uint32_t __VECTOR_TABLE[];
static uint32_t irqNesting = 0;
static void DefaultIRQHandler(void)
{
for (;;)
{
}
}
/* ----------------------------------------------------------------------------
-- SystemInit()
---------------------------------------------------------------------------- */
void SystemInit (void) {
#if (DISABLE_WDOG)
WDOG1->CNT = 0xD928C520U;
WDOG1->TOVAL = 0xFFFF;
WDOG1->CS = (uint32_t) ((WDOG1->CS) & ~WDOG_CS_EN_MASK) | WDOG_CS_UPDATE_MASK;
#endif /* (DISABLE_WDOG) */
SystemInitHook();
copy_section(&__etext, &__data_start__, &__data_end__);
zero_section(&__bss_start__, &__bss_end__);
/* Setup the vector table address. */
irqNesting = 0;
__ASM volatile("csrw 0x305, %0" :: "r"((uint32_t)__VECTOR_TABLE)); /* MTVEC */
__ASM volatile("csrw 0x005, %0" :: "r"((uint32_t)__VECTOR_TABLE)); /* UTVEC */
/* Clear all pending flags. */
EVENT_UNIT->INTPTPENDCLEAR = 0xFFFFFFFF;
EVENT_UNIT->EVTPENDCLEAR = 0xFFFFFFFF;
/* Set all interrupt as secure interrupt. */
EVENT_UNIT->INTPTSECURE = 0xFFFFFFFF;
}
/* ----------------------------------------------------------------------------
-- SystemCoreClockUpdate()
---------------------------------------------------------------------------- */
void SystemCoreClockUpdate (void) {
uint32_t SCGOUTClock; /* Variable to store output clock frequency of the SCG module */
uint16_t Divider;
Divider = ((SCG->CSR & SCG_CSR_DIVCORE_MASK) >> SCG_CSR_DIVCORE_SHIFT) + 1;
switch ((SCG->CSR & SCG_CSR_SCS_MASK) >> SCG_CSR_SCS_SHIFT) {
case 0x1:
/* System OSC */
SCGOUTClock = CPU_XTAL_CLK_HZ;
break;
case 0x2:
/* Slow IRC */
SCGOUTClock = (((SCG->SIRCCFG & SCG_SIRCCFG_RANGE_MASK) >> SCG_SIRCCFG_RANGE_SHIFT) ? 8000000 : 2000000);
break;
case 0x3:
/* Fast IRC */
SCGOUTClock = 48000000 + ((SCG->FIRCCFG & SCG_FIRCCFG_RANGE_MASK) >> SCG_FIRCCFG_RANGE_SHIFT) * 4000000;
break;
case 0x5:
/* Low Power FLL */
SCGOUTClock = 48000000 + ((SCG->LPFLLCFG & SCG_LPFLLCFG_FSEL_MASK) >> SCG_LPFLLCFG_FSEL_SHIFT) * 24000000;
break;
default:
return;
}
SystemCoreClock = (SCGOUTClock / Divider);
}
/* ----------------------------------------------------------------------------
-- SystemInitHook()
---------------------------------------------------------------------------- */
__attribute__ ((weak)) void SystemInitHook (void) {
/* Void implementation of the weak function. */
}
#if defined(__IAR_SYSTEMS_ICC__)
#pragma weak SystemIrqHandler
void SystemIrqHandler(uint32_t mcause) {
#elif defined(__GNUC__)
__attribute__((weak)) void SystemIrqHandler(uint32_t mcause) {
#else
#error Not supported compiler type
#endif
uint32_t intNum;
if (mcause & 0x80000000) /* For external interrupt. */
{
intNum = mcause & 0x1FUL;
irqNesting++;
/* Clear pending flag in EVENT unit .*/
EVENT_UNIT->INTPTPENDCLEAR = (1U << intNum);
/* Read back to make sure write finished. */
(void)(EVENT_UNIT->INTPTPENDCLEAR);
__enable_irq(); /* Support nesting interrupt */
/* Now call the real irq handler for intNum */
isrTable[intNum]();
__disable_irq();
irqNesting--;
}
}
/* Use LIPT1 channel 0 for systick. */
#define SYSTICK_LPIT LPIT1
#define SYSTICK_LPIT_CH 0
#define SYSTICK_LPIT_IRQn LPIT1_IRQn
/* Leverage LPIT0 to provide Systick */
void SystemSetupSystick(uint32_t tickRateHz, uint32_t intPriority)
{
/* Init pit module */
CLOCK_EnableClock(kCLOCK_Lpit1);
/* Reset the timer channels and registers except the MCR register */
SYSTICK_LPIT->MCR |= LPIT_MCR_SW_RST_MASK;
SYSTICK_LPIT->MCR &= ~LPIT_MCR_SW_RST_MASK;
/* Setup timer operation in debug and doze modes and enable the module */
SYSTICK_LPIT->MCR = LPIT_MCR_DBG_EN_MASK | LPIT_MCR_DOZE_EN_MASK | LPIT_MCR_M_CEN_MASK;
/* Set timer period for channel 0 */
SYSTICK_LPIT->CHANNEL[SYSTICK_LPIT_CH].TVAL = (CLOCK_GetIpFreq(kCLOCK_Lpit1) / tickRateHz) - 1;
/* Enable timer interrupts for channel 0 */
SYSTICK_LPIT->MIER |= (1U << SYSTICK_LPIT_CH);
/* Set interrupt priority. */
EVENT_SetIRQPriority(SYSTICK_LPIT_IRQn, intPriority);
/* Enable interrupt at the EVENT unit */
EnableIRQ(SYSTICK_LPIT_IRQn);
/* Start channel 0 */
SYSTICK_LPIT->SETTEN |= (LPIT_SETTEN_SET_T_EN_0_MASK << SYSTICK_LPIT_CH);
}
uint32_t SystemGetIRQNestingLevel(void)
{
return irqNesting;
}
void SystemClearSystickFlag(void)
{
/* Channel 0. */
SYSTICK_LPIT->MSR = (1U << SYSTICK_LPIT_CH);
}
void EVENT_SetIRQPriority(IRQn_Type IRQn, uint8_t intPriority)
{
uint8_t regIdx;
uint8_t regOffset;
if ((IRQn < 32) && (intPriority < 8))
{
/*
* 4 priority control registers, each register controls 8 interrupts.
* Bit 0-2: interrupt 0
* Bit 4-7: interrupt 1
* ...
* Bit 28-30: interrupt 7
*/
regIdx = IRQn >> 3U;
regOffset = (IRQn & 0x07U) * 4U;
EVENT_UNIT->INTPTPRI[regIdx] = (EVENT_UNIT->INTPTPRI[regIdx] & ~(0x0F << regOffset)) | (intPriority << regOffset);
}
}
bool SystemInISR(void)
{
return ((EVENT_UNIT->INTPTENACTIVE) != 0);;
}
void EVENT_SystemReset(void)
{
EVENT_UNIT->SLPCTRL |= EVENT_SLPCTRL_SYSRSTREQST_MASK;
}

View File

@ -0,0 +1,174 @@
/*
** ###################################################################
** Processors: RV32M1_zero_riscy
** RV32M1_zero_riscy
**
** Compilers: Keil ARM C/C++ Compiler
** GNU C Compiler
** IAR ANSI C/C++ Compiler for ARM
** MCUXpresso Compiler
**
** Reference manual: RV32M1 Series Reference Manual, Rev. 1 , 8/10/2018
** Version: rev. 1.0, 2018-10-02
** Build: b180926
**
** Abstract:
** Provides a system configuration function and a global variable that
** contains the system frequency. It configures the device and initializes
** the oscillator (PLL) that is part of the microcontroller device.
**
** Copyright 2016 Freescale Semiconductor, Inc.
** Copyright 2016-2018 NXP
** All rights reserved.
**
** SPDX-License-Identifier: BSD-3-Clause
**
** http: www.nxp.com
** mail: support@nxp.com
**
** Revisions:
** - rev. 1.0 (2018-10-02)
** Initial version.
**
** ###################################################################
*/
/*!
* @file RV32M1_zero_riscy
* @version 1.0
* @date 2018-10-02
* @brief Device specific configuration file for RV32M1_zero_riscy (header
* file)
*
* Provides a system configuration function and a global variable that contains
* the system frequency. It configures the device and initializes the oscillator
* (PLL) that is part of the microcontroller device.
*/
#ifndef _SYSTEM_RV32M1_zero_riscy_H_
#define _SYSTEM_RV32M1_zero_riscy_H_ /**< Symbol preventing repeated inclusion */
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h>
#include <stdbool.h>
#ifndef DISABLE_WDOG
#define DISABLE_WDOG 1
#endif
/* Define clock source values */
#define CPU_XTAL_CLK_HZ 8000000u /* Value of the external crystal or oscillator clock frequency in Hz */
/* Low power mode enable */
/* SMC_PMPROT: AHSRUN=1, AVLP=1,ALLS=1,AVLLS=0x3 */
#define SYSTEM_SMC_PMPROT_VALUE 0xABu /* SMC_PMPROT */
#define SYSTEM_SMC_PMCTRL_VALUE 0x0u /* SMC_PMCTRL */
#define DEFAULT_SYSTEM_CLOCK 48000000u /* Default System clock value */
/**
* @brief System clock frequency (core clock)
*
* The system clock frequency supplied to the SysTick timer and the processor
* core clock. This variable can be used by the user application to setup the
* SysTick timer or configure other parameters. It may also be used by debugger to
* query the frequency of the debug timer or configure the trace clock speed
* SystemCoreClock is initialized with a correct predefined value.
*/
extern uint32_t SystemCoreClock;
/**
* @brief Setup the microcontroller system.
*
* Typically this function configures the oscillator (PLL) that is part of the
* microcontroller device. For systems with variable clock speed it also updates
* the variable SystemCoreClock. SystemInit is called from startup_device file.
*/
void SystemInit (void);
/**
* @brief Updates the SystemCoreClock variable.
*
* It must be called whenever the core clock is changed during program
* execution. SystemCoreClockUpdate() evaluates the clock register settings and calculates
* the current core clock.
*/
void SystemCoreClockUpdate (void);
/**
* @brief SystemInit function hook.
*
* This weak function allows to call specific initialization code during the
* SystemInit() execution.This can be used when an application specific code needs
* to be called as close to the reset entry as possible (for example the Multicore
* Manager MCMGR_EarlyInit() function call).
* NOTE: No global r/w variables can be used in this hook function because the
* initialization of these variables happens after this function.
*/
void SystemInitHook (void);
/**
* @brief System IRQ handler which dispatches specific IRQ to corresponding registered handler.
*
* It is called from IRQ exception context and dispatches to registered handler according to
* MCAUSE interrupt number.
*
* @param mcause IRQ acknowledge value read from MCAUSE
*/
void SystemIrqHandler(uint32_t mcause);
/**
* @brief Get IRQ nesting level of current context.
*
* If the return value is 0, then the context is not ISR, otherwise the context is ISR.
*
* @return IRQ nesting level
*/
uint32_t SystemGetIRQNestingLevel (void);
/**
* @brief Setup systick for RTOS system.
*
* @param tickRateHz Tick number per second
* @param intPriority IRQ interrupt priority (the smaller, the higher priority)
*/
void SystemSetupSystick (uint32_t tickRateHz, uint32_t intPriority);
/**
* @brief Clear systick flag status so that next tick interrupt may occur.
*/
void SystemClearSystickFlag (void);
#define SysTick_Handler LPIT1_IRQHandler
/**
* @brief Sysem is in ISR or not.
*/
bool SystemInISR(void);
/**
* @brief Set interrupt priority in Event unit.
*/
void EVENT_SetIRQPriority(IRQn_Type IRQn, uint8_t intPriority);
/* Priority setting macro remap. */
#define NVIC_SetPriority EVENT_SetIRQPriority
/**
* @brief Reset the system.
*/
void EVENT_SystemReset(void);
#define NVIC_SystemReset EVENT_SystemReset
#ifdef __cplusplus
}
#endif
#endif /* _SYSTEM_RV32M1_zero_riscy_H_ */

View File

@ -0,0 +1,386 @@
/*
* This is a modified version of the file printf.c, which was distributed
* by Motorola as part of the M5407C3BOOT.zip package used to initialize
* the M5407C3 evaluation board.
*
* Copyright:
* 1999-2000 MOTOROLA, INC. All Rights Reserved.
* You are hereby granted a copyright license to use, modify, and
* distribute the SOFTWARE so long as this entire notice is
* retained without alteration in any modified and/or redistributed
* versions, and that such modified versions are clearly identified
* as such. No licenses are granted by implication, estoppel or
* otherwise under any patents or trademarks of Motorola, Inc. This
* software is provided on an "AS IS" basis and without warranty.
*
* To the maximum extent permitted by applicable law, MOTOROLA
* DISCLAIMS ALL WARRANTIES WHETHER EXPRESS OR IMPLIED, INCLUDING
* IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR
* PURPOSE AND ANY WARRANTY AGAINST INFRINGEMENT WITH REGARD TO THE
* SOFTWARE (INCLUDING ANY MODIFIED VERSIONS THEREOF) AND ANY
* ACCOMPANYING WRITTEN MATERIALS.
*
* To the maximum extent permitted by applicable law, IN NO EVENT
* SHALL MOTOROLA BE LIABLE FOR ANY DAMAGES WHATSOEVER (INCLUDING
* WITHOUT LIMITATION, DAMAGES FOR LOSS OF BUSINESS PROFITS, BUSINESS
* INTERRUPTION, LOSS OF BUSINESS INFORMATION, OR OTHER PECUNIARY
* LOSS) ARISING OF THE USE OR INABILITY TO USE THE SOFTWARE.
*
* Motorola assumes no responsibility for the maintenance and support
* of this software
* Copyright (c) 2015, Freescale Semiconductor, Inc.
* Copyright 2016-2017 NXP
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <stdarg.h>
#include <stdlib.h>
#if defined(__CC_ARM)
#include <stdio.h>
#endif
#include "fsl_debug_console.h"
#include "fsl_debug_console_conf.h"
#include "fsl_log.h"
#include "fsl_str.h"
#if defined(__riscv)
#include <sys/stat.h>
#include <sys/types.h>
#endif
/*******************************************************************************
* Definitions
******************************************************************************/
/*******************************************************************************
* Variables
******************************************************************************/
/*******************************************************************************
* Prototypes
******************************************************************************/
/*!
* @brief This is a printf call back function which is used to relocate the log to buffer
* or print the log immediately when the local buffer is full.
*
* @param[in] buf Buffer to store log.
* @param[in] indicator Buffer index.
* @param[in] val Target character to store.
* @param[in] len length of the character
*
*/
#if SDK_DEBUGCONSOLE
static void DbgConsole_RelocateLog(char *buf, int32_t *indicator, char val, int len);
#endif
/*******************************************************************************
* Code
******************************************************************************/
/*************Code for DbgConsole Init, Deinit, Printf, Scanf *******************************/
/* See fsl_debug_console.h for documentation of this function. */
status_t DbgConsole_Init(uint32_t baseAddr, uint32_t baudRate, uint8_t device, uint32_t clkSrcFreq)
{
assert(device != DEBUG_CONSOLE_DEVICE_TYPE_NONE);
return LOG_Init(baseAddr, device, baudRate, clkSrcFreq);
}
/* See fsl_debug_console.h for documentation of this function. */
status_t DbgConsole_Deinit(void)
{
/* LOG deinit */
LOG_Deinit();
return kStatus_Success;
}
status_t DbgConsole_Flush(void)
{
/* wait log and io idle */
return LOG_WaitIdle();
}
#if SDK_DEBUGCONSOLE
/* See fsl_debug_console.h for documentation of this function. */
int DbgConsole_Printf(const char *fmt_s, ...)
{
va_list ap;
int logLength = 0U, result = 0U;
char printBuf[DEBUG_CONSOLE_PRINTF_MAX_LOG_LEN] = {0U};
va_start(ap, fmt_s);
/* format print log first */
logLength = StrFormatPrintf(fmt_s, ap, printBuf, DbgConsole_RelocateLog);
/* print log */
result = LOG_Push((uint8_t *)printBuf, logLength);
va_end(ap);
return result;
}
/* See fsl_debug_console.h for documentation of this function. */
int DbgConsole_Putchar(int ch)
{
/* print char */
return LOG_Push((uint8_t *)&ch, 1U);
}
/* See fsl_debug_console.h for documentation of this function. */
int DbgConsole_Scanf(char *fmt_ptr, ...)
{
va_list ap;
int result;
char scanfBuf[DEBUG_CONSOLE_SCANF_MAX_LOG_LEN + 1U] = {0U};
/* scanf log */
LOG_ReadLine((uint8_t *)scanfBuf, DEBUG_CONSOLE_SCANF_MAX_LOG_LEN);
/* get va_list */
va_start(ap, fmt_ptr);
/* format scanf log */
result = StrFormatScanf(scanfBuf, fmt_ptr, ap);
va_end(ap);
return result;
}
/* See fsl_debug_console.h for documentation of this function. */
int DbgConsole_Getchar(void)
{
uint8_t ch;
/* Get char */
LOG_ReadCharacter(&ch);
return ch;
}
static void DbgConsole_RelocateLog(char *buf, int32_t *indicator, char val, int len)
{
int i = 0;
for (i = 0; i < len; i++)
{
if ((*indicator + 1) >= DEBUG_CONSOLE_PRINTF_MAX_LOG_LEN)
{
LOG_Push((uint8_t *)buf, *indicator);
*indicator = 0U;
}
buf[*indicator] = val;
(*indicator)++;
}
}
#endif /* SDK_DEBUGCONSOLE */
/*************Code to support toolchain's printf, scanf *******************************/
/* These function __write and __read is used to support IAR toolchain to printf and scanf*/
#if (defined(__ICCARM__))
#pragma weak __write
size_t __write(int handle, const unsigned char *buffer, size_t size)
{
if (buffer == 0)
{
/*
* This means that we should flush internal buffers. Since we don't we just return.
* (Remember, "handle" == -1 means that all handles should be flushed.)
*/
return 0;
}
/* This function only writes to "standard out" and "standard err" for all other file handles it returns failure. */
if ((handle != 1) && (handle != 2))
{
return ((size_t)-1);
}
/* Send data. */
LOG_Push((uint8_t *)buffer, 1U);
return size;
}
#pragma weak __read
size_t __read(int handle, unsigned char *buffer, size_t size)
{
/* This function only reads from "standard in", for all other file handles it returns failure. */
if (handle != 0)
{
return ((size_t)-1);
}
/* Receive data.*/
LOG_ReadLine(buffer, size);
return size;
}
/* support LPC Xpresso with RedLib */
#elif(defined(__REDLIB__))
#if (!SDK_DEBUGCONSOLE) && (defined(SDK_DEBUGCONSOLE_UART))
int __attribute__((weak)) __sys_write(int handle, char *buffer, int size)
{
if (buffer == 0)
{
/* return -1 if error. */
return -1;
}
/* This function only writes to "standard out" and "standard err" for all other file handles it returns failure. */
if ((handle != 1) && (handle != 2))
{
return -1;
}
/* Send data. */
LOG_Push((uint8_t *)buffer, size);
return 0;
}
int __attribute__((weak)) __sys_readc(void)
{
char tmp;
/* Receive data. */
LOG_ReadCharacter((uint8_t *)&tmp);
return tmp;
}
#endif
/* These function __write and __read is used to support ARM_GCC, KDS, Atollic toolchains to printf and scanf*/
#elif(defined(__GNUC__))
#if ((defined(__GNUC__) && (!defined(__MCUXPRESSO))) || \
(defined(__MCUXPRESSO) && (!SDK_DEBUGCONSOLE) && (defined(SDK_DEBUGCONSOLE_UART))))
int __attribute__((weak)) _write(int handle, char *buffer, int size)
{
if (buffer == 0)
{
/* return -1 if error. */
return -1;
}
/* This function only writes to "standard out" and "standard err" for all other file handles it returns failure. */
if ((handle != 1) && (handle != 2))
{
return -1;
}
/* Send data. */
LOG_Push((uint8_t *)buffer, size);
return size;
}
int __attribute__((weak)) _read(int handle, char *buffer, int size)
{
/* This function only reads from "standard in", for all other file handles it returns failure. */
if (handle != 0)
{
return -1;
}
/* Receive data. */
return LOG_ReadLine((uint8_t *)buffer, size);
}
#endif
/* These function fputc and fgetc is used to support KEIL toolchain to printf and scanf*/
#elif defined(__CC_ARM)
struct __FILE
{
int handle;
/*
* Whatever you require here. If the only file you are using is standard output using printf() for debugging,
* no file handling is required.
*/
};
/* FILE is typedef in stdio.h. */
#pragma weak __stdout
#pragma weak __stdin
FILE __stdout;
FILE __stdin;
#pragma weak fputc
int fputc(int ch, FILE *f)
{
/* Send data. */
return LOG_Push((uint8_t *)(&ch), 1);
}
#pragma weak fgetc
int fgetc(FILE *f)
{
char ch;
/* Receive data. */
LOG_ReadCharacter((uint8_t *)&ch);
return ch;
}
#endif /* __ICCARM__ */
#if defined(__riscv)
int isatty(int fd)
{
return 1;
}
int fstat(int fd, struct stat *st)
{
st->st_mode = S_IFCHR;
return 0;
}
int lseek(int fd, off_t ptr, int dir)
{
return 0;
}
int close(int fd)
{
return -1;
}
int read(int fd, void* ptr, size_t len)
{
/* This function only reads from "standard in", for all other file handles it returns failure. */
if (fd != 0)
{
return -1;
}
/* Receive data. */
return LOG_ReadLine((uint8_t *)ptr, len);
}
int write(int fd, const void* ptr, size_t len)
{
if (ptr == 0)
{
/* return -1 if error. */
return -1;
}
/* This function only writes to "standard out" and "standard err" for all other file handles it returns failure. */
if ((fd != 1) && (fd != 2))
{
return -1;
}
/* Send data. */
LOG_Push((uint8_t *)ptr, len);
return len;
}
#endif

View File

@ -0,0 +1,162 @@
/*
* Copyright (c) 2013 - 2015, Freescale Semiconductor, Inc.
* Copyright 2016-2017 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*
* Debug console shall provide input and output functions to scan and print formatted data.
* o Support a format specifier for PRINTF follows this prototype "%[flags][width][.precision][length]specifier"
* - [flags] :'-', '+', '#', ' ', '0'
* - [width]: number (0,1...)
* - [.precision]: number (0,1...)
* - [length]: do not support
* - [specifier]: 'd', 'i', 'f', 'F', 'x', 'X', 'o', 'p', 'u', 'c', 's', 'n'
* o Support a format specifier for SCANF follows this prototype " %[*][width][length]specifier"
* - [*]: is supported.
* - [width]: number (0,1...)
* - [length]: 'h', 'hh', 'l','ll','L'. ignore ('j','z','t')
* - [specifier]: 'd', 'i', 'u', 'f', 'F', 'e', 'E', 'g', 'G', 'a', 'A', 'o', 'c', 's'
*/
#ifndef _FSL_DEBUGCONSOLE_H_
#define _FSL_DEBUGCONSOLE_H_
#include "fsl_common.h"
/*
* @addtogroup debugconsole
* @{
*/
/*******************************************************************************
* Definitions
******************************************************************************/
/*! @brief Definition to select sdk or toolchain printf, scanf. */
#ifndef SDK_DEBUGCONSOLE
#define SDK_DEBUGCONSOLE 1U
#endif
#if defined(SDK_DEBUGCONSOLE) && !(SDK_DEBUGCONSOLE)
#include <stdio.h>
#endif
#if SDK_DEBUGCONSOLE /* Select printf, scanf, putchar, getchar of SDK version. */
#define PRINTF DbgConsole_Printf
#define SCANF DbgConsole_Scanf
#define PUTCHAR DbgConsole_Putchar
#define GETCHAR DbgConsole_Getchar
#else /* Select printf, scanf, putchar, getchar of toolchain. */
#define PRINTF printf
#define SCANF scanf
#define PUTCHAR putchar
#define GETCHAR getchar
#endif /* SDK_DEBUGCONSOLE */
/*******************************************************************************
* Prototypes
******************************************************************************/
#if defined(__cplusplus)
extern "C" {
#endif /* __cplusplus */
/*! @name Initialization*/
/* @{ */
/*!
* @brief Initializes the the peripheral used for debug messages.
*
* Call this function to enable debug log messages to be output via the specified peripheral,
* frequency of peripheral source clock, and base address at the specified baud rate.
* After this function has returned, stdout and stdin are connected to the selected peripheral.
*
* @param baseAddr Indicates the address of the peripheral used to send debug messages.
* @param baudRate The desired baud rate in bits per second.
* @param device Low level device type for the debug console, can be one of the following.
* @arg DEBUG_CONSOLE_DEVICE_TYPE_UART,
* @arg DEBUG_CONSOLE_DEVICE_TYPE_LPUART,
* @arg DEBUG_CONSOLE_DEVICE_TYPE_LPSCI,
* @arg DEBUG_CONSOLE_DEVICE_TYPE_USBCDC.
* @param clkSrcFreq Frequency of peripheral source clock.
*
* @return Indicates whether initialization was successful or not.
* @retval kStatus_Success Execution successfully
* @retval kStatus_Fail Execution failure
* @retval kStatus_InvalidArgument Invalid argument existed
*/
status_t DbgConsole_Init(uint32_t baseAddr, uint32_t baudRate, uint8_t device, uint32_t clkSrcFreq);
/*!
* @brief De-initializes the peripheral used for debug messages.
*
* Call this function to disable debug log messages to be output via the specified peripheral
* base address and at the specified baud rate.
*
* @return Indicates whether de-initialization was successful or not.
*/
status_t DbgConsole_Deinit(void);
/*!
* @brief Debug console flush log.
*
* Call this function to wait the buffer empty and io idle before.
* If interrupt transfer is using, make sure the global IRQ is enable before call this function
* This function should be called when
* 1, before enter power down mode
* 2, log is required to print to terminal immediately
* @return Indicates whether wait idle was successful or not.
*/
status_t DbgConsole_Flush(void);
#if SDK_DEBUGCONSOLE
/*!
* @brief Writes formatted output to the standard output stream.
*
* Call this function to write a formatted output to the standard output stream.
*
* @param fmt_s Format control string.
* @return Returns the number of characters printed or a negative value if an error occurs.
*/
int DbgConsole_Printf(const char *fmt_s, ...);
/*!
* @brief Writes a character to stdout.
*
* Call this function to write a character to stdout.
*
* @param ch Character to be written.
* @return Returns the character written.
*/
int DbgConsole_Putchar(int ch);
/*!
* @brief Reads formatted data from the standard input stream.
*
* Call this function to read formatted data from the standard input stream.
*
* @param fmt_ptr Format control string.
* @return Returns the number of fields successfully converted and assigned.
*/
int DbgConsole_Scanf(char *fmt_ptr, ...);
/*!
* @brief Reads a character from standard input.
*
* Call this function to read a character from standard input.
*
* @return Returns the character read.
*/
int DbgConsole_Getchar(void);
#endif /* SDK_DEBUGCONSOLE */
/*! @} */
#if defined(__cplusplus)
}
#endif /* __cplusplus */
/*! @} */
#endif /* _FSL_DEBUGCONSOLE_H_ */

View File

@ -0,0 +1,128 @@
/*
* Copyright 2017 NXP
* All rights reserved.
*
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef _FSL_DEBUG_CONSOLE_CONF_H_
#define _FSL_DEBUG_CONSOLE_CONF_H_
/****************Debug console configuration********************/
/*! @brief If Non-blocking mode is needed, please define it at project setting,
* otherwise blocking mode is the default transfer mode.
* Warning: If you want to use non-blocking transfer,please make sure the corresponding
* IO interrupt is enable, otherwise there is no output.
* And non-blocking is combine with buffer, no matter bare-metal or rtos.
*/
#ifdef DEBUG_CONSOLE_TRANSFER_NON_BLOCKING
/*! @brief define the transmit buffer length which is used to store the multi task log, buffer is enabled automatically
* when
* non-blocking transfer is using,
* This value will affect the RAM's ultilization, should be set per paltform's capability and software requirement.
* If it is configured too small, log maybe missed , because the log will not be
* buffered if the buffer is full, and the print will return immediately with -1.
* And this value should be multiple of 4 to meet memory alignment.
*
*/
#ifndef DEBUG_CONSOLE_TRANSMIT_BUFFER_LEN
#define DEBUG_CONSOLE_TRANSMIT_BUFFER_LEN (512U)
#endif /* DEBUG_CONSOLE_TRANSMIT_BUFFER_LEN */
/*! @brief define the receive buffer length which is used to store the user input, buffer is enabled automatically when
* non-blocking transfer is using,
* This value will affect the RAM's ultilization, should be set per paltform's capability and software requirement.
* If it is configured too small, log maybe missed, because buffer will be overwrited if buffer is too small.
* And this value should be multiple of 4 to meet memory alignment.
*
*/
#ifndef DEBUG_CONSOLE_RECEIVE_BUFFER_LEN
#define DEBUG_CONSOLE_RECEIVE_BUFFER_LEN (512U)
#endif /* DEBUG_CONSOLE_RECEIVE_BUFFER_LEN */
#else
#define DEBUG_CONSOLE_TRANSFER_BLOCKING
#endif /* DEBUG_CONSOLE_TRANSFER_NON_BLOCKING */
/*!@ brief define the MAX log length debug console support , that is when you call printf("log", x);, the log
* length can not bigger than this value.
* This macro decide the local log buffer length, the buffer locate at stack, the stack maybe overflow if
* the buffer is too big and current task stack size not big enough.
*/
#ifndef DEBUG_CONSOLE_PRINTF_MAX_LOG_LEN
#define DEBUG_CONSOLE_PRINTF_MAX_LOG_LEN (128U)
#endif /* DEBUG_CONSOLE_PRINTF_MAX_LOG_LEN */
/*!@ brief define the buffer support buffer scanf log length, that is when you call scanf("log", &x);, the log
* length can not bigger than this value.
* As same as the DEBUG_CONSOLE_BUFFER_PRINTF_MAX_LOG_LEN.
*/
#ifndef DEBUG_CONSOLE_SCANF_MAX_LOG_LEN
#define DEBUG_CONSOLE_SCANF_MAX_LOG_LEN (20U)
#endif /* DEBUG_CONSOLE_SCANF_MAX_LOG_LEN */
/*! @brief Debug console synchronization
* User should not change these macro for synchronization mode, but add the
* corresponding synchronization mechanism per different software environment.
* Such as, if another RTOS is used,
* add:
* #define DEBUG_CONSOLE_SYNCHRONIZATION_XXXX 3
* in this configuration file and implement the synchronization in fsl.log.c.
*/
/*! @brief synchronization for baremetal software */
#define DEBUG_CONSOLE_SYNCHRONIZATION_BM 0
/*! @brief synchronization for freertos software */
#define DEBUG_CONSOLE_SYNCHRONIZATION_FREERTOS 1
/*! @brief RTOS synchronization mechanism disable
* If not defined, default is enable, to avoid multitask log print mess.
* If other RTOS is used, you can implement the RTOS's specific synchronization mechanism in fsl.log.c
* If synchronization is disabled, log maybe messed on terminal.
*/
#ifndef DEBUG_CONSOLE_DISABLE_RTOS_SYNCHRONIZATION
#ifdef DEBUG_CONSOLE_TRANSFER_NON_BLOCKING
#ifdef FSL_RTOS_FREE_RTOS
#define DEBUG_CONSOLE_SYNCHRONIZATION_MODE DEBUG_CONSOLE_SYNCHRONIZATION_FREERTOS
#else
#define DEBUG_CONSOLE_SYNCHRONIZATION_MODE DEBUG_CONSOLE_SYNCHRONIZATION_BM
#endif /* FSL_RTOS_FREE_RTOS */
#endif /* DEBUG_CONSOLE_TRANSFER_NON_BLOCKING */
#endif /* DEBUG_CONSOLE_DISABLE_RTOS_SYNCHRONIZATION */
/*! @brief echo function support
* If you want to use the echo function,please define DEBUG_CONSOLE_ENABLE_ECHO
* at your project setting.
*/
#ifndef DEBUG_CONSOLE_ENABLE_ECHO
#define DEBUG_CONSOLE_ENABLE_ECHO_FUNCTION 0
#else
#define DEBUG_CONSOLE_ENABLE_ECHO_FUNCTION 1
#endif /* DEBUG_CONSOLE_ENABLE_ECHO */
/*********************************************************************/
/***************Debug console other configuration*********************/
/*! @brief Definition to printf the float number. */
#ifndef PRINTF_FLOAT_ENABLE
#define PRINTF_FLOAT_ENABLE 0U
#endif /* PRINTF_FLOAT_ENABLE */
/*! @brief Definition to scanf the float number. */
#ifndef SCANF_FLOAT_ENABLE
#define SCANF_FLOAT_ENABLE 0U
#endif /* SCANF_FLOAT_ENABLE */
/*! @brief Definition to support advanced format specifier for printf. */
#ifndef PRINTF_ADVANCED_ENABLE
#define PRINTF_ADVANCED_ENABLE 0U
#endif /* PRINTF_ADVANCED_ENABLE */
/*! @brief Definition to support advanced format specifier for scanf. */
#ifndef SCANF_ADVANCED_ENABLE
#define SCANF_ADVANCED_ENABLE 0U
#endif /* SCANF_ADVANCED_ENABLE */
/*******************************************************************/
#endif /* _FSL_DEBUG_CONSOLE_CONF_H_ */

View File

@ -0,0 +1,655 @@
/*
* Copyright 2017 NXP
* All rights reserved.
*
*
* SPDX-License-Identifier: BSD-3-Clause
*
*/
#include "fsl_io.h"
#include "fsl_debug_console_conf.h"
/*******************************************************************************
* Definitions
******************************************************************************/
/* check avaliable device */
#if (defined(FSL_FEATURE_SOC_UART_COUNT) && (FSL_FEATURE_SOC_UART_COUNT != 0))
#define DEBUG_CONSOLE_IO_UART
#endif
#if (defined(FSL_FEATURE_SOC_IUART_COUNT) && (FSL_FEATURE_SOC_IUART_COUNT != 0))
#define DEBUG_CONSOLE_IO_IUART
#endif
#if (defined(FSL_FEATURE_SOC_LPUART_COUNT) && (FSL_FEATURE_SOC_LPUART_COUNT != 0))
#define DEBUG_CONSOLE_IO_LPUART
#endif
#if (defined(FSL_FEATURE_SOC_LPSCI_COUNT) && (FSL_FEATURE_SOC_LPSCI_COUNT != 0))
#define DEBUG_CONSOLE_IO_LPSCI
#endif
#if ((defined(FSL_FEATURE_SOC_USB_COUNT) && (FSL_FEATURE_SOC_USB_COUNT == 0)) && defined(BOARD_USE_VIRTUALCOM))
#define DEBUG_CONSOLE_IO_USBCDC
#endif
#if (defined(FSL_FEATURE_SOC_FLEXCOMM_COUNT) && (FSL_FEATURE_SOC_FLEXCOMM_COUNT != 0))
#define DEBUG_CONSOLE_IO_FLEXCOMM
#endif
#if (defined(FSL_FEATURE_SOC_VFIFO_COUNT) && (FSL_FEATURE_SOC_VFIFO_COUNT != 0))
#define DEBUG_CONSOLE_IO_VUSART
#endif
/* configuration for debug console device */
/* If new device is required as the low level device for debug console,
* Add the #elif branch and add the preprocessor macro to judge whether
* this kind of device exist in this SOC. */
#if (defined DEBUG_CONSOLE_IO_UART) || (defined DEBUG_CONSOLE_IO_IUART)
#include "fsl_uart.h"
#ifdef DEBUG_CONSOLE_TRANSFER_NON_BLOCKING
static uart_handle_t s_ioUartHandler;
#endif /* DEBUG_CONSOLE_TRANSFER_NON_BLOCKING */
#endif /* defined DEBUG_CONSOLE_IO_UART) || (defined DEBUG_CONSOLE_IO_IUART */
#if defined DEBUG_CONSOLE_IO_LPUART
#include "fsl_lpuart.h"
#ifdef DEBUG_CONSOLE_TRANSFER_NON_BLOCKING
static lpuart_handle_t s_ioLpuartHandler;
#endif /* DEBUG_CONSOLE_TRANSFER_NON_BLOCKING */
#endif /* DEBUG_CONSOLE_IO_LPUART */
#if defined DEBUG_CONSOLE_IO_LPSCI
#include "fsl_lpsci.h"
#ifdef DEBUG_CONSOLE_TRANSFER_NON_BLOCKING
static lpsci_handle_t s_ioLpsciHandler;
#endif /* DEBUG_CONSOLE_TRANSFER_NON_BLOCKING */
#endif /* DEBUG_CONSOLE_IO_LPSCI */
#if defined DEBUG_CONSOLE_IO_USBCDC
#include "usb_device_config.h"
#include "usb.h"
#include "usb_device_cdc_acm.h"
#include "usb_device_ch9.h"
#include "virtual_com.h"
#endif /* DEBUG_CONSOLE_IO_USBCDC */
#if (defined DEBUG_CONSOLE_IO_FLEXCOMM) || (defined DEBUG_CONSOLE_IO_VUSART)
#include "fsl_usart.h"
#ifdef DEBUG_CONSOLE_TRANSFER_NON_BLOCKING
static usart_handle_t s_ioUsartHandler;
#endif /* DEBUG_CONSOLE_TRANSFER_NON_BLOCKING */
#endif /* defined DEBUG_CONSOLE_IO_FLEXCOMM) || (defined DEBUG_CONSOLE_IO_VUSART */
/*******************************************************************************
* Variables
******************************************************************************/
/*! @brief Debug console IO state information. */
static io_state_t s_debugConsoleIO = {
.ioBase = NULL,
.ioType = DEBUG_CONSOLE_DEVICE_TYPE_NONE,
#ifdef DEBUG_CONSOLE_TRANSFER_NON_BLOCKING
.callBack = NULL,
#endif /* DEBUG_CONSOLE_TRANSFER_NON_BLOCKING */
};
/*******************************************************************************
* Code
******************************************************************************/
#ifdef DEBUG_CONSOLE_TRANSFER_NON_BLOCKING
#if (defined DEBUG_CONSOLE_IO_UART) || (defined DEBUG_CONSOLE_IO_IUART)
static void UART_Callback(UART_Type *base, uart_handle_t *handle, status_t status, void *userData)
{
bool tx = false, rx = false;
size_t size = 0U;
if (status == kStatus_UART_RxIdle)
{
rx = true;
size = handle->txDataSizeAll;
}
if (status == kStatus_UART_TxIdle)
{
tx = true;
size = handle->txDataSizeAll;
}
/* inform the buffer layer that transfer is complete */
if (s_debugConsoleIO.callBack != NULL)
{
/* call buffer callback function */
s_debugConsoleIO.callBack(&size, rx, tx);
}
}
#endif /* defined DEBUG_CONSOLE_IO_UART) || (defined DEBUG_CONSOLE_IO_IUART */
#if defined DEBUG_CONSOLE_IO_LPSCI
static void LPSCI_Callback(UART0_Type *base, lpsci_handle_t *handle, status_t status, void *userData)
{
bool tx = false, rx = false;
size_t size = 0U;
if (status == kStatus_LPSCI_RxIdle)
{
rx = true;
size = handle->txDataSizeAll;
}
if (status == kStatus_LPSCI_TxIdle)
{
tx = true;
size = handle->txDataSizeAll;
}
/* inform the buffer layer that transfer is complete */
if (s_debugConsoleIO.callBack != NULL)
{
/* call buffer callback function */
s_debugConsoleIO.callBack(&size, rx, tx);
}
}
#endif /* DEBUG_CONSOLE_IO_LPSCI */
#if defined DEBUG_CONSOLE_IO_LPUART
static void LPUART_Callback(LPUART_Type *base, lpuart_handle_t *handle, status_t status, void *userData)
{
bool tx = false, rx = false;
size_t size = 0U;
if (status == kStatus_LPUART_RxIdle)
{
rx = true;
size = handle->txDataSizeAll;
}
if (status == kStatus_LPUART_TxIdle)
{
tx = true;
size = handle->txDataSizeAll;
}
/* inform the buffer layer that transfer is complete */
if (s_debugConsoleIO.callBack != NULL)
{
/* call buffer callback function */
s_debugConsoleIO.callBack(&size, rx, tx);
}
}
#endif /* DEBUG_CONSOLE_IO_LPUART */
#if (defined DEBUG_CONSOLE_IO_FLEXCOMM) || (defined DEBUG_CONSOLE_IO_VUSART)
static void USART_Callback(USART_Type *base, usart_handle_t *handle, status_t status, void *userData)
{
bool tx = false, rx = false;
size_t size = 0U;
if (status == kStatus_USART_RxIdle)
{
rx = true;
size = handle->txDataSizeAll;
}
if (status == kStatus_USART_TxIdle)
{
tx = true;
size = handle->txDataSizeAll;
}
/* inform the buffer layer that transfer is complete */
if (s_debugConsoleIO.callBack != NULL)
{
/* call buffer callback function */
s_debugConsoleIO.callBack(&size, rx, tx);
}
}
#endif /* defined DEBUG_CONSOLE_IO_FLEXCOMM) || (defined DEBUG_CONSOLE_IO_VUSART */
#endif /* DEBUG_CONSOLE_TRANSFER_NON_BLOCKING */
void IO_Init(io_state_t *io, uint32_t baudRate, uint32_t clkSrcFreq, uint8_t *ringBuffer)
{
assert(NULL != io);
/* record device type/base */
s_debugConsoleIO.ioType = io->ioType;
s_debugConsoleIO.ioBase = (void *)(io->ioBase);
switch (s_debugConsoleIO.ioType)
{
#if (defined DEBUG_CONSOLE_IO_UART) || (defined DEBUG_CONSOLE_IO_IUART)
case DEBUG_CONSOLE_DEVICE_TYPE_UART:
case DEBUG_CONSOLE_DEVICE_TYPE_IUART:
{
uart_config_t uart_config;
UART_GetDefaultConfig(&uart_config);
uart_config.baudRate_Bps = baudRate;
/* Enable clock and initial UART module follow user configure structure. */
UART_Init((UART_Type *)s_debugConsoleIO.ioBase, &uart_config, clkSrcFreq);
UART_EnableTx(s_debugConsoleIO.ioBase, true);
UART_EnableRx(s_debugConsoleIO.ioBase, true);
#ifdef DEBUG_CONSOLE_TRANSFER_NON_BLOCKING
s_debugConsoleIO.callBack = io->callBack;
/* create handler for interrupt transfer */
UART_TransferCreateHandle(s_debugConsoleIO.ioBase, &s_ioUartHandler, UART_Callback, NULL);
/* start ring buffer */
UART_TransferStartRingBuffer(s_debugConsoleIO.ioBase, &s_ioUartHandler, ringBuffer,
DEBUG_CONSOLE_RECEIVE_BUFFER_LEN);
#endif
}
break;
#endif
#if defined DEBUG_CONSOLE_IO_LPUART
case DEBUG_CONSOLE_DEVICE_TYPE_LPUART:
{
lpuart_config_t lpuart_config;
LPUART_GetDefaultConfig(&lpuart_config);
lpuart_config.baudRate_Bps = baudRate;
/* Enable clock and initial UART module follow user configure structure. */
LPUART_Init((LPUART_Type *)s_debugConsoleIO.ioBase, &lpuart_config, clkSrcFreq);
LPUART_EnableTx(s_debugConsoleIO.ioBase, true);
LPUART_EnableRx(s_debugConsoleIO.ioBase, true);
#ifdef DEBUG_CONSOLE_TRANSFER_NON_BLOCKING
s_debugConsoleIO.callBack = io->callBack;
/* create handler for interrupt transfer */
LPUART_TransferCreateHandle(s_debugConsoleIO.ioBase, &s_ioLpuartHandler, LPUART_Callback, NULL);
/* start ring buffer */
LPUART_TransferStartRingBuffer(s_debugConsoleIO.ioBase, &s_ioLpuartHandler, ringBuffer,
DEBUG_CONSOLE_RECEIVE_BUFFER_LEN);
#endif
}
break;
#endif
#if defined DEBUG_CONSOLE_IO_LPSCI
case DEBUG_CONSOLE_DEVICE_TYPE_LPSCI:
{
lpsci_config_t lpsci_config;
LPSCI_GetDefaultConfig(&lpsci_config);
lpsci_config.baudRate_Bps = baudRate;
/* Enable clock and initial UART module follow user configure structure. */
LPSCI_Init((UART0_Type *)s_debugConsoleIO.ioBase, &lpsci_config, clkSrcFreq);
LPSCI_EnableTx(s_debugConsoleIO.ioBase, true);
LPSCI_EnableRx(s_debugConsoleIO.ioBase, true);
#ifdef DEBUG_CONSOLE_TRANSFER_NON_BLOCKING
s_debugConsoleIO.callBack = io->callBack;
/* create handler for interrupt transfer */
LPSCI_TransferCreateHandle(s_debugConsoleIO.ioBase, &s_ioLpsciHandler, LPSCI_Callback, NULL);
/* start ring buffer */
LPSCI_TransferStartRingBuffer(s_debugConsoleIO.ioBase, &s_ioLpsciHandler, ringBuffer,
DEBUG_CONSOLE_RECEIVE_BUFFER_LEN);
#endif
}
break;
#endif
#if defined DEBUG_CONSOLE_IO_USBCDC
case DEBUG_CONSOLE_DEVICE_TYPE_USBCDC:
{
s_debugConsoleIO.ioBase = USB_VcomInit();
}
break;
#endif
#if defined DEBUG_CONSOLE_IO_FLEXCOMM
case DEBUG_CONSOLE_DEVICE_TYPE_FLEXCOMM:
{
usart_config_t usart_config;
USART_GetDefaultConfig(&usart_config);
usart_config.baudRate_Bps = baudRate;
/* Enable clock and initial UART module follow user configure structure. */
USART_Init((USART_Type *)s_debugConsoleIO.ioBase, &usart_config, clkSrcFreq);
#ifdef DEBUG_CONSOLE_TRANSFER_NON_BLOCKING
s_debugConsoleIO.callBack = io->callBack;
/* create handler for interrupt transfer */
USART_TransferCreateHandle(s_debugConsoleIO.ioBase, &s_ioUsartHandler, USART_Callback, NULL);
/* start ring buffer */
USART_TransferStartRingBuffer(s_debugConsoleIO.ioBase, &s_ioUsartHandler, ringBuffer,
DEBUG_CONSOLE_RECEIVE_BUFFER_LEN);
#endif
}
break;
#endif
#if defined DEBUG_CONSOLE_IO_VUSART
case DEBUG_CONSOLE_DEVICE_TYPE_VUSART:
{
usart_config_t usart_config;
USART_GetDefaultConfig(&usart_config);
usart_config.baudRate_Bps = baudRate;
usart_config.enableRx = true;
usart_config.enableTx = true;
/* Enable clock and initial UART module follow user configure structure. */
USART_Init((USART_Type *)s_debugConsoleIO.ioBase, &usart_config, clkSrcFreq);
#ifdef DEBUG_CONSOLE_TRANSFER_NON_BLOCKING
s_debugConsoleIO.callBack = io->callBack;
/* create handler for interrupt transfer */
USART_TransferCreateHandle(s_debugConsoleIO.ioBase, &s_ioUsartHandler, USART_Callback, NULL);
/* start ring buffer */
USART_TransferStartRingBuffer(s_debugConsoleIO.ioBase, &s_ioUsartHandler, ringBuffer,
DEBUG_CONSOLE_RECEIVE_BUFFER_LEN);
#endif
}
break;
#endif
}
}
status_t IO_Deinit(void)
{
if (s_debugConsoleIO.ioType == DEBUG_CONSOLE_DEVICE_TYPE_NONE)
{
return kStatus_Success;
}
switch (s_debugConsoleIO.ioType)
{
#if (defined DEBUG_CONSOLE_IO_UART) || (defined DEBUG_CONSOLE_IO_IUART)
case DEBUG_CONSOLE_DEVICE_TYPE_UART:
case DEBUG_CONSOLE_DEVICE_TYPE_IUART:
#ifdef DEBUG_CONSOLE_TRANSFER_NON_BLOCKING
/* stop ring buffer */
UART_TransferStopRingBuffer(s_debugConsoleIO.ioBase, &s_ioUartHandler);
#endif
/* Disable UART module. */
UART_Deinit((UART_Type *)s_debugConsoleIO.ioBase);
break;
#endif
#if defined DEBUG_CONSOLE_IO_LPSCI
case DEBUG_CONSOLE_DEVICE_TYPE_LPSCI:
#ifdef DEBUG_CONSOLE_TRANSFER_NON_BLOCKING
/* stop ring buffer */
LPSCI_TransferStopRingBuffer(s_debugConsoleIO.ioBase, &s_ioLpsciHandler);
#endif
/* Disable LPSCI module. */
LPSCI_Deinit((UART0_Type *)s_debugConsoleIO.ioBase);
break;
#endif
#if defined DEBUG_CONSOLE_IO_LPUART
case DEBUG_CONSOLE_DEVICE_TYPE_LPUART:
#ifdef DEBUG_CONSOLE_TRANSFER_NON_BLOCKING
/* stop ring buffer */
LPUART_TransferStopRingBuffer(s_debugConsoleIO.ioBase, &s_ioLpuartHandler);
#endif
/* Disable LPUART module. */
LPUART_Deinit((LPUART_Type *)s_debugConsoleIO.ioBase);
break;
#endif
#if defined DEBUG_CONSOLE_IO_USBCDC
case DEBUG_CONSOLE_DEVICE_TYPE_USBCDC:
/* Disable USBCDC module. */
USB_VcomDeinit(s_debugConsoleIO.ioBase);
break;
#endif
#if (defined DEBUG_CONSOLE_IO_FLEXCOMM) || (defined DEBUG_CONSOLE_IO_VUSART)
case DEBUG_CONSOLE_DEVICE_TYPE_FLEXCOMM:
case DEBUG_CONSOLE_DEVICE_TYPE_VUSART:
#ifdef DEBUG_CONSOLE_TRANSFER_NON_BLOCKING
/* stop ring buffer */
USART_TransferStopRingBuffer(s_debugConsoleIO.ioBase, &s_ioUsartHandler);
#endif
/* deinit IO */
USART_Deinit((USART_Type *)s_debugConsoleIO.ioBase);
break;
#endif
default:
s_debugConsoleIO.ioType = DEBUG_CONSOLE_DEVICE_TYPE_NONE;
break;
}
s_debugConsoleIO.ioType = DEBUG_CONSOLE_DEVICE_TYPE_NONE;
return kStatus_Success;
}
status_t IO_WaitIdle(void)
{
switch (s_debugConsoleIO.ioType)
{
#if (defined DEBUG_CONSOLE_IO_UART)
case DEBUG_CONSOLE_DEVICE_TYPE_UART:
/* wait transfer complete flag */
while (!(UART_GetStatusFlags(s_debugConsoleIO.ioBase) & kUART_TransmissionCompleteFlag))
;
break;
#endif
#if (defined DEBUG_CONSOLE_IO_IUART)
case DEBUG_CONSOLE_DEVICE_TYPE_IUART:
/* wait transfer complete flag */
while (!(UART_GetStatusFlag(s_debugConsoleIO.ioBase, kUART_TxCompleteFlag)))
;
break;
#endif
#if defined DEBUG_CONSOLE_IO_LPSCI
case DEBUG_CONSOLE_DEVICE_TYPE_LPSCI:
/* wait transfer complete flag */
while (!(LPSCI_GetStatusFlags(s_debugConsoleIO.ioBase) & kLPSCI_TransmissionCompleteFlag))
;
break;
#endif
#if defined DEBUG_CONSOLE_IO_LPUART
case DEBUG_CONSOLE_DEVICE_TYPE_LPUART:
/* wait transfer complete flag */
while (!(LPUART_GetStatusFlags(s_debugConsoleIO.ioBase) & kLPUART_TransmissionCompleteFlag))
;
break;
#endif
#if (defined DEBUG_CONSOLE_IO_FLEXCOMM) || (defined DEBUG_CONSOLE_IO_VUSART)
case DEBUG_CONSOLE_DEVICE_TYPE_FLEXCOMM:
case DEBUG_CONSOLE_DEVICE_TYPE_VUSART:
/* wait transfer complete flag */
while (!(USART_GetStatusFlags(s_debugConsoleIO.ioBase) & kUSART_TxFifoEmptyFlag))
;
break;
#endif
default:
break;
}
return kStatus_Success;
}
#ifdef DEBUG_CONSOLE_TRANSFER_NON_BLOCKING
status_t IO_Transfer(uint8_t *ch, size_t size, bool tx)
{
status_t status = kStatus_Fail;
switch (s_debugConsoleIO.ioType)
{
#if (defined DEBUG_CONSOLE_IO_UART) || (defined DEBUG_CONSOLE_IO_IUART)
case DEBUG_CONSOLE_DEVICE_TYPE_UART:
case DEBUG_CONSOLE_DEVICE_TYPE_IUART:
{
uart_transfer_t transfer = {0U};
transfer.data = ch;
transfer.dataSize = size;
/* transfer data */
if (tx)
{
status = UART_TransferSendNonBlocking(s_debugConsoleIO.ioBase, &s_ioUartHandler, &transfer);
}
else
{
status = UART_TransferReceiveNonBlocking(s_debugConsoleIO.ioBase, &s_ioUartHandler, &transfer, NULL);
}
}
break;
#endif
#if defined DEBUG_CONSOLE_IO_LPSCI
case DEBUG_CONSOLE_DEVICE_TYPE_LPSCI:
{
lpsci_transfer_t transfer = {0U};
transfer.data = ch;
transfer.dataSize = size;
/* transfer data */
if (tx)
{
status = LPSCI_TransferSendNonBlocking(s_debugConsoleIO.ioBase, &s_ioLpsciHandler, &transfer);
}
else
{
status = LPSCI_TransferReceiveNonBlocking(s_debugConsoleIO.ioBase, &s_ioLpsciHandler, &transfer, NULL);
}
}
break;
#endif
#if defined DEBUG_CONSOLE_IO_LPUART
case DEBUG_CONSOLE_DEVICE_TYPE_LPUART:
{
lpuart_transfer_t transfer = {0U};
transfer.data = ch;
transfer.dataSize = size;
/* transfer data */
if (tx)
{
status = LPUART_TransferSendNonBlocking(s_debugConsoleIO.ioBase, &s_ioLpuartHandler, &transfer);
}
else
{
status =
LPUART_TransferReceiveNonBlocking(s_debugConsoleIO.ioBase, &s_ioLpuartHandler, &transfer, NULL);
}
}
break;
#endif
#if defined DEBUG_CONSOLE_IO_USBCDC
case DEBUG_CONSOLE_DEVICE_TYPE_USBCDC:
{
if (tx)
{
USB_VcomWriteBlocking(s_debugConsoleIO.ioBase, ch, size);
}
else
{
USB_VcomReadBlocking(s_debugConsoleIO.ioBase, ch, size);
}
}
break;
#endif
#if (defined DEBUG_CONSOLE_IO_FLEXCOMM) || (defined DEBUG_CONSOLE_IO_VUSART)
case DEBUG_CONSOLE_DEVICE_TYPE_FLEXCOMM:
case DEBUG_CONSOLE_DEVICE_TYPE_VUSART:
{
usart_transfer_t transfer = {0U};
transfer.data = ch;
transfer.dataSize = size;
/* transfer data */
if (tx)
{
status = USART_TransferSendNonBlocking(s_debugConsoleIO.ioBase, &s_ioUsartHandler, &transfer);
}
else
{
status = USART_TransferReceiveNonBlocking(s_debugConsoleIO.ioBase, &s_ioUsartHandler, &transfer, NULL);
}
}
break;
#endif
default:
break;
}
return status;
}
#else
status_t IO_Transfer(uint8_t *ch, size_t size, bool tx)
{
status_t status = kStatus_Success;
switch (s_debugConsoleIO.ioType)
{
#if (defined DEBUG_CONSOLE_IO_UART) || (defined DEBUG_CONSOLE_IO_IUART)
case DEBUG_CONSOLE_DEVICE_TYPE_UART:
case DEBUG_CONSOLE_DEVICE_TYPE_IUART:
{
if (tx)
{
UART_WriteBlocking(s_debugConsoleIO.ioBase, ch, size);
}
else
{
status = UART_ReadBlocking(s_debugConsoleIO.ioBase, ch, size);
}
}
break;
#endif
#if defined DEBUG_CONSOLE_IO_LPSCI
case DEBUG_CONSOLE_DEVICE_TYPE_LPSCI:
{
if (tx)
{
LPSCI_WriteBlocking(s_debugConsoleIO.ioBase, ch, size);
}
else
{
status = LPSCI_ReadBlocking(s_debugConsoleIO.ioBase, ch, size);
}
}
break;
#endif
#if defined DEBUG_CONSOLE_IO_LPUART
case DEBUG_CONSOLE_DEVICE_TYPE_LPUART:
{
if (tx)
{
LPUART_WriteBlocking(s_debugConsoleIO.ioBase, ch, size);
}
else
{
status = LPUART_ReadBlocking(s_debugConsoleIO.ioBase, ch, size);
}
}
break;
#endif
#if defined DEBUG_CONSOLE_IO_USBCDC
case DEBUG_CONSOLE_DEVICE_TYPE_USBCDC:
{
if (tx)
{
USB_VcomWriteBlocking(s_debugConsoleIO.ioBase, ch, size);
}
else
{
status = USB_VcomReadBlocking(s_debugConsoleIO.ioBase, ch, size);
}
}
break;
#endif
#if (defined DEBUG_CONSOLE_IO_FLEXCOMM) || (defined DEBUG_CONSOLE_IO_VUSART)
case DEBUG_CONSOLE_DEVICE_TYPE_FLEXCOMM:
case DEBUG_CONSOLE_DEVICE_TYPE_VUSART:
{
if (tx)
{
USART_WriteBlocking(s_debugConsoleIO.ioBase, ch, size);
}
else
{
status = USART_ReadBlocking(s_debugConsoleIO.ioBase, ch, size);
}
}
break;
#endif
default:
status = kStatus_Fail;
break;
}
return status;
}
#endif /* DEBUG_CONSOLE_TRANSFER_NON_BLOCKING */

Some files were not shown because too many files have changed in this diff Show More