添加PAN159资料
This commit is contained in:
@@ -0,0 +1,97 @@
|
||||
/**************************************************************************//**
|
||||
* @file acmp.c
|
||||
* @version V1.00
|
||||
* $Revision: 2 $
|
||||
* $Date: 15/02/24 7:19p $
|
||||
* @brief Mini58 series Analog Comparator(ACMP) driver source file
|
||||
*
|
||||
* @note
|
||||
* Copyright (C) 2015 Nuvoton Technology Corp. All rights reserved.
|
||||
*****************************************************************************/
|
||||
|
||||
#include "Mini58Series.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
/** @addtogroup Mini58_Device_Driver Mini58 Device Driver
|
||||
@{
|
||||
*/
|
||||
|
||||
/** @addtogroup Mini58_ACMP_Driver ACMP Driver
|
||||
@{
|
||||
*/
|
||||
|
||||
|
||||
/** @addtogroup Mini58_ACMP_EXPORTED_FUNCTIONS ACMP Exported Functions
|
||||
@{
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* @brief Configure the specified ACMP module
|
||||
*
|
||||
* @param[in] acmp The base address of ACMP module
|
||||
* @param[in] u32ChNum comparator number.
|
||||
* @param[in] u32NegSrc is comparator negative input selection. Including:
|
||||
* - \ref ACMP_VNEG_PIN
|
||||
* - \ref ACMP_VNEG_BANDGAP
|
||||
* - \ref ACMP_VNEG_4_OVER_24_VDD
|
||||
* - \ref ACMP_VNEG_5_OVER_24_VDD
|
||||
* - \ref ACMP_VNEG_6_OVER_24_VDD
|
||||
* - \ref ACMP_VNEG_7_OVER_24_VDD
|
||||
* - \ref ACMP_VNEG_8_OVER_24_VDD
|
||||
* - \ref ACMP_VNEG_9_OVER_24_VDD
|
||||
* - \ref ACMP_VNEG_10_OVER_24_VDD
|
||||
* - \ref ACMP_VNEG_11_OVER_24_VDD
|
||||
* - \ref ACMP_VNEG_12_OVER_24_VDD
|
||||
* - \ref ACMP_VNEG_13_OVER_24_VDD
|
||||
* - \ref ACMP_VNEG_14_OVER_24_VDD
|
||||
* - \ref ACMP_VNEG_15_OVER_24_VDD
|
||||
* - \ref ACMP_VNEG_16_OVER_24_VDD
|
||||
* - \ref ACMP_VNEG_17_OVER_24_VDD
|
||||
* - \ref ACMP_VNEG_18_OVER_24_VDD
|
||||
* - \ref ACMP_VNEG_19_OVER_24_VDD
|
||||
*
|
||||
* @param[in] u32HysteresisEn is the hysteresis function option. Including:
|
||||
* - \ref ACMP_HYSTERESIS_ENABLE or
|
||||
* - \ref ACMP_HYSTERESIS_DISABLE
|
||||
* @return None
|
||||
*/
|
||||
void ACMP_Open(ACMP_T *acmp, uint32_t u32ChNum, uint32_t u32NegSrc, uint32_t u32HysteresisEn)
|
||||
{
|
||||
if(u32NegSrc != ACMP_VNEG_PIN)
|
||||
ACMP->VREF = u32NegSrc;
|
||||
ACMP->CTL[u32ChNum] = (ACMP->CTL[u32ChNum] & (~(ACMP_CTL_NEGSEL_Msk | ACMP_CTL_HYSSEL_Msk))) |
|
||||
((u32NegSrc != ACMP_VNEG_PIN ? ACMP_CTL_NEGSEL_Msk : 0) | u32HysteresisEn | ACMP_CTL_ACMPEN_Msk);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function close comparator
|
||||
*
|
||||
* @param[in] acmp The base address of ACMP module
|
||||
* @param[in] u32ChNum comparator number.
|
||||
*
|
||||
* @return None
|
||||
*/
|
||||
void ACMP_Close(ACMP_T *acmp, uint32_t u32ChNum)
|
||||
{
|
||||
ACMP->CTL[u32ChNum] &= (~ACMP_CTL_ACMPEN_Msk);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*@}*/ /* end of group Mini58_ACMP_EXPORTED_FUNCTIONS */
|
||||
|
||||
/*@}*/ /* end of group Mini58_ACMP_Driver */
|
||||
|
||||
/*@}*/ /* end of group Mini58_Device_Driver */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
/*** (C) COPYRIGHT 2015 Nuvoton Technology Corp. ***/
|
||||
|
||||
@@ -0,0 +1,226 @@
|
||||
/**************************************************************************//**
|
||||
* @file adc.c
|
||||
* @version V1.00
|
||||
* $Revision: 4 $
|
||||
* $Date: 15/07/21 3:15p $
|
||||
* @brief Mini58 series ADC driver source file
|
||||
*
|
||||
* @note
|
||||
* Copyright (C) 2015 Nuvoton Technology Corp. All rights reserved.
|
||||
*****************************************************************************/
|
||||
#include "Mini58Series.h"
|
||||
|
||||
/** @addtogroup Mini58_Device_Driver Mini58 Device Driver
|
||||
@{
|
||||
*/
|
||||
|
||||
/** @addtogroup Mini58_ADC_Driver ADC Driver
|
||||
@{
|
||||
*/
|
||||
|
||||
|
||||
/** @addtogroup Mini58_ADC_EXPORTED_FUNCTIONS ADC Exported Functions
|
||||
@{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief This API configures ADC module to be ready for convert the input from selected channel
|
||||
* @param[in] adc Base address of ADC module
|
||||
* @param[in] u32InputMode This parameter is unused
|
||||
* @param[in] u32OpMode This parameter is unused
|
||||
* @param[in] u32ChMask Channel enable bit. Each bit corresponds to a input channel. Bit 0 is channel 0, bit 1 is channel 1...
|
||||
* @return None
|
||||
* @note Mini58 series MCU ADC can only convert 1 channel at a time. If more than 1 channels are enabled, only channel
|
||||
* with smallest number will be convert.
|
||||
* @note This API does not turn on ADC power nor does trigger ADC conversion
|
||||
*/
|
||||
void ADC_Open(ADC_T *adc,
|
||||
uint32_t u32InputMode,
|
||||
uint32_t u32OpMode,
|
||||
uint32_t u32ChMask)
|
||||
{
|
||||
ADC->CHEN = (ADC->CHEN & ~(ADC_CHEN_CHEN0_Msk |
|
||||
ADC_CHEN_CHEN1_Msk |
|
||||
ADC_CHEN_CHEN2_Msk |
|
||||
ADC_CHEN_CHEN3_Msk |
|
||||
ADC_CHEN_CHEN4_Msk |
|
||||
ADC_CHEN_CHEN5_Msk |
|
||||
ADC_CHEN_CHEN6_Msk |
|
||||
ADC_CHEN_CHEN7_Msk)) | u32ChMask;
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disable ADC module
|
||||
* @param[in] adc Base address of ADC module
|
||||
* @return None
|
||||
*/
|
||||
void ADC_Close(ADC_T *adc)
|
||||
{
|
||||
SYS->IPRST1 |= SYS_IPRST1_ADCRST_Msk;
|
||||
SYS->IPRST1 &= ~SYS_IPRST1_ADCRST_Msk;
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Configure the hardware trigger condition and enable hardware trigger
|
||||
* @param[in] adc Base address of ADC module
|
||||
* @param[in] u32Source Decides the hardware trigger source. Valid values are:
|
||||
* - \ref ADC_TRIGGER_BY_EXT_PIN
|
||||
* - \ref ADC_TRIGGER_BY_PWM
|
||||
* @param[in] u32Param While ADC trigger by PWM, this parameter is used to set the delay between PWM
|
||||
* trigger and ADC conversion. Valid values are from 0 ~ 0xFF, and actual delay
|
||||
* time is (4 * u32Param * HCLK). While ADC trigger by external pin, this parameter
|
||||
* is used to set trigger condition. Valid values are:
|
||||
* - \ref ADC_FALLING_EDGE_TRIGGER
|
||||
* - \ref ADC_RISING_EDGE_TRIGGER
|
||||
* @return None
|
||||
*/
|
||||
void ADC_EnableHWTrigger(ADC_T *adc,
|
||||
uint32_t u32Source,
|
||||
uint32_t u32Param)
|
||||
{
|
||||
ADC->CTL &= ~(ADC_TRIGGER_BY_PWM | ADC_RISING_EDGE_TRIGGER | ADC_CTL_HWTRGEN_Msk);
|
||||
if(u32Source == ADC_TRIGGER_BY_EXT_PIN) {
|
||||
ADC->CTL |= u32Source | u32Param | ADC_CTL_HWTRGEN_Msk;
|
||||
} else {
|
||||
ADC->TRGDLY = (ADC->TRGDLY & ~ADC_TRGDLY_DELAY_Msk) | u32Param;
|
||||
ADC->CTL |= u32Source | ADC_CTL_HWTRGEN_Msk;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disable hardware trigger ADC function.
|
||||
* @param[in] adc Base address of ADC module
|
||||
* @return None
|
||||
*/
|
||||
void ADC_DisableHWTrigger(ADC_T *adc)
|
||||
{
|
||||
ADC->CTL &= ~(ADC_TRIGGER_BY_PWM | ADC_RISING_EDGE_TRIGGER | ADC_CTL_HWTRGEN_Msk);
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set ADC sample time for designated channel.
|
||||
* @param[in] adc Base address of ADC module
|
||||
* @param[in] u32ChNum This parameter is not used
|
||||
* @param[in] u32SampleTime ADC sample ADC time, valid values are
|
||||
* - \ref ADC_SAMPLE_CLOCK_0
|
||||
* - \ref ADC_SAMPLE_CLOCK_1
|
||||
* - \ref ADC_SAMPLE_CLOCK_2
|
||||
* - \ref ADC_SAMPLE_CLOCK_4
|
||||
* - \ref ADC_SAMPLE_CLOCK_8
|
||||
* - \ref ADC_SAMPLE_CLOCK_16
|
||||
* - \ref ADC_SAMPLE_CLOCK_32
|
||||
* - \ref ADC_SAMPLE_CLOCK_64
|
||||
* - \ref ADC_SAMPLE_CLOCK_128
|
||||
* - \ref ADC_SAMPLE_CLOCK_256
|
||||
* - \ref ADC_SAMPLE_CLOCK_512
|
||||
* - \ref ADC_SAMPLE_CLOCK_1024
|
||||
* @return None
|
||||
*/
|
||||
void ADC_SetExtraSampleTime(ADC_T *adc,
|
||||
uint32_t u32ChNum,
|
||||
uint32_t u32SampleTime)
|
||||
{
|
||||
ADC->EXTSMPT = (ADC->EXTSMPT & ~ADC_EXTSMPT_EXTSMPT_Msk) | u32SampleTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable the interrupt(s) selected by u32Mask parameter.
|
||||
* @param[in] adc Base address of ADC module
|
||||
* @param[in] u32Mask The combination of interrupt status bits listed below. Each bit
|
||||
* corresponds to a interrupt status. This parameter decides which
|
||||
* interrupts will be enabled.
|
||||
* - \ref ADC_ADIF_INT
|
||||
* - \ref ADC_CMP0_INT
|
||||
* - \ref ADC_CMP1_INT
|
||||
* @return None
|
||||
*/
|
||||
void ADC_EnableInt(ADC_T *adc, uint32_t u32Mask)
|
||||
{
|
||||
if(u32Mask & ADC_ADIF_INT)
|
||||
ADC->CTL |= ADC_CTL_ADCIEN_Msk;
|
||||
if(u32Mask & ADC_CMP0_INT)
|
||||
ADC->CMP0 |= ADC_CMP0_ADCMPIE_Msk;
|
||||
if(u32Mask & ADC_CMP1_INT)
|
||||
ADC->CMP1 |= ADC_CMP1_ADCMPIE_Msk;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disable the interrupt(s) selected by u32Mask parameter.
|
||||
* @param[in] adc Base address of ADC module
|
||||
* @param[in] u32Mask The combination of interrupt status bits listed below. Each bit
|
||||
* corresponds to a interrupt status. This parameter decides which
|
||||
* interrupts will be disabled.
|
||||
* - \ref ADC_ADIF_INT
|
||||
* - \ref ADC_CMP0_INT
|
||||
* - \ref ADC_CMP1_INT
|
||||
* @return None
|
||||
*/
|
||||
void ADC_DisableInt(ADC_T *adc, uint32_t u32Mask)
|
||||
{
|
||||
if(u32Mask & ADC_ADIF_INT)
|
||||
ADC->CTL &= ~ADC_CTL_ADCIEN_Msk;
|
||||
if(u32Mask & ADC_CMP0_INT)
|
||||
ADC->CMP0 &= ~ADC_CMP0_ADCMPIE_Msk;
|
||||
if(u32Mask & ADC_CMP1_INT)
|
||||
ADC->CMP1 &= ~ADC_CMP1_ADCMPIE_Msk;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief ADC PWM Sequential Mode Control.
|
||||
* @param[in] adc Base address of ADC module
|
||||
* @param[in] u32SeqTYPE This parameter decides which type will be selected.
|
||||
* - \ref ADC_SEQMODE_TYPE_23SHUNT
|
||||
* - \ref ADC_SEQMODE_TYPE_1SHUNT
|
||||
* @param[in] u32ModeSel This parameter decides which mode will be selected.
|
||||
* - \ref ADC_SEQMODE_MODESELECT_CH01
|
||||
* - \ref ADC_SEQMODE_MODESELECT_CH12
|
||||
* - \ref ADC_SEQMODE_MODESELECT_CH02
|
||||
* @return None
|
||||
*/
|
||||
void ADC_SeqModeEnable(ADC_T *adc, uint32_t u32SeqTYPE, uint32_t u32ModeSel)
|
||||
{
|
||||
// Enable ADC Sequential Mode
|
||||
ADC->SEQCTL = ADC->SEQCTL | ADC_SEQCTL_SEQEN_Msk;
|
||||
|
||||
// Select ADC Sequential Mode Type
|
||||
ADC->SEQCTL = (ADC->SEQCTL & ~(ADC_SEQCTL_SEQTYPE_Msk)) | (u32SeqTYPE << ADC_SEQCTL_SEQTYPE_Pos);
|
||||
|
||||
// Select ADC Sequential Mode Type
|
||||
ADC->SEQCTL = (ADC->SEQCTL & ~(ADC_SEQCTL_MODESEL_Msk)) | (u32ModeSel << ADC_SEQCTL_MODESEL_Pos);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief ADC PWM Sequential Mode PWM Trigger Source and type.
|
||||
* @param[in] adc Base address of ADC module
|
||||
* @param[in] u32SeqModeTriSrc1 This parameter decides first PWM trigger source and type.
|
||||
* @param[in] u32SeqModeTriSrc2 This parameter decides second PWM trigger source and type.
|
||||
*
|
||||
*
|
||||
* @return None
|
||||
*/
|
||||
void ADC_SeqModeTriggerSrc(ADC_T *adc, uint32_t u32SeqModeTriSrc1, uint32_t u32SeqModeTriSrc2)
|
||||
{
|
||||
// Select PWM Trigger Source Selection for TRG1CTL or TRG2CTL
|
||||
ADC->SEQCTL = (ADC->SEQCTL & ~(ADC_SEQCTL_TRG1CTL_Msk)) | (u32SeqModeTriSrc1 << ADC_SEQCTL_TRG1CTL_Pos);
|
||||
ADC->SEQCTL = (ADC->SEQCTL & ~(ADC_SEQCTL_TRG2CTL_Msk)) | (u32SeqModeTriSrc2 << ADC_SEQCTL_TRG2CTL_Pos);
|
||||
return;
|
||||
}
|
||||
|
||||
/*@}*/ /* end of group Mini58_ADC_EXPORTED_FUNCTIONS */
|
||||
|
||||
/*@}*/ /* end of group Mini58_ADC_Driver */
|
||||
|
||||
/*@}*/ /* end of group Mini58_Device_Driver */
|
||||
|
||||
/*** (C) COPYRIGHT 2015 Nuvoton Technology Corp. ***/
|
||||
@@ -0,0 +1,615 @@
|
||||
/**************************************************************************//**
|
||||
* @file clk.c
|
||||
* @version V1.00
|
||||
* $Revision: 15 $
|
||||
* $Date: 15/06/05 9:39a $
|
||||
* @brief Mini58 series CLK driver source file
|
||||
*
|
||||
* @note
|
||||
* Copyright (C) 2015 Nuvoton Technology Corp. All rights reserved.
|
||||
*****************************************************************************/
|
||||
#include "Mini58Series.h"
|
||||
/** @addtogroup Mini58_Device_Driver Mini58 Device Driver
|
||||
@{
|
||||
*/
|
||||
|
||||
/** @addtogroup Mini58_CLK_Driver CLK Driver
|
||||
@{
|
||||
*/
|
||||
|
||||
|
||||
/** @addtogroup Mini58_CLK_EXPORTED_FUNCTIONS CLK Exported Functions
|
||||
@{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief This function disable frequency output function.
|
||||
* @return None
|
||||
*/
|
||||
void CLK_DisableCKO(void)
|
||||
{
|
||||
/* Disable CKO clock source */
|
||||
CLK->APBCLK &= (~CLK_APBCLK_CLKOCKEN_Msk);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function enable frequency divider module clock,
|
||||
* enable frequency divider clock function and configure frequency divider.
|
||||
* @param[in] u32ClkSrc is frequency divider function clock source
|
||||
* - \ref CLK_CLKSEL2_CLKOSEL_XTAL
|
||||
* - \ref CLK_CLKSEL2_CLKOSEL_LIRC
|
||||
* - \ref CLK_CLKSEL2_CLKOSEL_HCLK
|
||||
* - \ref CLK_CLKSEL2_CLKOSEL_HIRC
|
||||
* @param[in] u32ClkDiv Set the clock divider to CKO. 0 <= u32ClkDiv <= 15
|
||||
* @param[in] u32ClkDivBy1En is frequency divided by one enable.
|
||||
* @return None
|
||||
*
|
||||
* @details Output selected clock to CKO. The output clock frequency is divided by u32ClkDiv.
|
||||
* The formula is:
|
||||
* CKO frequency = (Clock source frequency) / 2^(u32ClkDiv + 1)
|
||||
* This function is just used to set CKO clock.
|
||||
* User must enable I/O for CKO clock output pin by themselves.
|
||||
*/
|
||||
void CLK_EnableCKO(uint32_t u32ClkSrc, uint32_t u32ClkDiv, uint32_t u32ClkDivBy1En)
|
||||
{
|
||||
/* CKO = clock source / 2^(u32ClkDiv + 1) */
|
||||
CLK->CLKOCTL = CLK_CLKOCTL_CLKOEN_Msk | u32ClkDiv | u32ClkDivBy1En<<CLK_CLKOCTL_DIV1EN_Pos;
|
||||
|
||||
/* Enable CKO clock source */
|
||||
CLK->APBCLK |= CLK_APBCLK_CLKOCKEN_Msk;
|
||||
|
||||
/* Select CKO clock source */
|
||||
CLK->CLKSEL2 = (CLK->CLKSEL2 & (~CLK_CLKSEL2_CLKOSEL_Msk)) | u32ClkSrc;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function let system enter to Power-down mode.
|
||||
* @return None
|
||||
*/
|
||||
void CLK_PowerDown(void)
|
||||
{
|
||||
SCB->SCR = SCB_SCR_SLEEPDEEP_Msk;
|
||||
CLK->PWRCTL |= (CLK_PWRCTL_PDEN_Msk | CLK_PWRCTL_PDWKIF_Msk);
|
||||
__WFI();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function let system enter to Idle mode
|
||||
* @return None
|
||||
*/
|
||||
void CLK_Idle(void)
|
||||
{
|
||||
CLK->PWRCTL |= (CLK_PWRCTL_PDEN_Msk | CLK_PWRCTL_PDWKIF_Msk);
|
||||
__WFI();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function get external high frequency crystal frequency. The frequency unit is Hz.
|
||||
* @return None
|
||||
*/
|
||||
uint32_t CLK_GetHXTFreq(void)
|
||||
{
|
||||
if((CLK->PWRCTL & CLK_PWRCTL_XTLEN_Msk)==CLK_PWRCTL_XTLEN_HXT )
|
||||
return __HXT;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function get external low frequency crystal frequency. The frequency unit is Hz.
|
||||
* @return LXT frequency
|
||||
*/
|
||||
uint32_t CLK_GetLXTFreq(void)
|
||||
{
|
||||
if((CLK->PWRCTL & CLK_PWRCTL_XTLEN_Msk )==CLK_PWRCTL_XTLEN_LXT )
|
||||
return __XTAL;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function get HCLK frequency. The frequency unit is Hz.
|
||||
* @return HCLK frequency
|
||||
*/
|
||||
uint32_t CLK_GetHCLKFreq(void)
|
||||
{
|
||||
SystemCoreClockUpdate();
|
||||
return SystemCoreClock;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief This function get CPU frequency. The frequency unit is Hz.
|
||||
* @return CPU frequency
|
||||
*/
|
||||
uint32_t CLK_GetCPUFreq(void)
|
||||
{
|
||||
SystemCoreClockUpdate();
|
||||
return SystemCoreClock;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set HCLK frequency
|
||||
* @param[in] u32Hclk is HCLK frequency. The range of u32Hclk is 26 MHz ~ 50 MHz.
|
||||
* @return HCLK frequency
|
||||
* @details This function is used to set HCLK frequency. The frequency unit is Hz.
|
||||
* It would configure PLL frequency to 100MHz ~ 200MHz,
|
||||
* set HCLK clock divider as 2 and switch HCLK clock source to PLL.
|
||||
* The register write-protection function should be disabled before using this function.
|
||||
*/
|
||||
uint32_t CLK_SetCoreClock(uint32_t u32Hclk)
|
||||
{
|
||||
uint32_t u32HIRCSTB;
|
||||
|
||||
/* Read HIRC clock source stable flag */
|
||||
u32HIRCSTB = CLK->STATUS & CLK_STATUS_HIRCSTB_Msk;
|
||||
|
||||
/* The range of u32Hclk is 25 MHz ~ 50 MHz */
|
||||
if(u32Hclk > FREQ_50MHZ)
|
||||
u32Hclk = FREQ_50MHZ;
|
||||
if(u32Hclk < FREQ_25MHZ)
|
||||
u32Hclk = FREQ_25MHZ;
|
||||
|
||||
/* Switch HCLK clock source to HIRC clock for safe */
|
||||
CLK->PWRCTL |= CLK_PWRCTL_HIRCEN_Msk;
|
||||
CLK_WaitClockReady(CLK_STATUS_HIRCSTB_Msk);
|
||||
CLK->CLKSEL0 |= CLK_CLKSEL0_HCLKSEL_Msk;
|
||||
CLK->CLKDIV &= (~CLK_CLKDIV_HCLKDIV_Msk);
|
||||
|
||||
/* Configure PLL setting if HXT clock is enabled */
|
||||
if( (CLK->PWRCTL & CLK_PWRCTL_XTLEN_Msk)==CLK_PWRCTL_XTLEN_HXT )
|
||||
u32Hclk = CLK_EnablePLL(CLK_PLLCTL_PLLSRC_HXT, (u32Hclk << 1));
|
||||
|
||||
/* Configure PLL setting if HXT clock is not enabled */
|
||||
else {
|
||||
u32Hclk = CLK_EnablePLL(CLK_PLLCTL_PLLSRC_HIRC, (u32Hclk << 1));
|
||||
|
||||
/* Read HIRC clock source stable flag */
|
||||
u32HIRCSTB = CLK->STATUS & CLK_STATUS_HIRCSTB_Msk;
|
||||
}
|
||||
|
||||
/* Select HCLK clock source to PLL,
|
||||
Select HCLK clock source divider as 2
|
||||
and update system core clock
|
||||
*/
|
||||
//CLK_SetHCLK(CLK_CLKSEL0_HCLKSEL_PLL, CLK_CLKDIV_HCLK(2));
|
||||
CLK_SetHCLK(CLK_CLKSEL0_HCLKSEL_PLL, CLK_CLKDIV_HCLK(2));
|
||||
/* Disable HIRC if HIRC is disabled before setting core clock */
|
||||
if(u32HIRCSTB == 0)
|
||||
CLK->PWRCTL &= ~CLK_PWRCTL_HIRCEN_Msk;
|
||||
|
||||
/* Return actually HCLK frequency is PLL frequency divide 2 */
|
||||
return u32Hclk >> 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function set HCLK clock source and HCLK clock divider
|
||||
* @param[in] u32ClkSrc is HCLK clock source. Including :
|
||||
* - \ref CLK_CLKSEL0_HCLKSEL_XTAL
|
||||
* - \ref CLK_CLKSEL0_HCLKSEL_LIRC
|
||||
* - \ref CLK_CLKSEL0_HCLKSEL_HIRC
|
||||
* @param[in] u32ClkDiv is HCLK clock divider. Including :
|
||||
* - \ref CLK_CLKDIV_HCLK(x)
|
||||
* @return None
|
||||
*/
|
||||
void CLK_SetHCLK(uint32_t u32ClkSrc, uint32_t u32ClkDiv)
|
||||
{
|
||||
/* Apply new Divider */
|
||||
CLK->CLKDIV = (CLK->CLKDIV & ~CLK_CLKDIV_HCLKDIV_Msk) | u32ClkDiv;
|
||||
|
||||
/* Switch HCLK to new HCLK source */
|
||||
CLK->CLKSEL0 = (CLK->CLKSEL0 & ~CLK_CLKSEL0_HCLKSEL_Msk) | u32ClkSrc;
|
||||
|
||||
/* Update System Core Clock */
|
||||
SystemCoreClockUpdate();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function set selected module clock source and module clock divider
|
||||
* @param[in] u32ModuleIdx is module index.
|
||||
* @param[in] u32ClkSrc is module clock source.
|
||||
* @param[in] u32ClkDiv is module clock divider.
|
||||
* @return None
|
||||
* @details Valid parameter combinations listed in following table:
|
||||
*
|
||||
* |Module index |Clock source |Divider |
|
||||
* | :---------------- | :----------------------------------- | :--------------------- |
|
||||
* |\ref WDT_MODULE |\ref CLK_CLKSEL1_WDTSEL_XTAL | x |
|
||||
* |\ref WDT_MODULE |\ref CLK_CLKSEL1_WDTSEL_HCLK_DIV2048 | x |
|
||||
* |\ref WDT_MODULE |\ref CLK_CLKSEL1_WDTSEL_LIRC | x |
|
||||
* |\ref TMR0_MODULE |\ref CLK_CLKSEL1_TMR0SEL_XTAL | x |
|
||||
* |\ref TMR0_MODULE |\ref CLK_CLKSEL1_TMR0SEL_LIRC | x |
|
||||
* |\ref TMR0_MODULE |\ref CLK_CLKSEL1_TMR0SEL_HCLK | x |
|
||||
* |\ref TMR0_MODULE |\ref CLK_CLKSEL1_TMR0SEL_TM0 | x |
|
||||
* |\ref TMR0_MODULE |\ref CLK_CLKSEL1_TMR0SEL_HIRC | x |
|
||||
* |\ref TMR1_MODULE |\ref CLK_CLKSEL1_TMR1SEL_XTAL | x |
|
||||
* |\ref TMR1_MODULE |\ref CLK_CLKSEL1_TMR1SEL_LIRC | x |
|
||||
* |\ref TMR1_MODULE |\ref CLK_CLKSEL1_TMR1SEL_HCLK | x |
|
||||
* |\ref TMR1_MODULE |\ref CLK_CLKSEL1_TMR1SEL_TM1 | x |
|
||||
* |\ref TMR1_MODULE |\ref CLK_CLKSEL1_TMR1SEL_HIRC | x |
|
||||
* |\ref CLKO_MODULE |\ref CLK_CLKSEL2_CLKOSEL_XTAL | x |
|
||||
* |\ref CLKO_MODULE |\ref CLK_CLKSEL2_CLKOSEL_HCLK | x |
|
||||
* |\ref CLKO_MODULE |\ref CLK_CLKSEL2_CLKOSEL_HIRC | x |
|
||||
* |\ref I2C0_MODULE | x | x |
|
||||
* |\ref I2C1_MODULE | x | x |
|
||||
* |\ref SPI0_MODULE |\ref CLK_CLKSEL1_SPISEL_XTAL | x |
|
||||
* |\ref SPI0_MODULE |\ref CLK_CLKSEL1_SPISEL_HCLK | x |
|
||||
* |\ref SPI0_MODULE |\ref CLK_CLKSEL1_SPISEL_PLL | x |
|
||||
* |\ref UART0_MODULE |\ref CLK_CLKSEL1_UARTSEL_XTAL |\ref CLK_CLKDIV_UART(x) |
|
||||
* |\ref UART0_MODULE |\ref CLK_CLKSEL1_UARTSEL_PLL |\ref CLK_CLKDIV_UART(x) |
|
||||
* |\ref UART0_MODULE |\ref CLK_CLKSEL1_UARTSEL_HIRC |\ref CLK_CLKDIV_UART(x) |
|
||||
* |\ref UART1_MODULE |\ref CLK_CLKSEL1_UARTSEL_XTAL |\ref CLK_CLKDIV_UART(x) |
|
||||
* |\ref UART1_MODULE |\ref CLK_CLKSEL1_UARTSEL_PLL |\ref CLK_CLKDIV_UART(x) |
|
||||
* |\ref UART1_MODULE |\ref CLK_CLKSEL1_UARTSEL_HIRC |\ref CLK_CLKDIV_UART(x) |
|
||||
* |\ref PWMCH01_MODULE |\ref CLK_CLKSEL1_PWMCH01SEL_HCLK | x |
|
||||
* |\ref PWMCH23_MODULE |\ref CLK_CLKSEL1_PWMCH23SEL_HCLK | x |
|
||||
* |\ref PWMCH45_MODULE |\ref CLK_CLKSEL2_PWMCH45SEL_HCLK | x |
|
||||
* |\ref ADC_MODULE |\ref CLK_CLKSEL1_ADCSEL_XTAL |\ref CLK_CLKDIV_ADC(x) |
|
||||
* |\ref ADC_MODULE |\ref CLK_CLKSEL1_ADCSEL_PLL |\ref CLK_CLKDIV_ADC(x) |
|
||||
* |\ref ADC_MODULE |\ref CLK_CLKSEL1_ADCSEL_HCLK |\ref CLK_CLKDIV_ADC(x) |
|
||||
* |\ref ADC_MODULE |\ref CLK_CLKSEL1_ADCSEL_HIRC |\ref CLK_CLKDIV_ADC(x) |
|
||||
* |\ref ACMP_MODULE | x | x |
|
||||
* |\ref WWDT_MODULE |\ref CLK_CLKSEL2_WWDTSEL_HCLK_DIV2048 | x |
|
||||
* |\ref WWDT_MODULE |\ref CLK_CLKSEL2_WWDTSEL_LIRC | x |
|
||||
*/
|
||||
|
||||
void CLK_SetModuleClock(uint32_t u32ModuleIdx, uint32_t u32ClkSrc, uint32_t u32ClkDiv)
|
||||
{
|
||||
uint32_t u32tmp=0,u32sel=0,u32div=0;
|
||||
|
||||
if(MODULE_CLKSEL_Msk(u32ModuleIdx)!=MODULE_NoMsk) {
|
||||
u32sel = (uint32_t)&CLK->CLKSEL0+((MODULE_CLKSEL(u32ModuleIdx))*4);
|
||||
u32tmp = *(volatile uint32_t *)(u32sel);
|
||||
u32tmp = ( u32tmp & ~(MODULE_CLKSEL_Msk(u32ModuleIdx)<<MODULE_CLKSEL_Pos(u32ModuleIdx)) ) | u32ClkSrc;
|
||||
*(volatile uint32_t *)(u32sel) = u32tmp;
|
||||
}
|
||||
|
||||
if(MODULE_CLKDIV_Msk(u32ModuleIdx)!=MODULE_NoMsk) {
|
||||
u32div =(uint32_t)&CLK->CLKDIV+((MODULE_CLKDIV(u32ModuleIdx))*4);
|
||||
u32tmp = *(volatile uint32_t *)(u32div);
|
||||
u32tmp = ( u32tmp & ~(MODULE_CLKDIV_Msk(u32ModuleIdx)<<MODULE_CLKDIV_Pos(u32ModuleIdx)) ) | u32ClkDiv;
|
||||
*(volatile uint32_t *)(u32div) = u32tmp;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function set SysTick clock source
|
||||
* @param[in] u32ClkSrc is module clock source. Including
|
||||
* - \ref CLK_CLKSEL0_STCLKSEL_XTAL
|
||||
* - \ref CLK_CLKSEL0_STCLKSEL_XTAL_DIV2
|
||||
* - \ref CLK_CLKSEL0_STCLKSEL_HCLK_DIV2
|
||||
* - \ref CLK_CLKSEL0_STCLKSEL_HIRC_DIV2
|
||||
* @return None
|
||||
*/
|
||||
void CLK_SetSysTickClockSrc(uint32_t u32ClkSrc)
|
||||
{
|
||||
CLK->CLKSEL0 = (CLK->CLKSEL0 & ~CLK_CLKSEL0_STCLKSEL_Msk) | u32ClkSrc;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable System Tick counter
|
||||
* @param[in] u32ClkSrc is System Tick clock source. Including:
|
||||
* - \ref CLK_CLKSEL0_STCLKSEL_XTAL
|
||||
* - \ref CLK_CLKSEL0_STCLKSEL_XTAL_DIV2
|
||||
* - \ref CLK_CLKSEL0_STCLKSEL_HCLK_DIV2
|
||||
* - \ref CLK_CLKSEL0_STCLKSEL_HIRC_DIV2
|
||||
* - \ref CLK_CLKSEL0_STCLKSEL_HCLK
|
||||
* @param[in] u32Count is System Tick reload value. It should be 0x1~0xFFFFFF.
|
||||
* @return None
|
||||
* @details This function set System Tick clock source, reload value, enable System Tick counter and interrupt.
|
||||
* The register write-protection function should be disabled before using this function.
|
||||
*/
|
||||
void CLK_EnableSysTick(uint32_t u32ClkSrc, uint32_t u32Count)
|
||||
{
|
||||
SysTick->CTRL=0;
|
||||
if( u32ClkSrc== CLK_CLKSEL0_STCLKSEL_HCLK ) /* Set System Tick clock source */
|
||||
SysTick->CTRL |= SysTick_CTRL_CLKSOURCE_Msk;
|
||||
else {
|
||||
SysTick->CTRL &= ~SysTick_CTRL_CLKSOURCE_Msk;
|
||||
CLK->CLKSEL0 = (CLK->CLKSEL0 & ~CLK_CLKSEL0_STCLKSEL_Msk) | u32ClkSrc;
|
||||
}
|
||||
SysTick->LOAD = u32Count; /* Set System Tick reload value */
|
||||
SysTick->VAL = 0; /* Clear System Tick current value and counter flag */
|
||||
SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk; /* Set System Tick counter enabled */
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disable System Tick counter
|
||||
* @return None
|
||||
* @details This function disable System Tick counter.
|
||||
*/
|
||||
void CLK_DisableSysTick(void)
|
||||
{
|
||||
SysTick->CTRL = 0; /* Set System Tick counter disabled */
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function enable clock source
|
||||
* @param[in] u32ClkMask is clock source mask. Including :
|
||||
* - \ref CLK_PWRCTL_XTLEN_HXT or \ref CLK_PWRCTL_XTLEN_LXT,
|
||||
* - \ref CLK_PWRCTL_LIRCEN_Msk
|
||||
* - \ref CLK_PWRCTL_HIRCEN_Msk
|
||||
* @return None
|
||||
*/
|
||||
void CLK_EnableXtalRC(uint32_t u32ClkMask)
|
||||
{
|
||||
if(u32ClkMask & CLK_PWRCTL_XTLEN_Msk)
|
||||
CLK->PWRCTL = (CLK->PWRCTL & ~CLK_PWRCTL_XTLEN_Msk) | u32ClkMask;
|
||||
else
|
||||
CLK->PWRCTL |= u32ClkMask;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function disable clock source
|
||||
* @param[in] u32ClkMask is clock source mask. Including :
|
||||
* - \ref CLK_PWRCTL_XTLEN_Msk,
|
||||
* - \ref CLK_PWRCTL_LIRCEN_Msk,
|
||||
* - \ref CLK_PWRCTL_HIRCEN_Msk,
|
||||
* @return None
|
||||
*/
|
||||
void CLK_DisableXtalRC(uint32_t u32ClkMask)
|
||||
{
|
||||
CLK->PWRCTL &=~u32ClkMask;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function enable module clock
|
||||
* @param[in] u32ModuleIdx is module index. Including :
|
||||
* - \ref WDT_MODULE
|
||||
* - \ref TMR0_MODULE
|
||||
* - \ref TMR1_MODULE
|
||||
* - \ref CLKO_MODULE
|
||||
* - \ref I2C0_MODULE
|
||||
* - \ref I2C1_MODULE
|
||||
* - \ref SPI0_MODULE
|
||||
* - \ref UART0_MODULE
|
||||
* - \ref UART1_MODULE
|
||||
* - \ref PWMCH01_MODULE
|
||||
* - \ref PWMCH23_MODULE
|
||||
* - \ref PWMCH45_MODULE
|
||||
* - \ref ADC_MODULE
|
||||
* - \ref ACMP_MODULE
|
||||
* - \ref WWDT_MODULE
|
||||
* @return None
|
||||
*/
|
||||
void CLK_EnableModuleClock(uint32_t u32ModuleIdx)
|
||||
{
|
||||
*(volatile uint32_t *)((uint32_t)&CLK->AHBCLK+(MODULE_APBCLK(u32ModuleIdx)*4)) |= 1<<MODULE_IP_EN_Pos(u32ModuleIdx);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function disable module clock
|
||||
* @param[in] u32ModuleIdx is module index
|
||||
* - \ref WDT_MODULE
|
||||
* - \ref TMR0_MODULE
|
||||
* - \ref TMR1_MODULE
|
||||
* - \ref CLKO_MODULE
|
||||
* - \ref I2C0_MODULE
|
||||
* - \ref I2C1_MODULE
|
||||
* - \ref SPI0_MODULE
|
||||
* - \ref UART0_MODULE
|
||||
* - \ref UART1_MODULE
|
||||
* - \ref PWMCH01_MODULE
|
||||
* - \ref PWMCH23_MODULE
|
||||
* - \ref PWMCH45_MODULE
|
||||
* - \ref ADC_MODULE
|
||||
* - \ref ACMP_MODULE
|
||||
* - \ref WWDT_MODULE
|
||||
* @return None
|
||||
*/
|
||||
void CLK_DisableModuleClock(uint32_t u32ModuleIdx)
|
||||
{
|
||||
*(volatile uint32_t *)((uint32_t)&CLK->AHBCLK+(MODULE_APBCLK(u32ModuleIdx)*4)) &= ~(1<<MODULE_IP_EN_Pos(u32ModuleIdx));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set PLL frequency
|
||||
* @param[in] u32PllClkSrc is PLL clock source. Including :
|
||||
* - \ref CLK_PLLCTL_PLLSRC_HXT
|
||||
* - \ref CLK_PLLCTL_PLLSRC_HIRC
|
||||
* @param[in] u32PllFreq is PLL frequency.
|
||||
* @return PLL frequency
|
||||
* @details This function is used to configure PLLCTL register to set specified PLL frequency.
|
||||
* The register write-protection function should be disabled before using this function.
|
||||
*/
|
||||
uint32_t CLK_EnablePLL(uint32_t u32PllClkSrc, uint32_t u32PllFreq)
|
||||
{
|
||||
uint32_t u32PllSrcClk, u32NR, u32NF, u32NO, u32CLK_SRC , u32NRT;
|
||||
uint32_t u32Tmp, u32Tmp2, u32Tmp3, u32Min, u32MinNF, u32MinNR,u32Best;
|
||||
|
||||
/* Disable PLL first to avoid unstable when setting PLL */
|
||||
CLK_DisablePLL();
|
||||
|
||||
/* PLL source clock is from HXT */
|
||||
if(u32PllClkSrc == CLK_PLLCTL_PLLSRC_HXT) {
|
||||
/* Enable HXT clock */
|
||||
CLK->PWRCTL = (CLK->PWRCTL & ~CLK_PWRCTL_XTLEN_Msk) | CLK_PWRCTL_XTLEN_HXT ;
|
||||
|
||||
/* Wait for HXT clock ready */
|
||||
CLK_WaitClockReady(CLK_STATUS_XTLSTB_Msk);
|
||||
|
||||
/* Select PLL source clock from HXT */
|
||||
u32CLK_SRC = CLK_PLLCTL_PLLSRC_HXT;
|
||||
u32PllSrcClk = __XTAL;
|
||||
|
||||
/* u32NR start from 2 */
|
||||
u32NRT = 2;
|
||||
}
|
||||
|
||||
/* PLL source clock is from HIRC */
|
||||
else {
|
||||
/* Enable HIRC clock */
|
||||
CLK->PWRCTL |= CLK_PWRCTL_HIRCEN_Msk;
|
||||
|
||||
/* Wait for HIRC clock ready */
|
||||
CLK_WaitClockReady(CLK_STATUS_HIRCSTB_Msk);
|
||||
|
||||
/* Select PLL source clock from HIRC */
|
||||
u32CLK_SRC = CLK_PLLCTL_PLLSRC_HIRC;
|
||||
u32PllSrcClk = __HIRC;
|
||||
|
||||
/* u32NR start from 4 when FIN = 22.1184MHz to avoid calculation overflow */
|
||||
u32NRT = 4;
|
||||
}
|
||||
|
||||
/* Select "NO" according to request frequency */
|
||||
if((u32PllFreq <= FREQ_200MHZ) && (u32PllFreq > FREQ_100MHZ)) {
|
||||
u32NO = 0;
|
||||
u32PllFreq = u32PllFreq;
|
||||
} else if((u32PllFreq <= FREQ_100MHZ) && (u32PllFreq >= FREQ_50MHZ)) {
|
||||
u32NO = 1;
|
||||
u32PllFreq = u32PllFreq << 1;
|
||||
} else if((u32PllFreq < FREQ_50MHZ) && (u32PllFreq >= FREQ_25MHZ)) {
|
||||
u32NO = 3;
|
||||
u32PllFreq = u32PllFreq << 2;
|
||||
} else {
|
||||
/* Wrong frequency request. Just return default setting. */
|
||||
goto lexit;
|
||||
}
|
||||
|
||||
/* Find best solution */
|
||||
u32Min = (uint32_t) - 1;
|
||||
u32MinNR = 0;
|
||||
u32MinNF = 0;
|
||||
for(u32NR=u32NRT; u32NR <= 33; u32NR++) {
|
||||
u32Tmp = u32PllSrcClk / u32NR;
|
||||
if((u32Tmp > 1600000) && (u32Tmp < 15000000)) {
|
||||
for(u32NF = 2; u32NF <= 513; u32NF++) {
|
||||
u32Tmp2 = u32Tmp * u32NF;
|
||||
if((u32Tmp2 >= 100000000) && (u32Tmp2 <= 200000000)) {
|
||||
u32Tmp3 = (u32Tmp2 > u32PllFreq) ? u32Tmp2 - u32PllFreq : u32PllFreq - u32Tmp2;
|
||||
if(u32Tmp3 < u32Min) {
|
||||
u32Min = u32Tmp3;
|
||||
u32MinNR = u32NR;
|
||||
u32MinNF = u32NF;
|
||||
/* Break when get good results */
|
||||
if(u32Min == 0) {
|
||||
/* Enable and apply new PLL setting. */
|
||||
CLK->PLLCTL = u32CLK_SRC | (u32NO << 14) | ((u32MinNR - 2) << 9) | (u32MinNF - 2);
|
||||
|
||||
/* Wait for PLL clock stable */
|
||||
CLK_WaitClockReady(CLK_STATUS_PLLSTB_Msk);
|
||||
|
||||
/* Return actual PLL output clock frequency */
|
||||
return u32PllSrcClk / ((u32NO + 1) * u32MinNR) * u32MinNF;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Find best solution */
|
||||
u32Best = u32Min;
|
||||
u32Min = (uint32_t) - 1;
|
||||
u32MinNR = 0;
|
||||
u32MinNF = 0;
|
||||
for(u32NR=u32NRT; u32NR <= 33; u32NR++) {
|
||||
u32Tmp = u32PllSrcClk / u32NR;
|
||||
if((u32Tmp > 1600000) && (u32Tmp < 15000000)) {
|
||||
for(u32NF = 2; u32NF <= 513; u32NF++) {
|
||||
u32Tmp2 = u32Tmp * u32NF;
|
||||
if((u32Tmp2 >= 100000000) && (u32Tmp2 <= 200000000)) {
|
||||
u32Tmp3 = (u32Tmp2 > u32PllFreq) ? u32Tmp2 - u32PllFreq : u32PllFreq - u32Tmp2;
|
||||
if(u32Tmp3 < u32Min) {
|
||||
u32Min = u32Tmp3;
|
||||
u32MinNR = u32NR;
|
||||
u32MinNF = u32NF;
|
||||
|
||||
/* Break when get good results */
|
||||
if(u32Min == u32Best) {
|
||||
/* Enable and apply new PLL setting. */
|
||||
CLK->PLLCTL = u32CLK_SRC | (u32NO << 14) | ((u32MinNR - 2) << 9) | (u32MinNF - 2);
|
||||
|
||||
/* Wait for PLL clock stable */
|
||||
CLK_WaitClockReady(CLK_STATUS_PLLSTB_Msk);
|
||||
|
||||
/* Return actual PLL output clock frequency */
|
||||
return u32PllSrcClk / ((u32NO + 1) * u32MinNR) * u32MinNF;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
lexit:
|
||||
|
||||
/* Apply default PLL setting and return */
|
||||
if(u32PllClkSrc == CLK_PLLCTL_PLLSRC_HXT)
|
||||
CLK->PLLCTL = CLK_PLLCTL_72MHz_HXT; /* 72MHz */
|
||||
else
|
||||
CLK->PLLCTL = CLK_PLLCTL_72MHz_HIRC; /* 71.8848MHz */
|
||||
|
||||
/* Wait for PLL clock stable */
|
||||
CLK_WaitClockReady(CLK_STATUS_PLLSTB_Msk);
|
||||
|
||||
return CLK_GetPLLClockFreq();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disable PLL
|
||||
* @param None
|
||||
* @return None
|
||||
* @details This function set PLL in Power-down mode.
|
||||
* The register write-protection function should be disabled before using this function.
|
||||
*/
|
||||
void CLK_DisablePLL(void)
|
||||
{
|
||||
CLK->PLLCTL |= CLK_PLLCTL_PD_Msk;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function execute delay function.
|
||||
* @param[in] us Delay time. The Max value is 2^24 / CPU Clock(MHz). Ex:
|
||||
* 50MHz => 335544us, 48MHz => 349525us, 28MHz => 699050us ...
|
||||
* @return None
|
||||
* @details Use the SysTick to generate the delay time and the UNIT is in us.
|
||||
* The SysTick clock source is from HCLK, i.e the same as system core clock.
|
||||
*/
|
||||
void CLK_SysTickDelay(uint32_t us)
|
||||
{
|
||||
SysTick->LOAD = us * CyclesPerUs;
|
||||
SysTick->VAL = (0x00);
|
||||
SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | SysTick_CTRL_ENABLE_Msk;
|
||||
|
||||
/* Waiting for down-count to zero */
|
||||
while((SysTick->CTRL & SysTick_CTRL_COUNTFLAG_Msk) == 0);
|
||||
SysTick->CTRL = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function check selected clock source status
|
||||
* @param[in] u32ClkMask is selected clock source. Including
|
||||
* - \ref CLK_STATUS_CLKSFAIL_Msk
|
||||
* - \ref CLK_STATUS_HIRCSTB_Msk
|
||||
* - \ref CLK_STATUS_LIRCSTB_Msk
|
||||
* - \ref CLK_STATUS_XTLSTB_Msk
|
||||
*
|
||||
* @return 0 clock is not stable
|
||||
* 1 clock is stable
|
||||
*
|
||||
* @details To wait for clock ready by specified CLKSTATUS bit or timeout (~5ms)
|
||||
*/
|
||||
uint32_t CLK_WaitClockReady(uint32_t u32ClkMask)
|
||||
{
|
||||
int32_t i32TimeOutCnt = 2160000;
|
||||
|
||||
while((CLK->STATUS & u32ClkMask) != u32ClkMask) {
|
||||
if(i32TimeOutCnt-- <= 0)
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/*@}*/ /* end of group Mini58_CLK_EXPORTED_FUNCTIONS */
|
||||
|
||||
/*@}*/ /* end of group Mini58_CLK_Driver */
|
||||
|
||||
/*@}*/ /* end of group Mini58_Device_Driver */
|
||||
|
||||
/*** (C) COPYRIGHT 2015 Nuvoton Technology Corp. ***/
|
||||
@@ -0,0 +1,310 @@
|
||||
/**************************************************************************//**
|
||||
* @file fmc.c
|
||||
* @version V1.00
|
||||
* $Revision: 6 $
|
||||
* $Date: 15/05/26 6:31p $
|
||||
* @brief Mini58 series FMC driver source file
|
||||
*
|
||||
* @note
|
||||
* Copyright (C) 2015 Nuvoton Technology Corp. All rights reserved.
|
||||
*****************************************************************************/
|
||||
|
||||
//* Includes ------------------------------------------------------------------*/
|
||||
#include <stdio.h>
|
||||
#include "Mini58Series.h"
|
||||
|
||||
/** @addtogroup Mini58_Device_Driver Mini58 Device Driver
|
||||
@{
|
||||
*/
|
||||
|
||||
/** @addtogroup Mini58_FMC_Driver FMC Driver
|
||||
@{
|
||||
*/
|
||||
|
||||
|
||||
/** @addtogroup Mini58_FMC_EXPORTED_FUNCTIONS FMC Exported Functions
|
||||
@{
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief Disable all FMC functions
|
||||
*
|
||||
* @return None
|
||||
*/
|
||||
void FMC_Close(void)
|
||||
{
|
||||
FMC->ISPCTL &= ~FMC_ISPCTL_ISPEN_Msk;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Erase a page. The page size is 512 bytes.
|
||||
* @param[in] u32PageAddr Flash page address. Must be a 512-byte aligned address.
|
||||
* @retval 0 Success
|
||||
* @retval -1 Erase failed
|
||||
*/
|
||||
int32_t FMC_Erase(uint32_t u32PageAddr)
|
||||
{
|
||||
FMC->ISPCMD = FMC_ISPCMD_PAGE_ERASE;
|
||||
FMC->ISPADDR = u32PageAddr;
|
||||
FMC->ISPTRG = FMC_ISPTRG_ISPGO_Msk;
|
||||
|
||||
while (FMC->ISPTRG & FMC_ISPTRG_ISPGO_Msk) ;
|
||||
|
||||
if (FMC->ISPCTL & FMC_ISPCTL_ISPFF_Msk) {
|
||||
FMC->ISPCTL |= FMC_ISPCTL_ISPFF_Msk;
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief get the current boot source
|
||||
* @retval 0 This chip is currently booting from APROM
|
||||
* @retval 1 This chip is currently booting from LDROM
|
||||
*/
|
||||
int32_t FMC_GetBootSource (void)
|
||||
{
|
||||
if (FMC->ISPCTL & FMC_ISPCTL_BS_Msk)
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Enable FMC ISP function
|
||||
*/
|
||||
void FMC_Open(void)
|
||||
{
|
||||
FMC->ISPCTL |= FMC_ISPCTL_ISPEN_Msk;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Read a word from specified flash address.
|
||||
* @param[in] u32Addr Flash word address. Must be a word aligned address.
|
||||
* @return The word data stored in the flash address "u32Addr".
|
||||
*/
|
||||
uint32_t FMC_Read(uint32_t u32Addr)
|
||||
{
|
||||
FMC->ISPCMD = FMC_ISPCMD_READ;
|
||||
FMC->ISPADDR = u32Addr;
|
||||
FMC->ISPTRG = FMC_ISPTRG_ISPGO_Msk;
|
||||
|
||||
while (FMC->ISPTRG & FMC_ISPTRG_ISPGO_Msk) ;
|
||||
|
||||
return FMC->ISPDAT;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Read company ID.
|
||||
* @return The company ID.
|
||||
*/
|
||||
uint32_t FMC_ReadCID(void)
|
||||
{
|
||||
FMC->ISPCMD = FMC_ISPCMD_READ_CID;
|
||||
FMC->ISPADDR = 0x0;
|
||||
FMC->ISPTRG = FMC_ISPTRG_ISPGO_Msk;
|
||||
while (FMC->ISPTRG & FMC_ISPTRG_ISPGO_Msk) ;
|
||||
return FMC->ISPDAT;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Read product ID.
|
||||
* @return The product ID.
|
||||
*/
|
||||
uint32_t FMC_ReadPID(void)
|
||||
{
|
||||
FMC->ISPCMD = FMC_ISPCMD_READ_PID;
|
||||
FMC->ISPADDR = 0x04;
|
||||
FMC->ISPTRG = FMC_ISPTRG_ISPGO_Msk;
|
||||
while (FMC->ISPTRG & FMC_ISPTRG_ISPGO_Msk) ;
|
||||
return FMC->ISPDAT;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief This function reads one of the four UCID.
|
||||
* @param[in] u32Index index of the UCID to read. u32Index must be 0, 1, 2, or 3.
|
||||
* @return The UCID.
|
||||
*/
|
||||
uint32_t FMC_ReadUCID(uint32_t u32Index)
|
||||
{
|
||||
FMC->ISPCMD = FMC_ISPCMD_READ_UID;
|
||||
FMC->ISPADDR = (0x04 * u32Index) + 0x10;
|
||||
FMC->ISPTRG = FMC_ISPTRG_ISPGO_Msk;
|
||||
|
||||
while (FMC->ISPTRG & FMC_ISPTRG_ISPGO_Msk) ;
|
||||
|
||||
return FMC->ISPDAT;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief This function reads one of the three UID.
|
||||
* @param[in] u32Index Index of the UID to read. u32Index must be 0, 1, or 2.
|
||||
* @return The UID.
|
||||
*/
|
||||
uint32_t FMC_ReadUID(uint32_t u32Index)
|
||||
{
|
||||
FMC->ISPCMD = FMC_ISPCMD_READ_UID;
|
||||
FMC->ISPADDR = 0x04 * u32Index;
|
||||
FMC->ISPTRG = FMC_ISPTRG_ISPGO_Msk;
|
||||
|
||||
while (FMC->ISPTRG & FMC_ISPTRG_ISPGO_Msk) ;
|
||||
|
||||
return FMC->ISPDAT;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Get the base address of Data Flash if enabled.
|
||||
* @return The base address of Data Flash
|
||||
*/
|
||||
uint32_t FMC_ReadDataFlashBaseAddr(void)
|
||||
{
|
||||
return FMC->DFBA;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief This function will force re-map assigned flash page to CPU address 0x0.
|
||||
* @param[in] u32PageAddr Address of the page to be mapped to CPU address 0x0.
|
||||
* @return None
|
||||
*/
|
||||
void FMC_SetVectorPageAddr(uint32_t u32PageAddr)
|
||||
{
|
||||
FMC->ISPCMD = FMC_ISPCMD_VECMAP;
|
||||
FMC->ISPADDR = u32PageAddr;
|
||||
FMC->ISPTRG = FMC_ISPTRG_ISPGO_Msk;
|
||||
while (FMC->ISPTRG & FMC_ISPTRG_ISPGO_Msk) ;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Obtain the current vector page address setting.
|
||||
* @return The vector page address.
|
||||
*/
|
||||
uint32_t FMC_GetVectorPageAddr(void)
|
||||
{
|
||||
return (FMC->ISPSTS & 0x0FFFFF00ul);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief Writes a word data to specified flash address.
|
||||
* @param[in] u32Addr Destination address
|
||||
* @param[in] u32Data Word data to be written
|
||||
* @return None
|
||||
*/
|
||||
void FMC_Write(uint32_t u32Addr, uint32_t u32Data)
|
||||
{
|
||||
FMC->ISPCMD = FMC_ISPCMD_PROGRAM;
|
||||
FMC->ISPADDR = u32Addr;
|
||||
FMC->ISPDAT = u32Data;
|
||||
FMC->ISPTRG = FMC_ISPTRG_ISPGO_Msk;
|
||||
while (FMC->ISPTRG & FMC_ISPTRG_ISPGO_Msk) ;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Read the User Configuration words.
|
||||
* @param[in] u32Config The word array to store data.
|
||||
* @param[in] u32Count Maximum length of "u32Config".
|
||||
* @retval 0 Success
|
||||
* @retval -1 Failed
|
||||
*/
|
||||
int32_t FMC_ReadConfig(uint32_t *u32Config, uint32_t u32Count)
|
||||
{
|
||||
if (u32Count < 1)
|
||||
return 0;
|
||||
|
||||
u32Config[0] = FMC_Read(FMC_CONFIG_BASE);
|
||||
if (u32Count < 2)
|
||||
return 0;
|
||||
|
||||
u32Config[1] = FMC_Read(FMC_CONFIG_BASE+4);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Write User Configuration
|
||||
* @param[in] u32Config The word array to store data.
|
||||
* @param[in] u32Count Maximum length of "u32Config".
|
||||
* @retval 0 Success
|
||||
* @retval -1 Failed
|
||||
*/
|
||||
int32_t FMC_WriteConfig(uint32_t *u32Config, uint32_t u32Count)
|
||||
{
|
||||
if (u32Count < 1)
|
||||
return 0;
|
||||
|
||||
FMC_ENABLE_CFG_UPDATE();
|
||||
FMC_Erase(FMC_CONFIG_BASE);
|
||||
FMC_Write(FMC_CONFIG_BASE, u32Config[0]);
|
||||
|
||||
if (u32Count < 2)
|
||||
return 0;
|
||||
|
||||
FMC_Write(FMC_CONFIG_BASE+4, u32Config[1]);
|
||||
FMC_DISABLE_CFG_UPDATE();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Calculate and read the CRC32 checksum of a specified flash area.
|
||||
* @param[in] addr Start address of the flash area to be executed CRC32 checksum calculation.
|
||||
* @param[in] count Number of bytes to be calculated.
|
||||
* @param[out] chksum If success, it will contain the result of CRC32 checksum calculation.
|
||||
* @retval 0 Success
|
||||
* @retval -1 Invalid parameter.
|
||||
*/
|
||||
int32_t FMC_GetCRC32Sum(uint32_t addr, uint32_t count, uint32_t *chksum)
|
||||
{
|
||||
FMC->ISPCMD = FMC_ISPCMD_CAL_CRC32;
|
||||
FMC->ISPADDR = addr;
|
||||
FMC->ISPDAT = count;
|
||||
FMC->ISPTRG = FMC_ISPTRG_ISPGO_Msk;
|
||||
|
||||
while (FMC->ISPTRG & FMC_ISPTRG_ISPGO_Msk) ;
|
||||
|
||||
if (FMC->ISPCTL & FMC_ISPCTL_ISPFF_Msk) {
|
||||
FMC->ISPCTL |= FMC_ISPCTL_ISPFF_Msk;
|
||||
return -1;
|
||||
}
|
||||
|
||||
FMC->ISPCMD = FMC_ISPCMD_READ_CRC32;
|
||||
FMC->ISPADDR = addr;
|
||||
FMC->ISPTRG = FMC_ISPTRG_ISPGO_Msk;
|
||||
|
||||
while (FMC->ISPTRG & FMC_ISPTRG_ISPGO_Msk) ;
|
||||
|
||||
if (FMC->ISPCTL & FMC_ISPCTL_ISPFF_Msk) {
|
||||
FMC->ISPCTL |= FMC_ISPCTL_ISPFF_Msk;
|
||||
return -1;
|
||||
}
|
||||
|
||||
*chksum = FMC->ISPDAT;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*@}*/ /* end of group Mini58_FMC_EXPORTED_FUNCTIONS */
|
||||
|
||||
/*@}*/ /* end of group Mini58_FMC_Driver */
|
||||
|
||||
/*@}*/ /* end of group Mini58_Device_Driver */
|
||||
|
||||
/*** (C) COPYRIGHT 2015 Nuvoton Technology Corp. ***/
|
||||
|
||||
|
||||
@@ -0,0 +1,101 @@
|
||||
/**************************************************************************//**
|
||||
* @file gpio.c
|
||||
* @version V1.00
|
||||
* $Revision: 1 $
|
||||
* $Date: 15/02/02 3:19p $
|
||||
* @brief Mini58 series GPIO driver source file
|
||||
*
|
||||
* @note
|
||||
* Copyright (C) 2015 Nuvoton Technology Corp. All rights reserved.
|
||||
*****************************************************************************/
|
||||
#include "Mini58Series.h"
|
||||
|
||||
|
||||
|
||||
/** @addtogroup Mini58_Device_Driver Mini58 Device Driver
|
||||
@{
|
||||
*/
|
||||
|
||||
/** @addtogroup Mini58_GPIO_Driver GPIO Driver
|
||||
@{
|
||||
*/
|
||||
|
||||
|
||||
/** @addtogroup Mini58_GPIO_EXPORTED_FUNCTIONS GPIO Exported Functions
|
||||
@{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Set GPIO operation mode
|
||||
*
|
||||
* @param[in] gpio GPIO port. It could be \ref P0, \ref P1, \ref P2, \ref P3, \ref P4 or \ref P5.
|
||||
* @param[in] u32PinMask The single or multiple pins of specified GPIO port. \ref BIT0, \ref BIT1, \ref BIT2,.. \ref BIT7
|
||||
* @param[in] u32Mode Operation mode.
|
||||
* - \ref GPIO_MODE_INPUT,
|
||||
* - \ref GPIO_MODE_OUTPUT,
|
||||
* - \ref GPIO_MODE_OPEN_DRAIN,
|
||||
* - \ref GPIO_MODE_QUASI
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
* @details This function is used to set specified GPIO operation mode.
|
||||
*/
|
||||
void GPIO_SetMode(GPIO_T *gpio, uint32_t u32PinMask, uint32_t u32Mode)
|
||||
{
|
||||
uint32_t i;
|
||||
|
||||
for (i=0; i<GPIO_PIN_MAX; i++) {
|
||||
if (u32PinMask & (1 << i)) {
|
||||
gpio->MODE = (gpio->MODE & ~(0x3 << (i << 1))) | (u32Mode << (i << 1));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable GPIO interrupt
|
||||
*
|
||||
* @param[in] gpio GPIO port. It could be \ref P0, \ref P1, \ref P2, \ref P3, \ref P4 or \ref P5.
|
||||
* @param[in] u32Pin The pin of specified GPIO port. It could be 0 ~ 7.
|
||||
* @param[in] u32IntAttribs The interrupt attribute of specified GPIO pin. It could be \n
|
||||
* - \ref GPIO_INT_RISING,
|
||||
* - \ref GPIO_INT_FALLING,
|
||||
* - \ref GPIO_INT_BOTH_EDGE,
|
||||
* - \ref GPIO_INT_HIGH,
|
||||
* - \ref GPIO_INT_LOW.
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
* @details This function is used to enable specified GPIO pin interrupt.
|
||||
*/
|
||||
void GPIO_EnableInt(GPIO_T *gpio, uint32_t u32Pin, uint32_t u32IntAttribs)
|
||||
{
|
||||
gpio->INTTYPE |= (((u32IntAttribs >> 24) & 0xFFUL) << u32Pin);
|
||||
gpio->INTEN |= ((u32IntAttribs & 0xFFFFFFUL) << u32Pin);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Disable GPIO interrupt
|
||||
*
|
||||
* @param[in] gpio GPIO port. It could be \ref P0, \ref P1, \ref P2, \ref P3, \ref P4 or \ref P5.
|
||||
* @param[in] u32Pin The pin of specified GPIO port. It could be 0 ~ 7.
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
* @details This function is used to enable specified GPIO pin interrupt.
|
||||
*/
|
||||
void GPIO_DisableInt(GPIO_T *gpio, uint32_t u32Pin)
|
||||
{
|
||||
gpio->INTTYPE &= ~(1UL << u32Pin);
|
||||
gpio->INTEN &= ~((0x00010001UL) << u32Pin);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*@}*/ /* end of group Mini58_GPIO_EXPORTED_FUNCTIONS */
|
||||
|
||||
/*@}*/ /* end of group Mini58_GPIO_Driver */
|
||||
|
||||
/*@}*/ /* end of group Mini58_Device_Driver */
|
||||
|
||||
/*** (C) COPYRIGHT 2015 Nuvoton Technology Corp. ***/
|
||||
@@ -0,0 +1,300 @@
|
||||
/**************************************************************************//**
|
||||
* @file i2c.c
|
||||
* @version V1.00
|
||||
* $Revision: 5 $
|
||||
* $Date: 15/05/26 4:24p $
|
||||
* @brief Mini58 series I2C driver source file
|
||||
*
|
||||
* @note
|
||||
* Copyright (C) 2015 Nuvoton Technology Corp. All rights reserved.
|
||||
*****************************************************************************/
|
||||
#include "Mini58Series.h"
|
||||
|
||||
/** @addtogroup Mini58_Device_Driver Mini58 Device Driver
|
||||
@{
|
||||
*/
|
||||
|
||||
/** @addtogroup Mini58_I2C_Driver I2C Driver
|
||||
@{
|
||||
*/
|
||||
|
||||
|
||||
/** @addtogroup Mini58_I2C_EXPORTED_FUNCTIONS I2C Exported Functions
|
||||
@{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief This function make I2C module be ready and set the wanted bus clock.
|
||||
* @param[in] i2c is the base address of I2C module.
|
||||
* @param[in] u32BusClock is the target bus speed of I2C module.
|
||||
* @return Actual I2C bus clock frequency.
|
||||
*/
|
||||
uint32_t I2C_Open(I2C_T *i2c, uint32_t u32BusClock)
|
||||
{
|
||||
uint32_t u32Div;
|
||||
|
||||
u32Div = (uint32_t) (((SystemCoreClock * 10)/(u32BusClock * 4) + 5) / 10 - 1); /* Compute proper divider for I2C clock */
|
||||
i2c->CLKDIV = u32Div;
|
||||
|
||||
/* Enable I2C */
|
||||
i2c->CTL |= I2C_CTL_I2CEN_Msk;
|
||||
|
||||
return ( SystemCoreClock / ((u32Div+1)<<2) );
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function closes the I2C module.
|
||||
* @param[in] i2c is the base address of I2C module.
|
||||
* @return none
|
||||
*/
|
||||
void I2C_Close(I2C_T *i2c)
|
||||
{
|
||||
/* Reset SPI */
|
||||
if(i2c == I2C0) {
|
||||
SYS->IPRST1 |= SYS_IPRST1_I2C0RST_Msk;
|
||||
SYS->IPRST1 &= ~SYS_IPRST1_I2C0RST_Msk;
|
||||
} else {
|
||||
SYS->IPRST1 |= SYS_IPRST1_I2C1RST_Msk;
|
||||
SYS->IPRST1 &= ~SYS_IPRST1_I2C1RST_Msk;
|
||||
}
|
||||
|
||||
/* Disable I2C */
|
||||
i2c->CTL &= ~I2C_CTL_I2CEN_Msk;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function clears the timeout flag.
|
||||
* @param[in] i2c is the base address of I2C module.
|
||||
* @return none
|
||||
*/
|
||||
void I2C_ClearTimeoutFlag(I2C_T *i2c)
|
||||
{
|
||||
i2c->TOCTL |= I2C_TOCTL_TOIF_Msk;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function sets the control bit of the I2C module.
|
||||
* @param[in] i2c is the base address of I2C module.
|
||||
* @param[in] u8Start sets START bit to I2C module.
|
||||
* @param[in] u8Stop sets STOP bit to I2C module.
|
||||
* @param[in] u8Si sets SI bit to I2C module.
|
||||
* @param[in] u8Ack sets ACK bit to I2C module.
|
||||
* @return none
|
||||
*/
|
||||
void I2C_Trigger(I2C_T *i2c, uint8_t u8Start, uint8_t u8Stop, uint8_t u8Si, uint8_t u8Ack)
|
||||
{
|
||||
uint32_t u32Reg = 0;
|
||||
|
||||
if (u8Start)
|
||||
u32Reg |= I2C_STA;
|
||||
if (u8Stop)
|
||||
u32Reg |= I2C_STO;
|
||||
if (u8Si)
|
||||
u32Reg |= I2C_SI;
|
||||
if (u8Ack)
|
||||
u32Reg |= I2C_AA;
|
||||
|
||||
i2c->CTL = (i2c->CTL & ~0x3C) | u32Reg;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function disables the interrupt (EI bit) of I2C module.
|
||||
* @param[in] i2c is the base address of I2C module.
|
||||
* @return none
|
||||
*/
|
||||
void I2C_DisableInt(I2C_T *i2c)
|
||||
{
|
||||
i2c->CTL &= ~I2C_CTL_INTEN_Msk;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function enables the interrupt (EI bit) of I2C module.
|
||||
* @param[in] i2c is the base address of I2C module.
|
||||
* @return none
|
||||
*/
|
||||
void I2C_EnableInt(I2C_T *i2c)
|
||||
{
|
||||
i2c->CTL |= I2C_CTL_INTEN_Msk;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function returns the real bus clock of I2C module.
|
||||
* @param[in] i2c is the base address of I2C module.
|
||||
* @return Actual I2C bus clock frequency.
|
||||
*/
|
||||
uint32_t I2C_GetBusClockFreq(I2C_T *i2c)
|
||||
{
|
||||
uint32_t u32Divider = i2c->CLKDIV;
|
||||
|
||||
return ( SystemCoreClock / ((u32Divider+1)<<2) );
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function enables the interrupt (EI bit) of I2C module.
|
||||
* @param[in] i2c is the base address of I2C module.
|
||||
* @param[in] u32BusClock is the target bus speed of I2C module.
|
||||
* @return Actual I2C bus clock frequency.
|
||||
*/
|
||||
uint32_t I2C_SetBusClockFreq(I2C_T *i2c, uint32_t u32BusClock)
|
||||
{
|
||||
uint32_t u32Div;
|
||||
|
||||
u32Div = (uint32_t) (((SystemCoreClock * 10)/(u32BusClock * 4) + 5) / 10 - 1); /* Compute proper divider for I2C clock */
|
||||
i2c->CLKDIV = u32Div;
|
||||
|
||||
return ( SystemCoreClock / ((u32Div+1)<<2) );
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function gets the interrupt flag (SI bit) of I2C module.
|
||||
* @param[in] i2c is the base address of I2C module.
|
||||
* @return Interrupt flag.
|
||||
* @retval 0 Flag is not set.
|
||||
* @retval 1 Flag is set.
|
||||
*/
|
||||
uint32_t I2C_GetIntFlag(I2C_T *i2c)
|
||||
{
|
||||
return ( (i2c->CTL & I2C_CTL_SI_Msk) == I2C_CTL_SI_Msk ? 1:0 );
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function returns the status of I2C module.
|
||||
* @param[in] i2c is the base address of I2C module.
|
||||
* @return Status.
|
||||
*/
|
||||
uint32_t I2C_GetStatus(I2C_T *i2c)
|
||||
{
|
||||
return ( i2c->STATUS );
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function returns the data stored in data register of I2C module.
|
||||
* @param[in] i2c is the base address of I2C module.
|
||||
* @return Data.
|
||||
*/
|
||||
uint32_t I2C_GetData(I2C_T *i2c)
|
||||
{
|
||||
return ( i2c->DAT );
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function writes the data to data register of I2C module.
|
||||
* @param[in] i2c is the base address of I2C module.
|
||||
* @param[in] u8Data is the data which will be write to data register of I2C module.
|
||||
* @return none
|
||||
*/
|
||||
void I2C_SetData(I2C_T *i2c, uint8_t u8Data)
|
||||
{
|
||||
i2c->DAT = u8Data;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Configure slave address and enable GC mode.
|
||||
* @param[in] i2c is the base address of I2C module.
|
||||
* @param[in] u8SlaveNo is the set number of salve address.
|
||||
* @param[in] u8SlaveAddr is the slave address.
|
||||
* @param[in] u8GCMode enable GC mode.
|
||||
* @return none
|
||||
*/
|
||||
void I2C_SetSlaveAddr(I2C_T *i2c, uint8_t u8SlaveNo, uint8_t u8SlaveAddr, uint8_t u8GCMode)
|
||||
{
|
||||
switch (u8SlaveNo) {
|
||||
case 0:
|
||||
i2c->ADDR0 = (u8SlaveAddr << 1) | u8GCMode;
|
||||
break;
|
||||
case 1:
|
||||
i2c->ADDR1 = (u8SlaveAddr << 1) | u8GCMode;
|
||||
break;
|
||||
case 2:
|
||||
i2c->ADDR2 = (u8SlaveAddr << 1) | u8GCMode;
|
||||
break;
|
||||
case 3:
|
||||
i2c->ADDR3 = (u8SlaveAddr << 1) | u8GCMode;
|
||||
break;
|
||||
default:
|
||||
i2c->ADDR0 = (u8SlaveAddr << 1) | u8GCMode;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Configure the mask of slave address. The corresponding address bit is "Don't Care".
|
||||
* @param[in] i2c is the base address of I2C module.
|
||||
* @param[in] u8SlaveNo is the set number of salve address.
|
||||
* @param[in] u8SlaveAddrMask is the slave address mask.
|
||||
* @return none
|
||||
*/
|
||||
void I2C_SetSlaveAddrMask(I2C_T *i2c, uint8_t u8SlaveNo, uint8_t u8SlaveAddrMask)
|
||||
{
|
||||
switch (u8SlaveNo) {
|
||||
case 0:
|
||||
i2c->ADDRMSK0 = u8SlaveAddrMask << 1;
|
||||
break;
|
||||
case 1:
|
||||
i2c->ADDRMSK1 = u8SlaveAddrMask << 1;
|
||||
break;
|
||||
case 2:
|
||||
i2c->ADDRMSK2 = u8SlaveAddrMask << 1;
|
||||
break;
|
||||
case 3:
|
||||
i2c->ADDRMSK3 = u8SlaveAddrMask << 1;
|
||||
break;
|
||||
default:
|
||||
i2c->ADDRMSK0 = u8SlaveAddrMask << 1;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function enables timeout function and configures DIV4 function to support long timeout.
|
||||
* @param[in] i2c is the base address of I2C module.
|
||||
* @param[in] u8LongTimeout Enable timeout counter input clock is divide by 4.
|
||||
* @return none.
|
||||
*/
|
||||
void I2C_EnableTimeout(I2C_T *i2c, uint8_t u8LongTimeout)
|
||||
{
|
||||
if(u8LongTimeout)
|
||||
i2c->TOCTL |= I2C_TOCTL_TOCURIEN_Msk;
|
||||
else
|
||||
i2c->TOCTL &= ~I2C_TOCTL_TOCURIEN_Msk;
|
||||
|
||||
i2c->TOCTL |= I2C_TOCTL_TOCEN_Msk;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function disables timeout function.
|
||||
* @param[in] i2c is the base address of I2C module.
|
||||
* @return none.
|
||||
*/
|
||||
void I2C_DisableTimeout(I2C_T *i2c)
|
||||
{
|
||||
i2c->TOCTL &= ~I2C_TOCTL_TOCEN_Msk;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function enables the wakeup function of I2C module.
|
||||
* @param[in] i2c is the base address of I2C module.
|
||||
* @return none.
|
||||
*/
|
||||
void I2C_EnableWakeup(I2C_T *i2c)
|
||||
{
|
||||
if(i2c == I2C0) //only support for port0
|
||||
i2c->CTL1 |= I2C_CTL1_WKEN_Msk;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function disables the wakeup function of I2C module.
|
||||
* @param[in] i2c is the base address of I2C module.
|
||||
* @return none.
|
||||
*/
|
||||
void I2C_DisableWakeup(I2C_T *i2c)
|
||||
{
|
||||
if(i2c == I2C0) //only support for port0
|
||||
i2c->CTL1 &= ~I2C_CTL1_WKEN_Msk;
|
||||
}
|
||||
|
||||
/*@}*/ /* end of group Mini58_I2C_EXPORTED_FUNCTIONS */
|
||||
|
||||
/*@}*/ /* end of group Mini58_I2C_Driver */
|
||||
|
||||
/*@}*/ /* end of group Mini58_Device_Driver */
|
||||
|
||||
/*** (C) COPYRIGHT 2015 Nuvoton Technology Corp. ***/
|
||||
@@ -0,0 +1,573 @@
|
||||
/**************************************************************************//**
|
||||
* @file PWM.c
|
||||
* @version V1.00
|
||||
* $Revision: 4 $
|
||||
* $Date: 15/06/05 1:43p $
|
||||
* @brief Mini58 series PWM driver source file
|
||||
*
|
||||
* @note
|
||||
* Copyright (C) 2015 Nuvoton Technology Corp. All rights reserved.
|
||||
*****************************************************************************/
|
||||
#include "Mini58Series.h"
|
||||
|
||||
/** @addtogroup Mini58_Device_Driver Mini58 Device Driver
|
||||
@{
|
||||
*/
|
||||
|
||||
/** @addtogroup Mini58_PWM_Driver PWM Driver
|
||||
@{
|
||||
*/
|
||||
|
||||
|
||||
/** @addtogroup Mini58_PWM_EXPORTED_FUNCTIONS PWM Exported Functions
|
||||
@{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief This function config PWM generator and get the nearest frequency in edge aligned auto-reload mode
|
||||
* @param[in] pwm The base address of PWM module
|
||||
* @param[in] u32ChannelNum PWM channel number. Valid values are between 0~5
|
||||
* @param[in] u32Frequency Target generator frequency
|
||||
* @param[in] u32DutyCycle Target generator duty cycle percentage. Valid range are between 0 ~ 100. 10 means 10%, 20 means 20%...
|
||||
* @return Nearest frequency clock in nano second
|
||||
* @note Since every two channels, (0 & 1), (2 & 3), (4 & 5), shares a prescaler. Call this API to configure PWM frequency may affect
|
||||
* existing frequency of other channel.
|
||||
*/
|
||||
uint32_t PWM_ConfigOutputChannel (PWM_T *pwm,
|
||||
uint32_t u32ChannelNum,
|
||||
uint32_t u32Frequency,
|
||||
uint32_t u32DutyCycle)
|
||||
{
|
||||
uint32_t i = SystemCoreClock / u32Frequency;
|
||||
uint8_t u8Divider = 1, u8Prescale = 0xFF;
|
||||
uint16_t u16CNR = 0xFFFF;
|
||||
|
||||
for(; u8Divider < 17; u8Divider <<= 1) { // clk divider could only be 1, 2, 4, 8, 16
|
||||
i = (SystemCoreClock / u32Frequency) / u8Divider;
|
||||
// If target value is larger than CNR * prescale, need to use a larger divider
|
||||
if(i > (0x10000 * 0x100))
|
||||
continue;
|
||||
|
||||
// CNR = 0xFFFF + 1, get a prescaler that CNR value is below 0xFFFF
|
||||
u8Prescale = (i + 0xFFFF)/ 0x10000;
|
||||
|
||||
// u8Prescale must at least be 2, otherwise the output stop
|
||||
if(u8Prescale < 3)
|
||||
u8Prescale = 2;
|
||||
|
||||
i /= u8Prescale;
|
||||
|
||||
if(i <= 0x10000) {
|
||||
if(i == 1)
|
||||
u16CNR = 1; // Too fast, and PWM cannot generate expected frequency...
|
||||
else
|
||||
u16CNR = i;
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
// Store return value here 'cos we're gonna change u8Divider & u8Prescale & u16CNR to the real value to fill into register
|
||||
i = SystemCoreClock / (u8Prescale * u8Divider * u16CNR);
|
||||
|
||||
u8Prescale -= 1;
|
||||
u16CNR -= 1;
|
||||
// convert to real register value
|
||||
if(u8Divider == 1)
|
||||
u8Divider = 4;
|
||||
else if (u8Divider == 2)
|
||||
u8Divider = 0;
|
||||
else if (u8Divider == 4)
|
||||
u8Divider = 1;
|
||||
else if (u8Divider == 8)
|
||||
u8Divider = 2;
|
||||
else // 16
|
||||
u8Divider = 3;
|
||||
|
||||
// every two channels share a prescaler
|
||||
PWM->CLKPSC = (PWM->CLKPSC & ~(PWM_CLKPSC_CLKPSC01_Msk << ((u32ChannelNum >> 1) * 8))) | (u8Prescale << ((u32ChannelNum >> 1) * 8));
|
||||
PWM->CLKDIV = (PWM->CLKDIV & ~(PWM_CLKDIV_CLKDIV0_Msk << (4 * u32ChannelNum))) | (u8Divider << (4 * u32ChannelNum));
|
||||
PWM->CTL = (PWM->CTL & ~PWM_CTL_CNTTYPE_Msk) | (PWM_CTL_CNTMODE0_Msk << ((4 * u32ChannelNum)));
|
||||
|
||||
if(u32DutyCycle == 0)
|
||||
*((__IO uint32_t *)((((uint32_t) & ((pwm)->CMPDAT0)) + u32ChannelNum * 4))) = 0;
|
||||
else
|
||||
*((__IO uint32_t *)((((uint32_t) & ((pwm)->CMPDAT0)) + u32ChannelNum * 4))) = u32DutyCycle * (u16CNR + 1) / 100 - 1;
|
||||
|
||||
*((__IO uint32_t *)((((uint32_t) & ((pwm)->PERIOD0)) + (u32ChannelNum) * 4))) = u16CNR;
|
||||
|
||||
return(i);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief This function start PWM module
|
||||
* @param[in] pwm The base address of PWM module
|
||||
* @param[in] u32ChannelMask Combination of enabled channels. Each bit corresponds to a channel.
|
||||
* Bit 0 is channel 0, bit 1 is channel 1...
|
||||
* @return None
|
||||
*/
|
||||
void PWM_Start (PWM_T *pwm, uint32_t u32ChannelMask)
|
||||
{
|
||||
uint32_t u32Mask = 0, i;
|
||||
for(i = 0; i < PWM_CHANNEL_NUM; i ++) {
|
||||
if(u32ChannelMask & (1 << i)) {
|
||||
u32Mask |= (PWM_CTL_CNTEN0_Msk << (i * 4));
|
||||
}
|
||||
}
|
||||
|
||||
PWM->CTL |= u32Mask;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function stop PWM module
|
||||
* @param[in] pwm The base address of PWM module
|
||||
* @param[in] u32ChannelMask Combination of enabled channels. Each bit corresponds to a channel.
|
||||
* Bit 0 is channel 0, bit 1 is channel 1...
|
||||
* @return None
|
||||
*/
|
||||
void PWM_Stop (PWM_T *pwm, uint32_t u32ChannelMask)
|
||||
{
|
||||
uint32_t i;
|
||||
for(i = 0; i < PWM_CHANNEL_NUM; i ++) {
|
||||
if(u32ChannelMask & (1 << i)) {
|
||||
*((__IO uint32_t *)((((uint32_t) & ((pwm)->PERIOD0)) + (i) * 4))) = 0;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function stop PWM generation immediately by clear channel enable bit
|
||||
* @param[in] pwm The base address of PWM module
|
||||
* @param[in] u32ChannelMask Combination of enabled channels. Each bit corresponds to a channel.
|
||||
* Bit 0 is channel 0, bit 1 is channel 1...
|
||||
* @return None
|
||||
*/
|
||||
void PWM_ForceStop (PWM_T *pwm, uint32_t u32ChannelMask)
|
||||
{
|
||||
uint32_t u32Mask = 0, i;
|
||||
for(i = 0; i < PWM_CHANNEL_NUM; i ++) {
|
||||
if(u32ChannelMask & (1 << i)) {
|
||||
u32Mask |= (PWM_CTL_CNTEN0_Msk << (i * 4));
|
||||
}
|
||||
}
|
||||
|
||||
PWM->CTL &= ~u32Mask;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function enable selected channel to trigger ADC
|
||||
* @param[in] pwm The base address of PWM module
|
||||
* @param[in] u32ChannelNum PWM channel number. Valid values are between 0~5
|
||||
* @param[in] u32Condition The condition to trigger ADC. Combination of following conditions:
|
||||
* - \ref PWM_TRIGGER_ADC_CNTR_IS_0
|
||||
* - \ref PWM_TRIGGER_ADC_CNTR_IS_CMR_D
|
||||
* - \ref PWM_TRIGGER_ADC_CNTR_IS_CNR
|
||||
* - \ref PWM_TRIGGER_ADC_CNTR_IS_CMR_U
|
||||
* @return None
|
||||
*/
|
||||
void PWM_EnableADCTrigger (PWM_T *pwm, uint32_t u32ChannelNum, uint32_t u32Condition)
|
||||
{
|
||||
if(u32ChannelNum < 4) {
|
||||
PWM->ADCTCTL0 = (PWM->ADCTCTL0 & ~((PWM_TRIGGER_ADC_CNTR_IS_0 |
|
||||
PWM_TRIGGER_ADC_CNTR_IS_CMR_D |
|
||||
PWM_TRIGGER_ADC_CNTR_IS_CNR |
|
||||
PWM_TRIGGER_ADC_CNTR_IS_CMR_U ) << (8 * u32ChannelNum))) | (u32Condition << (8 * u32ChannelNum));
|
||||
} else {
|
||||
PWM->ADCTCTL1 = (PWM->ADCTCTL1 & ~((PWM_TRIGGER_ADC_CNTR_IS_0 |
|
||||
PWM_TRIGGER_ADC_CNTR_IS_CMR_D |
|
||||
PWM_TRIGGER_ADC_CNTR_IS_CNR |
|
||||
PWM_TRIGGER_ADC_CNTR_IS_CMR_U ) << (8 * (u32ChannelNum - 4)))) | (u32Condition << (8 * (u32ChannelNum - 4)));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function disable selected channel to trigger ADC
|
||||
* @param[in] pwm The base address of PWM module
|
||||
* @param[in] u32ChannelNum PWM channel number. Valid values are between 0~5
|
||||
* @return None
|
||||
*/
|
||||
void PWM_DisableADCTrigger (PWM_T *pwm, uint32_t u32ChannelNum)
|
||||
{
|
||||
if(u32ChannelNum < 4) {
|
||||
PWM->ADCTCTL0 = (PWM->ADCTCTL0 & ~((PWM_TRIGGER_ADC_CNTR_IS_0 |
|
||||
PWM_TRIGGER_ADC_CNTR_IS_CMR_D |
|
||||
PWM_TRIGGER_ADC_CNTR_IS_CNR |
|
||||
PWM_TRIGGER_ADC_CNTR_IS_CMR_U ) << (8 * u32ChannelNum)));
|
||||
} else {
|
||||
PWM->ADCTCTL1 = (PWM->ADCTCTL1 & ~((PWM_TRIGGER_ADC_CNTR_IS_0 |
|
||||
PWM_TRIGGER_ADC_CNTR_IS_CMR_D |
|
||||
PWM_TRIGGER_ADC_CNTR_IS_CNR |
|
||||
PWM_TRIGGER_ADC_CNTR_IS_CMR_U ) << (8 * (u32ChannelNum - 4))));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function clear selected channel trigger ADC flag
|
||||
* @param[in] pwm The base address of PWM module
|
||||
* @param[in] u32ChannelNum PWM channel number. Valid values are between 0~5
|
||||
* @param[in] u32Condition PWM triggered ADC flag to be cleared.
|
||||
* @return None
|
||||
*/
|
||||
void PWM_ClearADCTriggerFlag (PWM_T *pwm, uint32_t u32ChannelNum, uint32_t u32Condition)
|
||||
{
|
||||
if(u32ChannelNum < 4) {
|
||||
PWM->ADCTSTS0 |= (u32Condition << (8 * u32ChannelNum));
|
||||
} else {
|
||||
PWM->ADCTSTS1 |= (u32Condition << (8 * (u32ChannelNum - 4)));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function get selected channel trigger ADC flag
|
||||
* @param[in] pwm The base address of PWM module
|
||||
* @param[in] u32ChannelNum PWM channel number. Valid values are between 0~5
|
||||
* @param[in] u32Condition PWM triggered ADC flag to be selected.
|
||||
* @return Get status of the selected channel trigger ADC
|
||||
*/
|
||||
uint32_t PWM_GetADCTriggerFlag (PWM_T *pwm, uint32_t u32ChannelNum, uint32_t u32Condition)
|
||||
{
|
||||
if(u32ChannelNum < 4) {
|
||||
return(PWM->ADCTSTS0 & (u32Condition << (8 * u32ChannelNum)) ? 1 : 0);
|
||||
} else {
|
||||
return(PWM->ADCTSTS1 & (u32Condition << (8 * (u32ChannelNum - 4))) ? 1 : 0);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function enable fault brake of selected channels
|
||||
* @param[in] pwm The base address of PWM module
|
||||
* @param[in] u32ChannelMask This parameter is not used
|
||||
* @param[in] u32LevelMask Output high or low while fault brake occurs, each bit represent the level of a channel
|
||||
* while fault brake occur. Bit 0 represents channel 0, bit 1 represents channel 1...
|
||||
* , bit 6 represent D6, and bit 7 represents D7
|
||||
* @param[in] u32BrakeSource Fault brake source, could be one of following source
|
||||
* - \ref PWM_FB0_EINT0
|
||||
* - \ref PWM_FB0_ACMP1
|
||||
* - \ref PWM_FB1_EINT1
|
||||
* - \ref PWM_FB1_ACMP0
|
||||
* @return None
|
||||
*/
|
||||
void PWM_EnableFaultBrake (PWM_T *pwm,
|
||||
uint32_t u32ChannelMask,
|
||||
uint32_t u32LevelMask,
|
||||
uint32_t u32BrakeSource)
|
||||
{
|
||||
PWM->BRKCTL = (u32LevelMask << PWM_BRKCTL_BKOD0_Pos) | u32BrakeSource;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function clear fault brake flag
|
||||
* @param[in] pwm The base address of PWM module
|
||||
* @param[in] u32BrakeSource This parameter is not used
|
||||
* @return None
|
||||
* @note After fault brake occurred, application must clear fault brake source before re-enable PWM output
|
||||
*/
|
||||
void PWM_ClearFaultBrakeFlag (PWM_T *pwm, uint32_t u32BrakeSource)
|
||||
{
|
||||
PWM->BRKCTL = PWM_BRKCTL_BRKSTS_Msk;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function enables PWM output generation of selected channels
|
||||
* @param[in] pwm The base address of PWM module
|
||||
* @param[in] u32ChannelMask Combination of enabled channels. Each bit corresponds to a channel.
|
||||
* Set bit 0 to 1 enables channel 0 output, set bit 1 to 1 enables channel 1 output...
|
||||
* @return None
|
||||
*/
|
||||
void PWM_EnableOutput (PWM_T *pwm, uint32_t u32ChannelMask)
|
||||
{
|
||||
PWM->POEN |= u32ChannelMask;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function disables PWM output generation of selected channels
|
||||
* @param[in] pwm The base address of PWM module
|
||||
* @param[in] u32ChannelMask Combination of enabled channels. Each bit corresponds to a channel
|
||||
* Set bit 0 to 1 disables channel 0 output, set bit 1 to 1 disables channel 1 output...
|
||||
* @return None
|
||||
*/
|
||||
void PWM_DisableOutput (PWM_T *pwm, uint32_t u32ChannelMask)
|
||||
{
|
||||
PWM->POEN &= ~u32ChannelMask;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function enable Dead zone of selected channel
|
||||
* @param[in] pwm The base address of PWM module
|
||||
* @param[in] u32ChannelNum PWM channel number. Valid values are between 0~5
|
||||
* @param[in] u32Duration Dead Zone length in PWM clock count, valid values are between 0~0xFF, but 0 means there is no
|
||||
* dead zone.
|
||||
* @return None
|
||||
*/
|
||||
void PWM_EnableDeadZone (PWM_T *pwm, uint32_t u32ChannelNum, uint32_t u32Duration)
|
||||
{
|
||||
// every two channels shares the same setting
|
||||
u32ChannelNum >>= 1;
|
||||
// set duration
|
||||
PWM->DTCTL = (PWM->DTCTL & ~(PWM_DTCTL_DTI01_Msk << (8 * u32ChannelNum))) | (u32Duration << (8 * u32ChannelNum));
|
||||
// enable dead zone
|
||||
PWM->CTL |= (PWM_CTL_DTCNT01_Msk << u32ChannelNum);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function disable Dead zone of selected channel
|
||||
* @param[in] pwm The base address of PWM module
|
||||
* @param[in] u32ChannelNum PWM channel number. Valid values are between 0~5
|
||||
* @return None
|
||||
*/
|
||||
void PWM_DisableDeadZone (PWM_T *pwm, uint32_t u32ChannelNum)
|
||||
{
|
||||
// every two channels shares the same setting
|
||||
u32ChannelNum >>= 1;
|
||||
// enable dead zone
|
||||
PWM->CTL &= ~(PWM_CTL_DTCNT01_Msk << u32ChannelNum);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function enable duty interrupt of selected channel
|
||||
* @param[in] pwm The base address of PWM module
|
||||
* @param[in] u32ChannelNum PWM channel number. Valid values are between 0~5
|
||||
* @param[in] u32IntDutyType This parameter is not used
|
||||
* @return None
|
||||
*/
|
||||
void PWM_EnableDutyInt (PWM_T *pwm, uint32_t u32ChannelNum, uint32_t u32IntDutyType)
|
||||
{
|
||||
(pwm)->INTEN |= ((1 << PWM_INTEN_CMPDIEN0_Pos) << u32ChannelNum);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function disable duty interrupt of selected channel
|
||||
* @param[in] pwm The base address of PWM module
|
||||
* @param[in] u32ChannelNum PWM channel number. Valid values are between 0~5
|
||||
* @return None
|
||||
*/
|
||||
void PWM_DisableDutyInt (PWM_T *pwm, uint32_t u32ChannelNum)
|
||||
{
|
||||
(pwm)->INTEN &= ~((1 << PWM_INTEN_CMPDIEN0_Pos) << u32ChannelNum);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function clears duty interrupt flag of selected channel
|
||||
* @param[in] pwm The base address of PWM module
|
||||
* @param[in] u32ChannelNum PWM channel number. Valid values are between 0~5
|
||||
* @return None
|
||||
*/
|
||||
void PWM_ClearDutyIntFlag (PWM_T *pwm, uint32_t u32ChannelNum)
|
||||
{
|
||||
PWM->INTSTS = (PWM_INTSTS_CMPDIF0_Msk << u32ChannelNum);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function get duty interrupt flag of selected channel
|
||||
* @param[in] pwm The base address of PWM module
|
||||
* @param[in] u32ChannelNum PWM channel number. Valid values are between 0~5
|
||||
* @return Duty interrupt flag of specified channel
|
||||
* @retval 0 Duty interrupt did not occurred
|
||||
* @retval 1 Duty interrupt occurred
|
||||
*/
|
||||
uint32_t PWM_GetDutyIntFlag (PWM_T *pwm, uint32_t u32ChannelNum)
|
||||
{
|
||||
return(PWM->INTSTS & (PWM_INTSTS_CMPDIF0_Msk << u32ChannelNum) ? 1 : 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function enable Period interrupt of selected channel
|
||||
* @param[in] pwm The base address of PWM module
|
||||
* @param[in] u32ChannelNum PWM channel number. Valid values are between 0~5
|
||||
* @return None
|
||||
*/
|
||||
void PWM_EnablePeriodInt (PWM_T *pwm, uint32_t u32ChannelNum)
|
||||
{
|
||||
(pwm)->INTEN |= ((1 << PWM_INTEN_ZIEN0_Pos) << u32ChannelNum);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function disable Period interrupt of selected channel
|
||||
* @param[in] pwm The base address of PWM module
|
||||
* @param[in] u32ChannelNum PWM channel number. Valid values are between 0~5
|
||||
* @return None
|
||||
*/
|
||||
void PWM_DisablePeriodInt (PWM_T *pwm, uint32_t u32ChannelNum)
|
||||
{
|
||||
(pwm)->INTEN &= ~((1 << PWM_INTEN_ZIEN0_Pos) << u32ChannelNum);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function clears Period interrupt flag of selected channel
|
||||
* @param[in] pwm The base address of PWM module
|
||||
* @param[in] u32ChannelNum PWM channel number. Valid values are between 0~5
|
||||
* @return None
|
||||
*/
|
||||
void PWM_ClearPeriodIntFlag (PWM_T *pwm, uint32_t u32ChannelNum)
|
||||
{
|
||||
PWM->INTSTS = (PWM_INTSTS_ZIF0_Msk << u32ChannelNum);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function get Period interrupt flag of selected channel
|
||||
* @param[in] pwm The base address of PWM module
|
||||
* @param[in] u32ChannelNum PWM channel number. Valid values are between 0~5
|
||||
* @return Period interrupt flag of specified channel
|
||||
* @retval 0 Period interrupt did not occurred
|
||||
* @retval 1 Period interrupt occurred
|
||||
*/
|
||||
uint32_t PWM_GetPeriodIntFlag (PWM_T *pwm, uint32_t u32ChannelNum)
|
||||
{
|
||||
return(PWM->INTSTS & (PWM_INTSTS_ZIF0_Msk << u32ChannelNum) ? 1 : 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function enable Rise interrupt of selected channel
|
||||
* @param[in] pwm The base address of PWM module
|
||||
* @param[in] u32ChannelNum PWM channel number. Valid values are between 0~5
|
||||
* @return None
|
||||
*/
|
||||
void PWM_EnableRiseInt (PWM_T *pwm, uint32_t u32ChannelNum)
|
||||
{
|
||||
(pwm)->INTEN |= ((1 << PWM_INTEN_CMPUIEN0_Pos) << u32ChannelNum);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function disable Rise interrupt of selected channel
|
||||
* @param[in] pwm The base address of PWM module
|
||||
* @param[in] u32ChannelNum PWM channel number. Valid values are between 0~5
|
||||
* @return None
|
||||
*/
|
||||
void PWM_DisableRiseInt (PWM_T *pwm, uint32_t u32ChannelNum)
|
||||
{
|
||||
(pwm)->INTEN &= ~((1 << PWM_INTEN_CMPUIEN0_Pos) << u32ChannelNum);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function clears Rise interrupt flag of selected channel
|
||||
* @param[in] pwm The base address of PWM module
|
||||
* @param[in] u32ChannelNum PWM channel number. Valid values are between 0~5
|
||||
* @return None
|
||||
*/
|
||||
void PWM_ClearRiseIntFlag (PWM_T *pwm, uint32_t u32ChannelNum)
|
||||
{
|
||||
PWM->INTSTS = (PWM_INTSTS_CMPUIF0_Msk << u32ChannelNum);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function get Rise interrupt flag of selected channel
|
||||
* @param[in] pwm The base address of PWM module
|
||||
* @param[in] u32ChannelNum PWM channel number. Valid values are between 0~5
|
||||
* @return Rise interrupt flag of specified channel
|
||||
* @retval 0 Rise interrupt did not occurred
|
||||
* @retval 1 Rise interrupt occurred
|
||||
*/
|
||||
uint32_t PWM_GetRiseIntFlag (PWM_T *pwm, uint32_t u32ChannelNum)
|
||||
{
|
||||
return(PWM->INTSTS & (PWM_INTSTS_CMPUIF0_Msk << u32ChannelNum) ? 1 : 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function enable fault brake interrupt
|
||||
* @param[in] pwm The base address of PWM module
|
||||
* @param[in] u32BrakeSource This parameter is not used
|
||||
* @return None
|
||||
*/
|
||||
void PWM_EnableFaultBrakeInt (PWM_T *pwm, uint32_t u32BrakeSource)
|
||||
{
|
||||
PWM->INTEN |= PWM_INTEN_BRKIEN_Msk;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function disable fault brake interrupt
|
||||
* @param[in] pwm The base address of PWM module
|
||||
* @param[in] u32BrakeSource This parameter is not used
|
||||
* @return None
|
||||
*/
|
||||
void PWM_DisableFaultBrakeInt (PWM_T *pwm, uint32_t u32BrakeSource)
|
||||
{
|
||||
PWM->INTEN &= ~PWM_INTEN_BRKIEN_Msk;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function clear fault brake interrupt of selected source
|
||||
* @param[in] pwm The base address of PWM module
|
||||
* @param[in] u32BrakeSource Fault brake source, could be either
|
||||
* - \ref PWM_INTSTS_BRKIF0_Msk, or
|
||||
* - \ref PWM_INTSTS_BRKIF1_Msk
|
||||
* @return None
|
||||
*/
|
||||
void PWM_ClearFaultBrakeIntFlag (PWM_T *pwm, uint32_t u32BrakeSource)
|
||||
{
|
||||
PWM->INTSTS = u32BrakeSource;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function get fault brake interrupt of selected source
|
||||
* @param[in] pwm The base address of PWM module
|
||||
* @param[in] u32BrakeSource Fault brake source, could be either
|
||||
* - \ref PWM_INTSTS_BRKIF0_Msk, or
|
||||
* - \ref PWM_INTSTS_BRKIF1_Msk
|
||||
* @return Fault brake interrupt flag of specified source
|
||||
* @retval 0 Fault brake interrupt did not occurred
|
||||
* @retval 1 Fault brake interrupt occurred
|
||||
*/
|
||||
uint32_t PWM_GetFaultBrakeIntFlag (PWM_T *pwm, uint32_t u32BrakeSource)
|
||||
{
|
||||
return (PWM->INTSTS & u32BrakeSource ? 1 : 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function enable Central interrupt of selected channel
|
||||
* @param[in] pwm The base address of PWM module
|
||||
* @param[in] u32ChannelNum PWM channel number. Valid values are between 0~5
|
||||
* @param[in] u32IntPeriodType Period interrupt type, could be either
|
||||
* - \ref PWM_PERIOD_INT_UNDERFLOW
|
||||
* - \ref PWM_PERIOD_INT_MATCH_CNR
|
||||
* @return None
|
||||
* @note All channels share the same Central interrupt type setting.
|
||||
*/
|
||||
void PWM_EnableCenterInt (PWM_T *pwm, uint32_t u32ChannelNum, uint32_t u32IntPeriodType)
|
||||
{
|
||||
PWM->INTEN = (PWM->INTEN & ~PWM_INTEN_PINTTYPE_Msk & ~(PWM_INTEN_PIEN0_Msk << u32ChannelNum)) | (PWM_INTEN_PIEN0_Msk << u32ChannelNum) | u32IntPeriodType;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function disable Central interrupt of selected channel
|
||||
* @param[in] pwm The base address of PWM module
|
||||
* @param[in] u32ChannelNum PWM channel number. Valid values are between 0~5
|
||||
* @return None
|
||||
*/
|
||||
void PWM_DisableCenterInt (PWM_T *pwm, uint32_t u32ChannelNum)
|
||||
{
|
||||
PWM->INTEN &= ~(PWM_INTEN_PIEN0_Msk << u32ChannelNum);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function clear Central interrupt of selected channel
|
||||
* @param[in] pwm The base address of PWM module
|
||||
* @param[in] u32ChannelNum PWM channel number. Valid values are between 0~5
|
||||
* @return None
|
||||
*/
|
||||
void PWM_ClearCenterIntFlag (PWM_T *pwm, uint32_t u32ChannelNum)
|
||||
{
|
||||
PWM->INTSTS = (PWM_INTSTS_PIF0_Msk << u32ChannelNum);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function get Central interrupt of selected channel
|
||||
* @param[in] pwm The base address of PWM module
|
||||
* @param[in] u32ChannelNum PWM channel number. Valid values are between 0~5
|
||||
* @return Central interrupt flag of specified channel
|
||||
* @retval 0 Central interrupt did not occurred
|
||||
* @retval 1 Central interrupt occurred
|
||||
*/
|
||||
uint32_t PWM_GetCenterIntFlag (PWM_T *pwm, uint32_t u32ChannelNum)
|
||||
{
|
||||
return(PWM->INTSTS & (PWM_INTSTS_PIF0_Msk << u32ChannelNum) ? 1 : 0);
|
||||
}
|
||||
|
||||
|
||||
/*@}*/ /* end of group Mini58_PWM_EXPORTED_FUNCTIONS */
|
||||
|
||||
/*@}*/ /* end of group Mini58_PWM_Driver */
|
||||
|
||||
/*@}*/ /* end of group Mini58_Device_Driver */
|
||||
|
||||
/*** (C) COPYRIGHT 2015 Nuvoton Technology Corp. ***/
|
||||
@@ -0,0 +1,493 @@
|
||||
/**************************************************************************//**
|
||||
* @file retarget.c
|
||||
* @version V1.00
|
||||
* $Revision: 4 $
|
||||
* $Date: 15/11/02 2:11p $
|
||||
* @brief Mini58 series retarget source file
|
||||
*
|
||||
* @note
|
||||
* Copyright (C) 2015 Nuvoton Technology Corp. All rights reserved.
|
||||
*****************************************************************************/
|
||||
#include <stdio.h>
|
||||
#include "Mini58Series.h"
|
||||
|
||||
#if defined ( __CC_ARM )
|
||||
#if (__ARMCC_VERSION < 400000)
|
||||
#else
|
||||
/* Insist on keeping widthprec, to avoid X propagation by benign code in C-lib */
|
||||
#pragma import _printf_widthprec
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG_ENABLE_UART1
|
||||
#define DEBUG_PORT UART1
|
||||
#else
|
||||
#define DEBUG_PORT UART0
|
||||
#endif
|
||||
|
||||
/* Un-comment this line to disable all printf and getchar. getchar() will always return 0x00*/
|
||||
//#define DISABLE_UART
|
||||
|
||||
#if defined(DEBUG_ENABLE_SEMIHOST)
|
||||
#ifndef DISABLE_UART
|
||||
#define DISABLE_UART
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/*---------------------------------------------------------------------------------------------------------*/
|
||||
/* Global variables */
|
||||
/*---------------------------------------------------------------------------------------------------------*/
|
||||
|
||||
#if !(defined(__ICCARM__) && (__VER__ >= 6010000))
|
||||
struct __FILE { int handle; /* Add whatever you need here */ };
|
||||
#endif
|
||||
FILE __stdout;
|
||||
FILE __stdin;
|
||||
|
||||
enum { r0, r1, r2, r3, r12, lr, pc, psr};
|
||||
|
||||
void stackDump(uint32_t stack[])
|
||||
{
|
||||
printf("r0 = 0x%x\n", stack[r0]);
|
||||
printf("r1 = 0x%x\n", stack[r1]);
|
||||
printf("r2 = 0x%x\n", stack[r2]);
|
||||
printf("r3 = 0x%x\n", stack[r3]);
|
||||
printf("r12 = 0x%x\n", stack[r12]);
|
||||
printf("lr = 0x%x\n", stack[lr]);
|
||||
printf("pc = 0x%x\n", stack[pc]);
|
||||
printf("psr = 0x%x\n", stack[psr]);
|
||||
}
|
||||
|
||||
void Hard_Fault_Handler(uint32_t stack[])
|
||||
{
|
||||
printf("In Hard Fault Handler\n");
|
||||
|
||||
stackDump(stack);
|
||||
|
||||
//Chip Reset
|
||||
//SYS_UnlockReg();
|
||||
//SYS->IPRSTC1 |= SYS_IPRSTC1_CHIP_RST_Msk;
|
||||
|
||||
while(1);
|
||||
}
|
||||
|
||||
|
||||
#if defined(DEBUG_ENABLE_SEMIHOST)
|
||||
/* The static buffer is used to speed up the semihost */
|
||||
static char g_buf[16];
|
||||
static char g_buf_len = 0;
|
||||
|
||||
# if defined(__ICCARM__)
|
||||
|
||||
|
||||
/**
|
||||
* @brief This HardFault handler is implemented to support semihost
|
||||
*
|
||||
* @param None
|
||||
*
|
||||
* @returns None
|
||||
*
|
||||
* @details This function is implement to support semihost message print.
|
||||
*
|
||||
*/
|
||||
void HardFault_Handler(void)
|
||||
{
|
||||
asm("MOV R0, lr \n"
|
||||
"LSLS R0, #29 \n" //; Check bit 2
|
||||
"BMI SP_is_PSP \n" //; previous stack is PSP
|
||||
"MRS R0, MSP \n" //; previous stack is MSP, read MSP
|
||||
"B SP_Read_Ready \n"
|
||||
"SP_is_PSP: \n"
|
||||
"MRS R0, PSP \n" //; Read PSP
|
||||
"SP_Read_Ready: \n"
|
||||
"LDR R1, [R0, #24] \n" //; Get previous PC
|
||||
"LDRH R3, [R1] \n" //; Get instruction
|
||||
"LDR R2, [pc, #8] \n" //; The special BKPT instruction
|
||||
"CMP R3, R2 \n" //; Test if the instruction at previous PC is BKPT
|
||||
"BNE HardFault_Handler_Ret\n" //; Not BKPT
|
||||
"ADDS R1, #4 \n" //; Skip BKPT and next line
|
||||
"STR R1, [R0, #24] \n" //; Save previous PC
|
||||
"BX lr \n" //; Return
|
||||
"DCD 0xBEAB \n" //; BKPT instruction code
|
||||
"HardFault_Handler_Ret:\n"
|
||||
"MOVS r0, #4 \n"
|
||||
"MOV r1, LR \n"
|
||||
"TST r0, r1 \n"
|
||||
"BEQ Stack_Use_MSP \n"
|
||||
"MRS R0, PSP \n" //; stack use PSP
|
||||
"B Get_LR_and_Branch \n"
|
||||
"Stack_Use_MSP: \n"
|
||||
"MRS R0, MSP \n" //; stack use MSP
|
||||
"Get_LR_and_Branch: \n"
|
||||
"MOV R1, LR \n" //; LR current value
|
||||
"B Hard_Fault_Handler \n"
|
||||
);
|
||||
|
||||
while(1);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @brief The function to process semihosted command
|
||||
* @param[in] n32In_R0 : semihost register 0
|
||||
* @param[in] n32In_R1 : semihost register 1
|
||||
* @param[out] pn32Out_R0: semihost register 0
|
||||
* @retval 0: No ICE debug
|
||||
* @retval 1: ICE debug
|
||||
*
|
||||
*/
|
||||
int32_t SH_DoCommand(int32_t n32In_R0, int32_t n32In_R1, int32_t *pn32Out_R0)
|
||||
{
|
||||
asm("BKPT 0xAB \n" //; This instruction will cause ICE trap or system HardFault
|
||||
"B SH_ICE \n"
|
||||
"SH_HardFault: \n" //; Captured by HardFault
|
||||
"MOVS R0, #0 \n" //; Set return value to 0
|
||||
"BX lr \n" //; Return
|
||||
"SH_ICE: \n" //; Captured by ICE
|
||||
"CMP R2, #0 \n"
|
||||
"BEQ SH_End \n"
|
||||
"STR R0, [R2]\n" //; Save the return value to *pn32Out_R0
|
||||
"SH_End: \n");
|
||||
|
||||
return 1; //; Return 1 when it is trap by ICE
|
||||
|
||||
}
|
||||
|
||||
|
||||
# else
|
||||
|
||||
/**
|
||||
* @brief This HardFault handler is implemented to support semihost
|
||||
*
|
||||
* @param None
|
||||
*
|
||||
* @returns None
|
||||
*
|
||||
* @details This function is implement to support semihost message print.
|
||||
*
|
||||
*/
|
||||
__asm int32_t HardFault_Handler(void)
|
||||
{
|
||||
|
||||
MOV R0, LR
|
||||
LSLS R0, #29 //; Check bit 2
|
||||
BMI SP_is_PSP //; previous stack is PSP
|
||||
MRS R0, MSP //; previous stack is MSP, read MSP
|
||||
B SP_Read_Ready
|
||||
SP_is_PSP
|
||||
MRS R0, PSP //; Read PSP
|
||||
|
||||
SP_Read_Ready
|
||||
LDR R1, [R0, #24] //; Get previous PC
|
||||
LDRH R3, [R1] //; Get instruction
|
||||
LDR R2, =0xBEAB //; The special BKPT instruction
|
||||
CMP R3, R2 //; Test if the instruction at previous PC is BKPT
|
||||
BNE HardFault_Handler_Ret //; Not BKPT
|
||||
|
||||
ADDS R1, #4 //; Skip BKPT and next line
|
||||
STR R1, [R0, #24] //; Save previous PC
|
||||
|
||||
BX LR //; Return
|
||||
HardFault_Handler_Ret
|
||||
|
||||
/* TODO: Implement your own hard fault handler here. */
|
||||
MOVS r0, #4
|
||||
MOV r1, LR
|
||||
TST r0, r1
|
||||
BEQ Stack_Use_MSP
|
||||
MRS R0, PSP ;stack use PSP
|
||||
B Get_LR_and_Branch
|
||||
Stack_Use_MSP
|
||||
MRS R0, MSP ; stack use MSP
|
||||
Get_LR_and_Branch
|
||||
MOV R1, LR ; LR current value
|
||||
LDR R2,=__cpp(Hard_Fault_Handler)
|
||||
BX R2
|
||||
|
||||
B .
|
||||
|
||||
ALIGN
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @brief The function to process semihosted command
|
||||
* @param[in] n32In_R0 : semihost register 0
|
||||
* @param[in] n32In_R1 : semihost register 1
|
||||
* @param[out] pn32Out_R0: semihost register 0
|
||||
* @retval 0: No ICE debug
|
||||
* @retval 1: ICE debug
|
||||
*
|
||||
*/
|
||||
__asm int32_t SH_DoCommand(int32_t n32In_R0, int32_t n32In_R1, int32_t *pn32Out_R0)
|
||||
{
|
||||
BKPT 0xAB //; Wait ICE or HardFault
|
||||
//; ICE will step over BKPT directly
|
||||
//; HardFault will step BKPT and the next line
|
||||
B SH_ICE
|
||||
|
||||
SH_HardFault //; Captured by HardFault
|
||||
MOVS R0, #0 //; Set return value to 0
|
||||
BX lr //; Return
|
||||
|
||||
SH_ICE //; Captured by ICE
|
||||
//; Save return value
|
||||
CMP R2, #0
|
||||
BEQ SH_End
|
||||
STR R0, [R2] //; Save the return value to *pn32Out_R0
|
||||
|
||||
SH_End
|
||||
MOVS R0, #1 //; Set return value to 1
|
||||
BX lr //; Return
|
||||
}
|
||||
#endif
|
||||
|
||||
#else
|
||||
|
||||
# if defined(__ICCARM__)
|
||||
|
||||
/**
|
||||
* @brief This HardFault handler is implemented to show r0, r1, r2, r3, r12, lr, pc, psr
|
||||
*
|
||||
* @param None
|
||||
*
|
||||
* @returns None
|
||||
*
|
||||
* @details This function is implement to print r0, r1, r2, r3, r12, lr, pc, psr.
|
||||
*
|
||||
*/
|
||||
void HardFault_Handler(void)
|
||||
{
|
||||
asm("MOVS r0, #4 \n"
|
||||
"MOV r1, LR \n"
|
||||
"TST r0, r1 \n"
|
||||
"BEQ Stack_Use_MSP \n"
|
||||
"MRS R0, PSP \n" //; stack use PSP
|
||||
"B Get_LR_and_Branch \n"
|
||||
"Stack_Use_MSP: \n"
|
||||
"MRS R0, MSP \n" //; stack use MSP
|
||||
"Get_LR_and_Branch: \n"
|
||||
"MOV R1, LR \n" //; LR current value
|
||||
"B Hard_Fault_Handler \n"
|
||||
);
|
||||
|
||||
while(1);
|
||||
}
|
||||
|
||||
# else
|
||||
|
||||
/**
|
||||
* @brief This HardFault handler is implemented to show r0, r1, r2, r3, r12, lr, pc, psr
|
||||
*
|
||||
* @param None
|
||||
*
|
||||
* @returns None
|
||||
*
|
||||
* @details This function is implement to print r0, r1, r2, r3, r12, lr, pc, psr
|
||||
*
|
||||
*/
|
||||
__asm int32_t HardFault_Handler(void)
|
||||
{
|
||||
MOVS r0, #4
|
||||
MOV r1, LR
|
||||
TST r0, r1
|
||||
BEQ Stack_Use_MSP
|
||||
MRS R0, PSP ;stack use PSP
|
||||
B Get_LR_and_Branch
|
||||
Stack_Use_MSP
|
||||
MRS R0, MSP ; stack use MSP
|
||||
Get_LR_and_Branch
|
||||
MOV R1, LR ; LR current value
|
||||
LDR R2,=__cpp(Hard_Fault_Handler)
|
||||
BX R2
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
* @brief Write a char to UART.
|
||||
* @param ch The character sent to UART.
|
||||
* @return None
|
||||
*/
|
||||
|
||||
void SendChar_ToUART(int ch)
|
||||
{
|
||||
#ifndef DISABLE_UART
|
||||
while(DEBUG_PORT->FIFOSTS & UART_FIFOSTS_TXFULL_Msk);
|
||||
DEBUG_PORT->DAT = ch;
|
||||
if(ch == '\n'){
|
||||
while(DEBUG_PORT->FIFOSTS & UART_FIFOSTS_TXFULL_Msk);
|
||||
DEBUG_PORT->DAT = '\r';
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Write a char to debug console.
|
||||
* @param ch The character sent to debug console
|
||||
* @return None
|
||||
*/
|
||||
|
||||
void SendChar(int ch)
|
||||
{
|
||||
#if defined(DEBUG_ENABLE_SEMIHOST)
|
||||
g_buf[g_buf_len++] = ch;
|
||||
g_buf[g_buf_len] = '\0';
|
||||
if(g_buf_len + 1 >= sizeof(g_buf) || ch == '\n' || ch == '\0')
|
||||
{
|
||||
|
||||
/* Send the char */
|
||||
|
||||
if(SH_DoCommand(0x04, (int)g_buf, NULL) != 0)
|
||||
{
|
||||
g_buf_len = 0;
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
int i;
|
||||
|
||||
for(i=0;i<g_buf_len;i++)
|
||||
SendChar_ToUART(g_buf[i]);
|
||||
g_buf_len = 0;
|
||||
}
|
||||
}
|
||||
#else
|
||||
SendChar_ToUART(ch);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Read a char from debug console.
|
||||
* @param None
|
||||
* @return Received character from debug console
|
||||
* @note This API waits until UART debug port or semihost input a character
|
||||
*/
|
||||
|
||||
char GetChar(void)
|
||||
{
|
||||
#if defined(DEBUG_ENABLE_SEMIHOST)
|
||||
# if defined ( __CC_ARM )
|
||||
int nRet;
|
||||
while(SH_DoCommand(0x101, 0, &nRet) != 0)
|
||||
{
|
||||
if(nRet != 0)
|
||||
{
|
||||
SH_DoCommand(0x07, 0, &nRet);
|
||||
return (char)nRet;
|
||||
}
|
||||
}
|
||||
# else
|
||||
int nRet;
|
||||
while(SH_DoCommand(0x7, 0, &nRet) != 0)
|
||||
{
|
||||
if(nRet != 0)
|
||||
return (char)nRet;
|
||||
}
|
||||
# endif
|
||||
#endif
|
||||
#ifndef DISABLE_UART
|
||||
while (1){
|
||||
if(!(DEBUG_PORT->FIFOSTS & UART_FIFOSTS_RXEMPTY_Msk))
|
||||
{
|
||||
return (DEBUG_PORT->DAT);
|
||||
|
||||
}
|
||||
}
|
||||
#else
|
||||
return(0);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Check whether UART receive FIFO is empty or not.
|
||||
* @param None
|
||||
* @return UART Rx FIFO empty status
|
||||
* @retval 1 Indicates at least one character is available in UART Rx FIFO
|
||||
* @retval 0 UART Rx FIFO is empty
|
||||
*/
|
||||
int kbhit(void)
|
||||
{
|
||||
#ifndef DISABLE_UART
|
||||
return !(DEBUG_PORT->FIFOSTS & UART_FIFOSTS_RXEMPTY_Msk);
|
||||
#else
|
||||
return(0);
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Check whether UART transmit FIFO is empty or not.
|
||||
* @param None
|
||||
* @return UART Tx FIFO empty status
|
||||
* @retval 1 UART Tx FIFO is empty
|
||||
* @retval 0 UART Tx FIFO is not empty
|
||||
*/
|
||||
int IsDebugFifoEmpty(void)
|
||||
{
|
||||
#ifndef DISABLE_UART
|
||||
return (DEBUG_PORT->FIFOSTS & UART_FIFOSTS_TXEMPTYF_Msk) ? 1 : 0;
|
||||
#else
|
||||
return(1);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------------------------------------*/
|
||||
/* C library retargetting */
|
||||
/*---------------------------------------------------------------------------------------------------------*/
|
||||
void _ttywrch(int ch)
|
||||
{
|
||||
SendChar(ch);
|
||||
return;
|
||||
}
|
||||
|
||||
int fputc(int ch, FILE *f)
|
||||
{
|
||||
SendChar(ch);
|
||||
return ch;
|
||||
}
|
||||
|
||||
int fgetc(FILE *f) {
|
||||
return (GetChar());
|
||||
}
|
||||
|
||||
|
||||
int ferror(FILE *f) {
|
||||
return EOF;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_ENABLE_SEMIHOST
|
||||
# ifdef __ICCARM__
|
||||
void __exit(int return_code) {
|
||||
|
||||
/* Check if link with ICE */
|
||||
|
||||
if(SH_DoCommand(0x18, 0x20026, NULL) == 0)
|
||||
{
|
||||
/* Make sure all message is print out */
|
||||
|
||||
while(IsDebugFifoEmpty() == 0);
|
||||
}
|
||||
label: goto label; /* endless loop */
|
||||
}
|
||||
# else
|
||||
void _sys_exit(int return_code) {
|
||||
|
||||
/* Check if link with ICE */
|
||||
if(SH_DoCommand(0x18, 0x20026, NULL) == 0)
|
||||
{
|
||||
/* Make sure all message is print out */
|
||||
while(IsDebugFifoEmpty() == 0);
|
||||
}
|
||||
label: goto label; /* endless loop */
|
||||
}
|
||||
# endif
|
||||
#endif
|
||||
/*** (C) COPYRIGHT 2015 Nuvoton Technology Corp. ***/
|
||||
|
||||
@@ -0,0 +1,260 @@
|
||||
/**************************************************************************//**
|
||||
* @file spi.c
|
||||
* @version V1.00
|
||||
* $Revision: 7 $
|
||||
* $Date: 15/05/28 1:47p $
|
||||
* @brief Mini58 series SPI driver source file
|
||||
*
|
||||
* @note
|
||||
* Copyright (C) 2015 Nuvoton Technology Corp. All rights reserved.
|
||||
*****************************************************************************/
|
||||
#include "Mini58Series.h"
|
||||
/** @addtogroup Mini58_Device_Driver Mini58 Device Driver
|
||||
@{
|
||||
*/
|
||||
|
||||
/** @addtogroup Mini58_SPI_Driver SPI Driver
|
||||
@{
|
||||
*/
|
||||
|
||||
|
||||
/** @addtogroup Mini58_SPI_EXPORTED_FUNCTIONS SPI Exported Functions
|
||||
@{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief This function make SPI module be ready to transfer.
|
||||
* By default, the SPI transfer sequence is MSB first and
|
||||
* the automatic slave select function is disabled. In
|
||||
* Slave mode, the u32BusClock must be NULL and the SPI clock
|
||||
* divider setting will be 0.
|
||||
* @param[in] spi is the base address of SPI module.
|
||||
* @param[in] u32MasterSlave decides the SPI module is operating in master mode or in slave mode. ( \ref SPI_SLAVE, \ref SPI_MASTER)
|
||||
* @param[in] u32SPIMode decides the transfer timing. ( \ref SPI_MODE_0, \ref SPI_MODE_1, \ref SPI_MODE_2, \ref SPI_MODE_3)
|
||||
* @param[in] u32DataWidth decides the data width of a SPI transaction.
|
||||
* @param[in] u32BusClock is the expected frequency of SPI bus clock in Hz.
|
||||
* @return Actual frequency of SPI peripheral clock.
|
||||
*/
|
||||
uint32_t SPI_Open(SPI_T *spi,
|
||||
uint32_t u32MasterSlave,
|
||||
uint32_t u32SPIMode,
|
||||
uint32_t u32DataWidth,
|
||||
uint32_t u32BusClock)
|
||||
{
|
||||
if(u32DataWidth == 32)
|
||||
u32DataWidth = 0;
|
||||
|
||||
spi->CTL = u32MasterSlave | (u32DataWidth << SPI_CTL_DWIDTH_Pos) | (u32SPIMode);
|
||||
|
||||
if(u32MasterSlave == SPI_SLAVE)
|
||||
spi->SSCTL = SPI_SSCTL_SSLTEN_Msk;
|
||||
|
||||
return ( SPI_SetBusClock(spi, u32BusClock) );
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Reset SPI module and disable SPI peripheral clock.
|
||||
* @param[in] spi is the base address of SPI module.
|
||||
* @return none
|
||||
*/
|
||||
void SPI_Close(SPI_T *spi)
|
||||
{
|
||||
/* Reset SPI */
|
||||
SYS->IPRST1 |= SYS_IPRST1_SPI0RST_Msk;
|
||||
SYS->IPRST1 &= ~SYS_IPRST1_SPI0RST_Msk;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Clear Rx FIFO buffer.
|
||||
* @param[in] spi is the base address of SPI module.
|
||||
* @return none
|
||||
*/
|
||||
void SPI_ClearRxFIFO(SPI_T *spi)
|
||||
{
|
||||
spi->FIFOCTL |= SPI_FIFOCTL_RXRST_Msk;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Clear Tx FIFO buffer.
|
||||
* @param[in] spi is the base address of SPI module.
|
||||
* @return none
|
||||
*/
|
||||
void SPI_ClearTxFIFO(SPI_T *spi)
|
||||
{
|
||||
spi->FIFOCTL |= SPI_FIFOCTL_TXRST_Msk;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disable the automatic slave select function.
|
||||
* @param[in] spi is the base address of SPI module.
|
||||
* @return none
|
||||
*/
|
||||
void SPI_DisableAutoSS(SPI_T *spi)
|
||||
{
|
||||
spi->SSCTL &= ~SPI_SSCTL_AUTOSS_Msk;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable the automatic slave select function. Only available in Master mode.
|
||||
* @param[in] spi is the base address of SPI module.
|
||||
* @param[in] u32SSPinMask specifies slave select pins. ( \ref SPI_SS)
|
||||
* @param[in] u32ActiveLevel specifies the active level of slave select signal. ( \ref SPI_SS_ACTIVE_HIGH, \ref SPI_SS_ACTIVE_LOW)
|
||||
* @return none
|
||||
*/
|
||||
void SPI_EnableAutoSS(SPI_T *spi, uint32_t u32SSPinMask, uint32_t u32ActiveLevel)
|
||||
{
|
||||
spi->SSCTL = (spi->SSCTL & ~(SPI_SSCTL_SSACTPOL_Msk | SPI_SSCTL_SS_Msk)) | (u32SSPinMask | u32ActiveLevel) | SPI_SSCTL_AUTOSS_Msk;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set the SPI bus clock. Only available in Master mode.
|
||||
* @param[in] spi is the base address of SPI module.
|
||||
* @param[in] u32BusClock is the expected frequency of SPI bus clock.
|
||||
* @return Actual frequency of SPI peripheral clock.
|
||||
*/
|
||||
uint32_t SPI_SetBusClock(SPI_T *spi, uint32_t u32BusClock)
|
||||
{
|
||||
uint32_t u32Div = 0;
|
||||
uint32_t u32ClkSrc;
|
||||
|
||||
if((CLK->CLKSEL1 & CLK_CLKSEL1_SPISEL_Msk) == CLK_CLKSEL1_SPISEL_XTAL) {
|
||||
if((u32ClkSrc = CLK_GetHXTFreq()) == 0)
|
||||
u32ClkSrc = CLK_GetLXTFreq();
|
||||
} else if((CLK->CLKSEL1 & CLK_CLKSEL1_SPISEL_Msk) == CLK_CLKSEL1_SPISEL_PLL)
|
||||
u32ClkSrc = CLK_GetPLLClockFreq();
|
||||
else
|
||||
u32ClkSrc = CLK_GetHCLKFreq();
|
||||
|
||||
if(u32BusClock > u32ClkSrc)
|
||||
u32BusClock = u32ClkSrc;
|
||||
|
||||
if(u32BusClock != 0) {
|
||||
u32Div = (((u32ClkSrc / u32BusClock) + 1) >> 1) - 1;
|
||||
if(u32Div > SPI_CLKDIV_DIVIDER_Msk)
|
||||
u32Div = SPI_CLKDIV_DIVIDER_Msk;
|
||||
} else
|
||||
return 0;
|
||||
|
||||
spi->CLKDIV = (spi->CLKDIV & ~SPI_CLKDIV_DIVIDER_Msk) | u32Div;
|
||||
|
||||
return ( u32ClkSrc / ((u32Div+1)*2) );
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable FIFO mode with user-specified Tx FIFO threshold and Rx FIFO threshold configurations.
|
||||
* @param[in] spi is the base address of SPI module.
|
||||
* @param[in] u32TxThreshold decides the Tx FIFO threshold.
|
||||
* @param[in] u32RxThreshold decides the Rx FIFO threshold.
|
||||
* @return none
|
||||
*/
|
||||
void SPI_EnableFIFO(SPI_T *spi, uint32_t u32TxThreshold, uint32_t u32RxThreshold)
|
||||
{
|
||||
spi->FIFOCTL = (spi->FIFOCTL & ~(SPI_FIFOCTL_TXTH_Msk | SPI_FIFOCTL_RXTH_Msk) |
|
||||
(u32TxThreshold << SPI_FIFOCTL_TXTH_Pos) |
|
||||
(u32RxThreshold << SPI_FIFOCTL_RXTH_Pos));
|
||||
|
||||
spi->CTL |= SPI_CTL_FIFOEN_Msk;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disable FIFO mode.
|
||||
* @param[in] spi is the base address of SPI module.
|
||||
* @return none
|
||||
*/
|
||||
void SPI_DisableFIFO(SPI_T *spi)
|
||||
{
|
||||
spi->CTL &= ~SPI_CTL_FIFOEN_Msk;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the actual frequency of SPI bus clock. Only available in Master mode.
|
||||
* @param[in] spi is the base address of SPI module.
|
||||
* @return Actual SPI bus clock frequency.
|
||||
*/
|
||||
uint32_t SPI_GetBusClock(SPI_T *spi)
|
||||
{
|
||||
uint32_t u32Div;
|
||||
uint32_t u32ClkSrc;
|
||||
|
||||
if((CLK->CLKSEL1 & CLK_CLKSEL1_SPISEL_Msk) == CLK_CLKSEL1_SPISEL_XTAL) {
|
||||
if((u32ClkSrc = CLK_GetHXTFreq()) == 0)
|
||||
u32ClkSrc = CLK_GetLXTFreq();
|
||||
} else if((CLK->CLKSEL1 & CLK_CLKSEL1_SPISEL_Msk) == CLK_CLKSEL1_SPISEL_PLL)
|
||||
u32ClkSrc = CLK_GetPLLClockFreq();
|
||||
else
|
||||
u32ClkSrc = CLK_GetHCLKFreq();
|
||||
|
||||
u32Div = spi->CLKDIV & SPI_CLKDIV_DIVIDER_Msk;
|
||||
|
||||
return ( u32ClkSrc / ((u32Div + 1)*2) );
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable FIFO related interrupts specified by u32Mask parameter.
|
||||
* @param[in] spi is the base address of SPI module.
|
||||
* @param[in] u32Mask is the combination of all related interrupt enable bits.
|
||||
* Each bit corresponds to a interrupt bit.
|
||||
* This parameter decides which interrupts will be enabled.
|
||||
* ( \ref SPI_IE_MASK, \ref SPI_SSTA_INTEN_MASK, \ref SPI_FIFO_TX_INTEN_MASK,
|
||||
* \ref SPI_FIFO_RX_INTEN_MASK, \ref SPI_FIFO_RXOV_INTEN_MASK, \ref SPI_FIFO_TIMEOUT_INTEN_MASK)
|
||||
* @return none
|
||||
*/
|
||||
void SPI_EnableInt(SPI_T *spi, uint32_t u32Mask)
|
||||
{
|
||||
if((u32Mask & SPI_IE_MASK) == SPI_IE_MASK)
|
||||
spi->CTL |= SPI_CTL_UNITIEN_Msk;
|
||||
|
||||
if((u32Mask & SPI_SSTA_INTEN_MASK) == SPI_SSTA_INTEN_MASK)
|
||||
spi->SLVCTL |= SPI_SLVCTL_SLVSTIEN_Msk;
|
||||
|
||||
if((u32Mask & SPI_FIFO_TX_INTEN_MASK) == SPI_FIFO_TX_INTEN_MASK)
|
||||
spi->FIFOCTL |= SPI_FIFOCTL_TXTHIEN_Msk;
|
||||
|
||||
if((u32Mask & SPI_FIFO_RX_INTEN_MASK) == SPI_FIFO_RX_INTEN_MASK)
|
||||
spi->FIFOCTL |= SPI_FIFOCTL_RXTHIEN_Msk;
|
||||
|
||||
if((u32Mask & SPI_FIFO_RXOV_INTEN_MASK) == SPI_FIFO_RXOV_INTEN_MASK)
|
||||
spi->FIFOCTL |= SPI_FIFOCTL_RXOVIEN_Msk;
|
||||
|
||||
if((u32Mask & SPI_FIFO_TIMEOUT_INTEN_MASK) == SPI_FIFO_TIMEOUT_INTEN_MASK)
|
||||
spi->FIFOCTL |= SPI_FIFOCTL_RXTOIEN_Msk;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disable FIFO related interrupts specified by u32Mask parameter.
|
||||
* @param[in] spi is the base address of SPI module.
|
||||
* @param[in] u32Mask is the combination of all related interrupt enable bits.
|
||||
* Each bit corresponds to a interrupt bit.
|
||||
* This parameter decides which interrupts will be disabled.
|
||||
* ( \ref SPI_IE_MASK, \ref SPI_SSTA_INTEN_MASK, \ref SPI_FIFO_TX_INTEN_MASK,
|
||||
* \ref SPI_FIFO_RX_INTEN_MASK, \ref SPI_FIFO_RXOV_INTEN_MASK, \ref SPI_FIFO_TIMEOUT_INTEN_MASK)
|
||||
* @return none
|
||||
*/
|
||||
void SPI_DisableInt(SPI_T *spi, uint32_t u32Mask)
|
||||
{
|
||||
if((u32Mask & SPI_IE_MASK) == SPI_IE_MASK)
|
||||
spi->CTL &= ~SPI_CTL_UNITIEN_Msk;
|
||||
|
||||
if((u32Mask & SPI_SSTA_INTEN_MASK) == SPI_SSTA_INTEN_MASK)
|
||||
spi->SLVCTL &= ~SPI_SLVCTL_SLVSTIEN_Msk;
|
||||
|
||||
if((u32Mask & SPI_FIFO_TX_INTEN_MASK) == SPI_FIFO_TX_INTEN_MASK)
|
||||
spi->FIFOCTL &= ~SPI_FIFOCTL_TXTHIEN_Msk;
|
||||
|
||||
if((u32Mask & SPI_FIFO_RX_INTEN_MASK) == SPI_FIFO_RX_INTEN_MASK)
|
||||
spi->FIFOCTL &= ~SPI_FIFOCTL_RXTHIEN_Msk;
|
||||
|
||||
if((u32Mask & SPI_FIFO_RXOV_INTEN_MASK) == SPI_FIFO_RXOV_INTEN_MASK)
|
||||
spi->FIFOCTL &= ~SPI_FIFOCTL_RXOVIEN_Msk;
|
||||
|
||||
if((u32Mask & SPI_FIFO_TIMEOUT_INTEN_MASK) == SPI_FIFO_TIMEOUT_INTEN_MASK)
|
||||
spi->FIFOCTL &= ~SPI_FIFOCTL_RXTOIEN_Msk;
|
||||
}
|
||||
|
||||
/*@}*/ /* end of group Mini58_SPI_EXPORTED_FUNCTIONS */
|
||||
|
||||
/*@}*/ /* end of group Mini58_SPI_Driver */
|
||||
|
||||
/*@}*/ /* end of group Mini58_Device_Driver */
|
||||
|
||||
/*** (C) COPYRIGHT 2015 Nuvoton Technology Corp. ***/
|
||||
@@ -0,0 +1,153 @@
|
||||
/**************************************************************************//**
|
||||
* @file sys.c
|
||||
* @version V1.00
|
||||
* $Revision: 9 $
|
||||
* $Date: 15/06/05 1:13p $
|
||||
* @brief Mini58 series SYS driver source file
|
||||
*
|
||||
* @note
|
||||
* Copyright (C) 2015 Nuvoton Technology Corp. All rights reserved.
|
||||
*****************************************************************************/
|
||||
#include "Mini58Series.h"
|
||||
/** @addtogroup Mini58_Device_Driver Mini58 Device Driver
|
||||
@{
|
||||
*/
|
||||
|
||||
/** @addtogroup Mini58_SYS_Driver SYS Driver
|
||||
@{
|
||||
*/
|
||||
|
||||
|
||||
/** @addtogroup Mini58_SYS_EXPORTED_FUNCTIONS SYS Exported Functions
|
||||
@{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief This function clear the selected system reset source
|
||||
* @param[in] u32Src is system reset source
|
||||
* @return None
|
||||
*/
|
||||
void SYS_ClearResetSrc(uint32_t u32Src)
|
||||
{
|
||||
SYS->RSTSTS |= u32Src;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function get Brown-out detector output status
|
||||
* @return 0: System voltage is higher than BOD_VL setting or BOD_EN is 0.
|
||||
* 1: System voltage is lower than BOD_VL setting.
|
||||
* Note : If the BOD_EN is 0, this function always return 0.
|
||||
*/
|
||||
uint32_t SYS_GetBODStatus(void)
|
||||
{
|
||||
return (SYS->BODCTL & SYS_BODCTL_BODOUT_Msk)?1:0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function get the system reset source register value
|
||||
* @return Reset source
|
||||
*/
|
||||
uint32_t SYS_GetResetSrc(void)
|
||||
{
|
||||
return (SYS->RSTSTS);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function check register write-protection bit setting
|
||||
* @return 0: Write-protection function is disabled.
|
||||
* 1: Write-protection function is enabled.
|
||||
*/
|
||||
uint32_t SYS_IsRegLocked(void)
|
||||
{
|
||||
return !(SYS->REGLCTL & SYS_REGLCTL_REGLCTL_Msk);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function get product ID.
|
||||
* @return Product ID
|
||||
*/
|
||||
uint32_t SYS_ReadPDID(void)
|
||||
{
|
||||
return SYS->PDID;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function reset chip.
|
||||
* @return None
|
||||
*/
|
||||
void SYS_ResetChip(void)
|
||||
{
|
||||
SYS->IPRST0 |= SYS_IPRST0_CHIPRST_Msk;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function reset CPU.
|
||||
* @return None
|
||||
*/
|
||||
void SYS_ResetCPU(void)
|
||||
{
|
||||
SYS->IPRST0 |= SYS_IPRST0_CPURST_Msk;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function reset selected modules.
|
||||
* @param[in] u32ModuleIndex is module index. Including :
|
||||
* - \ref ADC_RST
|
||||
* - \ref ACMP_RST
|
||||
* - \ref PWM0_RST
|
||||
* - \ref UART0_RST
|
||||
* - \ref UART1_RST
|
||||
* - \ref SPI0_RST
|
||||
* - \ref I2C0_RST
|
||||
* - \ref I2C1_RST
|
||||
* - \ref TMR1_RST
|
||||
* - \ref TMR0_RST
|
||||
* - \ref GPIO_RST
|
||||
* @return None
|
||||
*/
|
||||
void SYS_ResetModule(uint32_t u32ModuleIndex)
|
||||
{
|
||||
*(volatile uint32_t *)(&(SYS->IPRST0) + (u32ModuleIndex>>24)) |= 1<<(u32ModuleIndex & 0x00ffffff);
|
||||
*(volatile uint32_t *)(&(SYS->IPRST0) + (u32ModuleIndex>>24)) &= ~(1<<(u32ModuleIndex & 0x00ffffff));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function configure BOD function.
|
||||
* Configure BOD reset or interrupt mode and set Brown-out voltage level.
|
||||
* Enable Brown-out function
|
||||
* @param[in] i32Mode is reset or interrupt mode. Including :
|
||||
* - \ref SYS_BODCTL_BOD_RST_EN
|
||||
* - \ref SYS_BODCTL_BOD_INTERRUPT_EN
|
||||
* @param[in] u32BODLevel is Brown-out voltage level. Including :
|
||||
* - \ref SYS_BODCTL_BODVL_4_4V
|
||||
* - \ref SYS_BODCTL_BODVL_3_7V
|
||||
* - \ref SYS_BODCTL_BODVL_2_7V
|
||||
* - \ref SYS_BODCTL_BODVL_2_2V
|
||||
* @return None
|
||||
*/
|
||||
void SYS_EnableBOD(int32_t i32Mode, uint32_t u32BODLevel)
|
||||
{
|
||||
SYS->BODCTL |= SYS_BODCTL_BODEN_Msk;
|
||||
SYS->BODCTL = (SYS->BODCTL & ~SYS_BODCTL_BODRSTEN_Msk) | i32Mode;
|
||||
SYS->BODCTL = (SYS->BODCTL & ~SYS_BODCTL_BODVL_Msk) | u32BODLevel;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function disable BOD function.
|
||||
* @return None
|
||||
*/
|
||||
void SYS_DisableBOD(void)
|
||||
{
|
||||
SYS->BODCTL &= ~SYS_BODCTL_BODEN_Msk;
|
||||
SYS->BODCTL = (SYS->BODCTL & ~SYS_BODCTL_BODVL_Msk) | SYS_BODCTL_BODVL_Msk ;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*@}*/ /* end of group Mini58_SYS_EXPORTED_FUNCTIONS */
|
||||
|
||||
/*@}*/ /* end of group Mini58_SYS_Driver */
|
||||
|
||||
/*@}*/ /* end of group Mini58_Device_Driver */
|
||||
|
||||
/*** (C) COPYRIGHT 2015 Nuvoton Technology Corp. ***/
|
||||
@@ -0,0 +1,217 @@
|
||||
/**************************************************************************//**
|
||||
* @file timer.c
|
||||
* @version V1.00
|
||||
* $Revision: 3 $
|
||||
* $Date: 15/05/27 11:56a $
|
||||
* @brief Mini58 series TIMER driver source file
|
||||
*
|
||||
* @note
|
||||
* Copyright (C) 2015 Nuvoton Technology Corp. All rights reserved.
|
||||
*****************************************************************************/
|
||||
#include "Mini58Series.h"
|
||||
|
||||
/** @addtogroup Mini58_Device_Driver Mini58 Device Driver
|
||||
@{
|
||||
*/
|
||||
|
||||
/** @addtogroup Mini58_TIMER_Driver TIMER Driver
|
||||
@{
|
||||
*/
|
||||
|
||||
|
||||
/** @addtogroup Mini58_TIMER_EXPORTED_FUNCTIONS TIMER Exported Functions
|
||||
@{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief This API is used to configure timer to operate in specified mode
|
||||
* and frequency. If timer cannot work in target frequency, a closest
|
||||
* frequency will be chose and returned.
|
||||
* @param[in] timer The base address of Timer module
|
||||
* @param[in] u32Mode Operation mode. Possible options are
|
||||
* - \ref TIMER_ONESHOT_MODE
|
||||
* - \ref TIMER_PERIODIC_MODE
|
||||
* - \ref TIMER_TOGGLE_MODE
|
||||
* - \ref TIMER_CONTINUOUS_MODE
|
||||
* @param[in] u32Freq Target working frequency
|
||||
* @return Real Timer working frequency
|
||||
* @note After calling this API, Timer is \b NOT running yet. But could start timer running be calling
|
||||
* \ref TIMER_Start macro or program registers directly
|
||||
*/
|
||||
uint32_t TIMER_Open(TIMER_T *timer, uint32_t u32Mode, uint32_t u32Freq)
|
||||
{
|
||||
uint32_t u32Clk = TIMER_GetModuleClock(timer);
|
||||
uint32_t u32Cmpr = 0, u32Prescale = 0;
|
||||
|
||||
// Fastest possible timer working freq is u32Clk / 2. While cmpr = 2, pre-scale = 0
|
||||
if(u32Freq > (u32Clk / 2)) {
|
||||
u32Cmpr = 2;
|
||||
} else {
|
||||
if(u32Clk >= 0x2000000) {
|
||||
u32Prescale = 3; // real prescaler value is 4
|
||||
u32Clk >>= 2;
|
||||
} else if(u32Clk >= 0x1000000) {
|
||||
u32Prescale = 1; // real prescaler value is 2
|
||||
u32Clk >>= 1;
|
||||
}
|
||||
u32Cmpr = u32Clk / u32Freq;
|
||||
}
|
||||
|
||||
timer->CTL = u32Mode | u32Prescale;
|
||||
timer->CMP = u32Cmpr;
|
||||
|
||||
return(u32Clk / (u32Cmpr * (u32Prescale + 1)));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This API stops Timer counting and disable the Timer interrupt function
|
||||
* @param[in] timer The base address of Timer module
|
||||
* @return None
|
||||
*/
|
||||
void TIMER_Close(TIMER_T *timer)
|
||||
{
|
||||
timer->CTL = 0;
|
||||
timer->EXTCTL = 0;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This API is used to create a delay loop for u32usec micro seconds
|
||||
* @param[in] timer The base address of Timer module
|
||||
* @param[in] u32Usec Delay period in micro seconds with 10 usec every step. Valid values are between 10~1000000 (10 micro second ~ 1 second)
|
||||
* @return None
|
||||
* @note This API overwrites the register setting of the timer used to count the delay time.
|
||||
* @note This API use polling mode. So there is no need to enable interrupt for the timer module used to generate delay
|
||||
*/
|
||||
void TIMER_Delay(TIMER_T *timer, uint32_t u32Usec)
|
||||
{
|
||||
uint32_t u32Clk = TIMER_GetModuleClock(timer);
|
||||
uint32_t u32Prescale = 0, delay = SystemCoreClock / u32Clk;
|
||||
float fCmpr;
|
||||
|
||||
// Clear current timer configuration
|
||||
timer->CTL = 0;
|
||||
timer->EXTCTL = 0;
|
||||
|
||||
if(u32Clk == 10000) { // min delay is 100us if timer clock source is LIRC 10k
|
||||
u32Usec = ((u32Usec + 99) / 100) * 100;
|
||||
} else { // 10 usec every step
|
||||
u32Usec = ((u32Usec + 9) / 10) * 10;
|
||||
}
|
||||
|
||||
if(u32Clk >= 0x2000000) {
|
||||
u32Prescale = 3; // real prescaler value is 4
|
||||
u32Clk >>= 2;
|
||||
} else if(u32Clk >= 0x1000000) {
|
||||
u32Prescale = 1; // real prescaler value is 2
|
||||
u32Clk >>= 1;
|
||||
}
|
||||
|
||||
// u32Usec * u32Clk might overflow if using uint32_t
|
||||
fCmpr = ((float)u32Usec * (float)u32Clk) / 1000000.0;
|
||||
|
||||
timer->CMP = (uint32_t)fCmpr;
|
||||
timer->CTL = TIMER_CTL_CNTEN_Msk | u32Prescale; // one shot mode
|
||||
|
||||
// When system clock is faster than timer clock, it is possible timer active bit cannot set in time while we check it.
|
||||
// And the while loop below return immediately, so put a tiny delay here allowing timer start counting and raise active flag.
|
||||
for(; delay > 0; delay--) {
|
||||
__NOP();
|
||||
}
|
||||
|
||||
while(timer->CTL & TIMER_CTL_ACTSTS_Msk);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This API is used to enable timer capture function with specified mode and capture edge
|
||||
* @param[in] timer The base address of Timer module
|
||||
* @param[in] u32CapMode Timer capture mode. Could be
|
||||
* - \ref TIMER_CAPTURE_FREE_COUNTING_MODE
|
||||
* - \ref TIMER_CAPTURE_TRIGGER_COUNTING_MODE
|
||||
* - \ref TIMER_CAPTURE_COUNTER_RESET_MODE
|
||||
* @param[in] u32Edge Timer capture edge. Possible values are
|
||||
* - \ref TIMER_CAPTURE_FALLING_EDGE
|
||||
* - \ref TIMER_CAPTURE_RISING_EDGE
|
||||
* - \ref TIMER_CAPTURE_FALLING_THEN_RISING_EDGE
|
||||
* - \ref TIMER_CAPTURE_RISING_THEN_FALLING_EDGE
|
||||
* @return None
|
||||
* @note Timer frequency should be configured separately by using \ref TIMER_Open API, or program registers directly
|
||||
*/
|
||||
void TIMER_EnableCapture(TIMER_T *timer, uint32_t u32CapMode, uint32_t u32Edge)
|
||||
{
|
||||
|
||||
timer->EXTCTL = (timer->EXTCTL & ~(TIMER_EXTCTL_CAPSEL_Msk |
|
||||
TIMER_EXTCTL_CAPFUNCS_Msk |
|
||||
TIMER_EXTCTL_CAPEDGE_Msk)) |
|
||||
u32CapMode | u32Edge | TIMER_EXTCTL_CAPEN_Msk;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This API is used to disable the Timer capture function
|
||||
* @param[in] timer The base address of Timer module
|
||||
* @return None
|
||||
*/
|
||||
void TIMER_DisableCapture(TIMER_T *timer)
|
||||
{
|
||||
timer->EXTCTL &= ~TIMER_EXTCTL_CAPEN_Msk;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function is used to enable the Timer counter function with specify detection edge
|
||||
* @param[in] timer The base address of Timer module
|
||||
* @param[in] u32Edge Detection edge of counter pin. Could be ether
|
||||
* - \ref TIMER_COUNTER_RISING_EDGE, or
|
||||
* - \ref TIMER_COUNTER_FALLING_EDGE
|
||||
* @return None
|
||||
* @note Timer compare value should be configured separately by using \ref TIMER_SET_CMP_VALUE macro or program registers directly
|
||||
*/
|
||||
void TIMER_EnableEventCounter(TIMER_T *timer, uint32_t u32Edge)
|
||||
{
|
||||
timer->EXTCTL = (timer->EXTCTL & ~TIMER_EXTCTL_CNTPHASE_Msk) | u32Edge;
|
||||
timer->CTL |= TIMER_CTL_EXTCNTEN_Msk;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This API is used to disable the Timer event counter function.
|
||||
* @param[in] timer The base address of Timer module
|
||||
* @return None
|
||||
*/
|
||||
void TIMER_DisableEventCounter(TIMER_T *timer)
|
||||
{
|
||||
timer->CTL &= ~TIMER_CTL_EXTCNTEN_Msk;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This API is used to get the clock frequency of Timer
|
||||
* @param[in] timer The base address of Timer module
|
||||
* @return Timer clock frequency
|
||||
* @note This API cannot return correct clock rate if timer source is external clock input.
|
||||
*/
|
||||
uint32_t TIMER_GetModuleClock(TIMER_T *timer)
|
||||
{
|
||||
uint32_t u32Src;
|
||||
if(timer == TIMER0)
|
||||
u32Src = (CLK->CLKSEL1 & CLK_CLKSEL1_TMR0SEL_Msk) >> CLK_CLKSEL1_TMR0SEL_Pos;
|
||||
else
|
||||
u32Src = (CLK->CLKSEL1 & CLK_CLKSEL1_TMR1SEL_Msk) >> CLK_CLKSEL1_TMR1SEL_Pos;
|
||||
|
||||
if(u32Src == 0)
|
||||
return((CLK->PWRCTL & CLK_PWRCTL_XTLEN_Msk) == 1 ? __XTAL12M : __XTAL32K);
|
||||
else if(u32Src == 1)
|
||||
return __IRC10K;
|
||||
else if(u32Src == 2)
|
||||
return SystemCoreClock;
|
||||
else
|
||||
return __HSI;
|
||||
|
||||
}
|
||||
|
||||
/*@}*/ /* end of group Mini58_TIMER_EXPORTED_FUNCTIONS */
|
||||
|
||||
/*@}*/ /* end of group Mini58_TIMER_Driver */
|
||||
|
||||
/*@}*/ /* end of group Mini58_Device_Driver */
|
||||
|
||||
/*** (C) COPYRIGHT 2015 Nuvoton Technology Corp. ***/
|
||||
@@ -0,0 +1,364 @@
|
||||
/**************************************************************************//**
|
||||
* @file uart.c
|
||||
* @version V1.00
|
||||
* $Revision: 3 $
|
||||
* $Date: 15/05/28 4:34p $
|
||||
* @brief Mini58 series UART driver source file
|
||||
*
|
||||
* @note
|
||||
* Copyright (C) 2015 Nuvoton Technology Corp. All rights reserved.
|
||||
*****************************************************************************/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "Mini58Series.h"
|
||||
|
||||
/** @addtogroup Mini58_Device_Driver Mini58 Device Driver
|
||||
@{
|
||||
*/
|
||||
|
||||
/** @addtogroup Mini58_UART_Driver UART Driver
|
||||
@{
|
||||
*/
|
||||
|
||||
|
||||
/** @addtogroup Mini58_UART_EXPORTED_FUNCTIONS UART Exported Functions
|
||||
@{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief The function is used to clear UART specified interrupt flag.
|
||||
*
|
||||
* @param[in] uart The base address of UART module.
|
||||
* @param[in] u32InterruptFlag The specified interrupt of UART module.
|
||||
*
|
||||
* @return None
|
||||
*/
|
||||
void UART_ClearIntFlag(UART_T* uart , uint32_t u32InterruptFlag)
|
||||
{
|
||||
|
||||
if(u32InterruptFlag & UART_INTSTS_RLSINT_Msk) { /* clear Receive Line Status Interrupt */
|
||||
uart->FIFOSTS = UART_FIFOSTS_BIF_Msk | UART_FIFOSTS_FEF_Msk | UART_FIFOSTS_FEF_Msk;
|
||||
uart->FIFOSTS = UART_FIFOSTS_ADDRDETF_Msk;
|
||||
}
|
||||
|
||||
if(u32InterruptFlag & UART_INTSTS_MODEMINT_Msk) /* clear Modem Interrupt */
|
||||
uart->MODEMSTS = UART_MODEMSTS_CTSDETF_Msk;
|
||||
|
||||
if(u32InterruptFlag & UART_INTSTS_BUFERRINT_Msk) { /* clear Buffer Error Interrupt */
|
||||
uart->FIFOSTS = UART_FIFOSTS_RXOVIF_Msk | UART_FIFOSTS_TXOVIF_Msk;
|
||||
}
|
||||
|
||||
if(u32InterruptFlag & UART_INTSTS_RXTOINT_Msk) /* clear Modem Interrupt */
|
||||
uart->INTSTS = UART_INTSTS_RXTOIF_Msk;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief The function is used to disable UART.
|
||||
*
|
||||
* @param[in] uart The base address of UART module.
|
||||
*
|
||||
* @return None
|
||||
*/
|
||||
void UART_Close(UART_T* uart)
|
||||
{
|
||||
uart->INTEN = 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief The function is used to disable UART auto flow control.
|
||||
*
|
||||
* @param[in] uart The base address of UART module.
|
||||
*
|
||||
* @return None
|
||||
*/
|
||||
void UART_DisableFlowCtrl(UART_T* uart)
|
||||
{
|
||||
uart->INTEN &= ~(UART_INTEN_ATORTSEN_Msk | UART_INTEN_ATOCTSEN_Msk);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief The function is used to disable UART specified interrupt and disable NVIC UART IRQ.
|
||||
*
|
||||
* @param[in] uart The base address of UART module.
|
||||
* @param[in] u32InterruptFlag The specified interrupt of UART module.
|
||||
* - \ref UART_INTEN_TOCNTEN_Msk : Rx Time Out interrupt
|
||||
* - \ref UART_INTEN_WKCTSIEN_Msk : Wakeup interrupt
|
||||
* - \ref UART_INTEN_BUFERRIEN_Msk : Buffer Error interrupt
|
||||
* - \ref UART_INTEN_RXTOIEN_Msk : Rx time-out interrupt
|
||||
* - \ref UART_INTEN_MODEMIEN_Msk : Modem interrupt
|
||||
* - \ref UART_INTEN_RLSIEN_Msk : Rx Line status interrupt
|
||||
* - \ref UART_INTEN_THREIEN_Msk : Tx empty interrupt
|
||||
* - \ref UART_INTEN_RDAIEN_Msk : Rx ready interrupt
|
||||
*
|
||||
* @return None
|
||||
*/
|
||||
void UART_DisableInt(UART_T* uart, uint32_t u32InterruptFlag )
|
||||
{
|
||||
uart->INTEN &= ~ u32InterruptFlag;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief The function is used to Enable UART auto flow control.
|
||||
*
|
||||
* @param[in] uart The base address of UART module.
|
||||
*
|
||||
* @return None
|
||||
*/
|
||||
void UART_EnableFlowCtrl(UART_T* uart )
|
||||
{
|
||||
uart->MODEM |= UART_MODEM_RTSACTLV_Msk;
|
||||
uart->MODEM &= ~UART_MODEM_RTS_Msk;
|
||||
uart->MODEMSTS |= UART_MODEMSTS_CTSACTLV_Msk;
|
||||
uart->INTEN |= UART_INTEN_ATORTSEN_Msk | UART_INTEN_ATOCTSEN_Msk;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief The function is used to enable UART specified interrupt and disable NVIC UART IRQ.
|
||||
*
|
||||
* @param[in] uart The base address of UART module.
|
||||
* @param[in] u32InterruptFlag The specified interrupt of UART module:
|
||||
* - \ref UART_INTEN_TOCNTEN_Msk : Rx Time Out interrupt
|
||||
* - \ref UART_INTEN_WKCTSIEN_Msk : Wakeup interrupt
|
||||
* - \ref UART_INTEN_BUFERRIEN_Msk : Buffer Error interrupt
|
||||
* - \ref UART_INTEN_RXTOIEN_Msk : Rx time-out interrupt
|
||||
* - \ref UART_INTEN_MODEMIEN_Msk : Modem interrupt
|
||||
* - \ref UART_INTEN_RLSIEN_Msk : Rx Line status interrupt
|
||||
* - \ref UART_INTEN_THREIEN_Msk : Tx empty interrupt
|
||||
* - \ref UART_INTEN_RDAIEN_Msk : Rx ready interrupt
|
||||
*
|
||||
* @return None
|
||||
*/
|
||||
void UART_EnableInt(UART_T* uart, uint32_t u32InterruptFlag )
|
||||
{
|
||||
uart->INTEN |= u32InterruptFlag;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief This function use to enable UART function and set baud-rate.
|
||||
*
|
||||
* @param[in] uart The base address of UART module.
|
||||
* @param[in] u32baudrate The baudrate of UART module.
|
||||
*
|
||||
* @return None
|
||||
*/
|
||||
void UART_Open(UART_T* uart, uint32_t u32baudrate)
|
||||
{
|
||||
uint8_t u8UartClkSrcSel;
|
||||
uint32_t u32Clk = 0;
|
||||
uint32_t u32ClkDiv = 0;
|
||||
uint32_t u32Baud_Div;
|
||||
|
||||
u8UartClkSrcSel = (CLK->CLKSEL1 & CLK_CLKSEL1_UARTSEL_Msk) >> CLK_CLKSEL1_UARTSEL_Pos;
|
||||
uart->FUNSEL = UART_FUNC_SEL_UART;
|
||||
uart->LINE = UART_WORD_LEN_8 | UART_PARITY_NONE | UART_STOP_BIT_1;
|
||||
uart->FIFO = UART_FIFO_RFITL_1BYTE | UART_FIFO_RTSTRGLV_1BYTE;
|
||||
|
||||
if(u8UartClkSrcSel == 0)
|
||||
u32Clk = __XTAL;
|
||||
else if(u8UartClkSrcSel == 1)
|
||||
u32Clk = CLK_GetPLLClockFreq();
|
||||
else if(u8UartClkSrcSel >= 2)
|
||||
u32Clk = __HSI;
|
||||
|
||||
u32ClkDiv = ( (CLK->CLKDIV & CLK_CLKDIV_UARTDIV_Msk) >> CLK_CLKDIV_UARTDIV_Pos );
|
||||
u32Clk = u32Clk/(u32ClkDiv + 1);
|
||||
|
||||
if(u32baudrate != 0) {
|
||||
u32Baud_Div = UART_BAUD_MODE2_DIVIDER(u32Clk, u32baudrate);
|
||||
|
||||
if(u32Baud_Div > 0xFFFF)
|
||||
uart->BAUD = (UART_BAUD_MODE0 | UART_BAUD_MODE0_DIVIDER(u32Clk, u32baudrate));
|
||||
else
|
||||
uart->BAUD = (UART_BAUD_MODE2 | u32Baud_Div);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief The function is used to read Rx data from RX FIFO and the data will be stored in pu8RxBuf.
|
||||
*
|
||||
* @param[in] uart The base address of UART module.
|
||||
* @param[in] pu8RxBuf The buffer to receive the data of receive FIFO.
|
||||
* @param[in] u32ReadBytes The the read bytes number of data.
|
||||
*
|
||||
* @return u32Count: Receive byte count
|
||||
*
|
||||
*/
|
||||
uint32_t UART_Read(UART_T* uart, uint8_t *pu8RxBuf, uint32_t u32ReadBytes)
|
||||
{
|
||||
uint32_t u32Count, u32delayno;
|
||||
|
||||
for(u32Count=0; u32Count < u32ReadBytes; u32Count++) {
|
||||
u32delayno = 0;
|
||||
|
||||
while(uart->FIFOSTS & UART_FIFOSTS_RXEMPTY_Msk) { /* Check RX empty => failed */
|
||||
u32delayno++;
|
||||
if( u32delayno >= 0x40000000 )
|
||||
return FALSE;
|
||||
}
|
||||
pu8RxBuf[u32Count] = uart->DAT; /* Get Data from UART RX */
|
||||
}
|
||||
|
||||
return u32Count;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief This function use to config UART line setting.
|
||||
*
|
||||
* @param[in] uart The base address of UART module.
|
||||
* @param[in] u32baudrate The register value of baudrate of UART module.
|
||||
* if u32baudrate = 0, UART baudrate will not change.
|
||||
* @param[in] u32data_width The data length of UART module.
|
||||
* @param[in] u32parity The parity setting (odd/even/none) of UART module.
|
||||
* @param[in] u32stop_bits The stop bit length (1/1.5 bit) of UART module.
|
||||
*
|
||||
* @return None
|
||||
*/
|
||||
void UART_SetLine_Config(UART_T* uart, uint32_t u32baudrate, uint32_t u32data_width, uint32_t u32parity, uint32_t u32stop_bits)
|
||||
{
|
||||
uint8_t u8UartClkSrcSel;
|
||||
uint32_t u32Clk = 0;
|
||||
uint32_t u32ClkDiv = 0;
|
||||
uint32_t u32Baud_Div = 0;
|
||||
|
||||
u8UartClkSrcSel = (CLK->CLKSEL1 & CLK_CLKSEL1_UARTSEL_Msk) >> CLK_CLKSEL1_UARTSEL_Pos;
|
||||
|
||||
if(u8UartClkSrcSel == 0)
|
||||
u32Clk = __XTAL;
|
||||
else if(u8UartClkSrcSel == 1)
|
||||
u32Clk = CLK_GetPLLClockFreq();
|
||||
else if(u8UartClkSrcSel >= 2)
|
||||
u32Clk = __HSI;
|
||||
|
||||
u32ClkDiv = ( (CLK->CLKDIV & CLK_CLKDIV_UARTDIV_Msk) >> CLK_CLKDIV_UARTDIV_Pos );
|
||||
u32Clk = u32Clk/(u32ClkDiv + 1);
|
||||
|
||||
if(u32baudrate != 0) {
|
||||
u32Baud_Div = UART_BAUD_MODE2_DIVIDER(u32Clk, u32baudrate);
|
||||
|
||||
if(u32Baud_Div > 0xFFFF)
|
||||
uart->BAUD = (UART_BAUD_MODE0 | UART_BAUD_MODE0_DIVIDER(u32Clk, u32baudrate));
|
||||
else
|
||||
uart->BAUD = (UART_BAUD_MODE2 | u32Baud_Div);
|
||||
}
|
||||
|
||||
uart->LINE = u32data_width | u32parity | u32stop_bits;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief This function use to set Rx timeout count.
|
||||
*
|
||||
* @param[in] uart The base address of UART module.
|
||||
* @param[in] u32TOC Rx timeout counter.
|
||||
*
|
||||
* @return None
|
||||
*/
|
||||
void UART_SetTimeoutCnt(UART_T* uart, uint32_t u32TOC)
|
||||
{
|
||||
uart->TOUT = (uart->TOUT & ~UART_TOUT_TOIC_Msk)| (u32TOC);
|
||||
uart->INTEN |= UART_INTEN_TOCNTEN_Msk;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief The function is used to configure IrDA relative settings. It consists of TX or RX mode and baudrate.
|
||||
*
|
||||
* @param[in] uart The base address of UART module.
|
||||
* @param[in] u32Buadrate The baudrate of UART module.
|
||||
* @param[in] u32Direction The direction(transmit:1/receive:0) of UART module in IrDA mode.
|
||||
*
|
||||
* @return None
|
||||
*/
|
||||
void UART_SelectIrDAMode(UART_T* uart, uint32_t u32Buadrate, uint32_t u32Direction)
|
||||
{
|
||||
uint8_t u8UartClkSrcSel;
|
||||
uint32_t u32Clk = 0;
|
||||
uint32_t u32ClkDiv = 0;
|
||||
|
||||
u8UartClkSrcSel = (CLK->CLKSEL1 & CLK_CLKSEL1_UARTSEL_Msk) >> CLK_CLKSEL1_UARTSEL_Pos;
|
||||
|
||||
if(u8UartClkSrcSel == 0)
|
||||
u32Clk = __XTAL;
|
||||
else if(u8UartClkSrcSel == 1)
|
||||
u32Clk = CLK_GetPLLClockFreq();
|
||||
else if(u8UartClkSrcSel >= 2)
|
||||
u32Clk = __HSI;
|
||||
|
||||
u32ClkDiv = ( (CLK->CLKDIV & CLK_CLKDIV_UARTDIV_Msk) >> CLK_CLKDIV_UARTDIV_Pos );
|
||||
u32Clk = u32Clk/(u32ClkDiv + 1);
|
||||
|
||||
uart->BAUD = UART_BAUD_MODE0 | UART_BAUD_MODE0_DIVIDER(u32Clk, u32Buadrate);
|
||||
|
||||
uart->IRDA &= ~UART_IRDA_TXINV_Msk;
|
||||
uart->IRDA |= UART_IRDA_RXINV_Msk;
|
||||
uart->IRDA = u32Direction ? uart->IRDA | UART_IRDA_TXEN_Msk : uart->IRDA &~ UART_IRDA_TXEN_Msk;
|
||||
uart->FUNSEL = (0x2 << UART_FUNSEL_FUN_SEL_Pos);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief The function is used to set RS485 relative setting.
|
||||
*
|
||||
* @param[in] uart The base address of UART module.
|
||||
* @param[in] u32Mode The operation mode(NMM/AUD/AAD).
|
||||
* @param[in] u32Addr The RS485 address.
|
||||
*
|
||||
* @return None
|
||||
*/
|
||||
void UART_SelectRS485Mode(UART_T* uart, uint32_t u32Mode, uint32_t u32Addr)
|
||||
{
|
||||
uart->FUNSEL = UART_FUNC_SEL_RS485;
|
||||
uart->ALTCTL = 0;
|
||||
uart->ALTCTL |= u32Mode | (u32Addr << UART_ALTCTL_ADDRMV_Pos);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief The function is to write data into TX buffer to transmit data by UART.
|
||||
*
|
||||
* @param[in] uart The base address of UART module.
|
||||
* @param[in] pu8TxBuf The buffer to send the data to UART transmission FIFO.
|
||||
* @param[in] u32WriteBytes The byte number of data.
|
||||
*
|
||||
* @return u32Count: transfer byte count
|
||||
*/
|
||||
uint32_t UART_Write(UART_T* uart,uint8_t *pu8TxBuf, uint32_t u32WriteBytes)
|
||||
{
|
||||
uint32_t u32Count, u32delayno;
|
||||
|
||||
for(u32Count=0; u32Count != u32WriteBytes; u32Count++) {
|
||||
u32delayno = 0;
|
||||
while((uart->FIFOSTS & UART_FIFOSTS_TXEMPTYF_Msk) == 0) { /* Wait Tx empty and Time-out manner */
|
||||
u32delayno++;
|
||||
if( u32delayno >= 0x40000000 )
|
||||
return FALSE;
|
||||
}
|
||||
uart->DAT = pu8TxBuf[u32Count]; /* Send UART Data from buffer */
|
||||
}
|
||||
|
||||
return u32Count;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*@}*/ /* end of group Mini58_UART_EXPORTED_FUNCTIONS */
|
||||
|
||||
/*@}*/ /* end of group Mini58_UART_Driver */
|
||||
|
||||
/*@}*/ /* end of group Mini58_Device_Driver */
|
||||
|
||||
/*** (C) COPYRIGHT 2012 Nuvoton Technology Corp. ***/
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,100 @@
|
||||
/**************************************************************************//**
|
||||
* @file wdt.c
|
||||
* @version V1.00
|
||||
* $Revision: 3 $
|
||||
* $Date: 15/05/28 1:16p $
|
||||
* @brief Mini58 series WDT driver source file
|
||||
*
|
||||
* @note
|
||||
* Copyright (C) 2015 Nuvoton Technology Corp. All rights reserved.
|
||||
*****************************************************************************/
|
||||
#include "Mini58Series.h"
|
||||
|
||||
/** @addtogroup Mini58_Device_Driver Mini58 Device Driver
|
||||
@{
|
||||
*/
|
||||
|
||||
/** @addtogroup Mini58_WDT_Driver WDT Driver
|
||||
@{
|
||||
*/
|
||||
|
||||
|
||||
/** @addtogroup Mini58_WDT_EXPORTED_FUNCTIONS WDT Exported Functions
|
||||
@{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief This function make WDT module start counting with different time-out interval
|
||||
* @param[in] u32TimeoutInterval Time-out interval period of WDT module. Valid values are:
|
||||
* - \ref WDT_TIMEOUT_2POW4
|
||||
* - \ref WDT_TIMEOUT_2POW6
|
||||
* - \ref WDT_TIMEOUT_2POW8
|
||||
* - \ref WDT_TIMEOUT_2POW10
|
||||
* - \ref WDT_TIMEOUT_2POW12
|
||||
* - \ref WDT_TIMEOUT_2POW14
|
||||
* - \ref WDT_TIMEOUT_2POW16
|
||||
* - \ref WDT_TIMEOUT_2POW18
|
||||
* @param[in] u32ResetDelay Reset delay period while WDT time-out happened. Valid values are:
|
||||
* - \ref WDT_RESET_DELAY_3CLK
|
||||
* - \ref WDT_RESET_DELAY_18CLK
|
||||
* - \ref WDT_RESET_DELAY_130CLK
|
||||
* - \ref WDT_RESET_DELAY_1026CLK
|
||||
* @param[in] u32EnableReset Enable WDT reset system function. Valid values are TRUE and FALSE
|
||||
* @param[in] u32EnableWakeup Enable WDT wake-up system function. Valid values are TRUE and FALSE
|
||||
* @return None
|
||||
*/
|
||||
void WDT_Open(uint32_t u32TimeoutInterval,
|
||||
uint32_t u32ResetDelay,
|
||||
uint32_t u32EnableReset,
|
||||
uint32_t u32EnableWakeup)
|
||||
{
|
||||
|
||||
WDT->CTL = u32TimeoutInterval | WDT_CTL_WDTEN_Msk |
|
||||
(u32EnableReset << WDT_CTL_RSTEN_Pos) |
|
||||
(u32EnableWakeup << WDT_CTL_WKEN_Pos);
|
||||
WDT->ALTCTL = u32ResetDelay;
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function stops WDT counting and disable WDT module
|
||||
* @param None
|
||||
* @return None
|
||||
*/
|
||||
void WDT_Close(void)
|
||||
{
|
||||
WDT->CTL = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function enables the WDT time-out interrupt
|
||||
* @param None
|
||||
* @return None
|
||||
*/
|
||||
void WDT_EnableInt(void)
|
||||
{
|
||||
WDT->CTL = (WDT->CTL & ~(WDT_CTL_IF_Msk | WDT_CTL_WKF_Msk | WDT_CTL_RSTF_Msk)) | WDT_CTL_INTEN_Msk;
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function disables the WDT time-out interrupt
|
||||
* @param None
|
||||
* @return None
|
||||
*/
|
||||
void WDT_DisableInt(void)
|
||||
{
|
||||
WDT->CTL &= ~(WDT_CTL_IF_Msk | WDT_CTL_WKF_Msk | WDT_CTL_RSTF_Msk | WDT_CTL_INTEN_Msk);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*@}*/ /* end of group Mini58_WDT_EXPORTED_FUNCTIONS */
|
||||
|
||||
/*@}*/ /* end of group Mini58_WDT_Driver */
|
||||
|
||||
/*@}*/ /* end of group Mini58_Device_Driver */
|
||||
|
||||
/*** (C) COPYRIGHT 2015 Nuvoton Technology Corp. ***/
|
||||
@@ -0,0 +1,68 @@
|
||||
/**************************************************************************//**
|
||||
* @file wwdt.c
|
||||
* @version V1.00
|
||||
* $Revision: 1 $
|
||||
* $Date: 15/02/02 3:19p $
|
||||
* @brief Mini58 series WWDT driver source file
|
||||
*
|
||||
* @note
|
||||
* Copyright (C) 2015 Nuvoton Technology Corp. All rights reserved.
|
||||
*****************************************************************************/
|
||||
#include "mini58Series.h"
|
||||
|
||||
/** @addtogroup Mini58_Device_Driver Mini58 Device Driver
|
||||
@{
|
||||
*/
|
||||
|
||||
/** @addtogroup Mini58_WWDT_Driver WWDT Driver
|
||||
@{
|
||||
*/
|
||||
|
||||
|
||||
/** @addtogroup Mini58_WWDT_EXPORTED_FUNCTIONS WWDT Exported Functions
|
||||
@{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief This function make WWDT module start counting with different counter period and compared window value
|
||||
* @param[in] u32PreScale Prescale period for the WWDT counter period. Valid values are:
|
||||
* - \ref WWDT_PRESCALER_1
|
||||
* - \ref WWDT_PRESCALER_2
|
||||
* - \ref WWDT_PRESCALER_4
|
||||
* - \ref WWDT_PRESCALER_8
|
||||
* - \ref WWDT_PRESCALER_16
|
||||
* - \ref WWDT_PRESCALER_32
|
||||
* - \ref WWDT_PRESCALER_64
|
||||
* - \ref WWDT_PRESCALER_128
|
||||
* - \ref WWDT_PRESCALER_192
|
||||
* - \ref WWDT_PRESCALER_256
|
||||
* - \ref WWDT_PRESCALER_384
|
||||
* - \ref WWDT_PRESCALER_512
|
||||
* - \ref WWDT_PRESCALER_768
|
||||
* - \ref WWDT_PRESCALER_1024
|
||||
* - \ref WWDT_PRESCALER_1536
|
||||
* - \ref WWDT_PRESCALER_2048
|
||||
* @param[in] u32CmpValue Window compared value. Valid values are between 0x0 to 0x3F
|
||||
* @param[in] u32EnableInt Enable WWDT interrupt or not. Valid values are \ref TRUE and \ref FALSE
|
||||
* @return None
|
||||
* @note Application can call this function can only once after boot up
|
||||
*/
|
||||
void WWDT_Open(uint32_t u32PreScale, uint32_t u32CmpValue, uint32_t u32EnableInt)
|
||||
{
|
||||
WWDT->CTL = u32PreScale |
|
||||
(u32CmpValue << WWDT_CTL_CMPDAT_Pos)|
|
||||
WWDT_CTL_WWDTEN_Msk |
|
||||
(u32EnableInt ? WWDT_CTL_INTEN_Msk : 0);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/*@}*/ /* end of group Mini58_WWDT_EXPORTED_FUNCTIONS */
|
||||
|
||||
/*@}*/ /* end of group Mini58_WWDT_Driver */
|
||||
|
||||
/*@}*/ /* end of group Mini58_Device_Driver */
|
||||
|
||||
/*** (C) COPYRIGHT 2015 Nuvoton Technology Corp. ***/
|
||||
Reference in New Issue
Block a user