/** * @brief Get the actual frequency of SPI bus clock. Only available in Master mode. * @param 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; /* Get DIVIDER setting */ u32Div = (spi->DIVIDER & SPI_DIVIDER_DIVIDER_Msk) >> SPI_DIVIDER_DIVIDER_Pos; /* Check clock source of SPI */ if(spi == SPI0) { if((CLK->CLKSEL1 & CLK_CLKSEL1_SPI0_S_Msk) == CLK_CLKSEL1_SPI0_S_HCLK) u32ClkSrc = CLK_GetHCLKFreq(); else u32ClkSrc = CLK_GetPLLClockFreq(); } else { if((CLK->CLKSEL1 & CLK_CLKSEL1_SPI1_S_Msk) == CLK_CLKSEL1_SPI1_S_HCLK) u32ClkSrc = CLK_GetHCLKFreq(); else u32ClkSrc = CLK_GetPLLClockFreq(); } if(spi->CNTRL2 & SPI_CNTRL2_BCn_Msk) /* BCn = 1: f_spi = f_spi_clk_src / (DIVIDER + 1) */ { /* Return SPI bus clock rate */ return (u32ClkSrc / (u32Div + 1)); } else /* BCn = 0: f_spi = f_spi_clk_src / ((DIVIDER + 1) * 2) */ { /* Return SPI bus clock rate */ return (u32ClkSrc / ((u32Div + 1) * 2)); } }
/** * @brief Set UART line configuration * * @param[in] uart The pointer of the specified 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. * - UART_WORD_LEN_5 * - UART_WORD_LEN_6 * - UART_WORD_LEN_7 * - UART_WORD_LEN_8 * @param[in] u32parity The parity setting (none/odd/even/mark/space) of UART module. * - UART_PARITY_NONE * - UART_PARITY_ODD * - UART_PARITY_EVEN * - UART_PARITY_MARK * - UART_PARITY_SPACE * @param[in] u32stop_bits The stop bit length (1/1.5/2 bit) of UART module. * - UART_STOP_BIT_1 * - UART_STOP_BIT_1_5 * - UART_STOP_BIT_2 * * @return None * * @details This function use to config UART line setting. */ void UART_SetLine_Config(UART_T* uart, uint32_t u32baudrate, uint32_t u32data_width, uint32_t u32parity, uint32_t u32stop_bits) { uint8_t u8UartClkSrcSel, u8UartClkDivNum; uint32_t u32ClkTbl[4] = {__HXT, 0, 0, __HIRC}; uint32_t u32Baud_Div = 0; /* Get UART clock source selection */ u8UartClkSrcSel = (CLK->CLKSEL1 & CLK_CLKSEL1_UART_S_Msk) >> CLK_CLKSEL1_UART_S_Pos; /* Get UART clock divider number */ u8UartClkDivNum = (CLK->CLKDIV & CLK_CLKDIV_UART_N_Msk) >> CLK_CLKDIV_UART_N_Pos; /* Get PLL clock frequency if UART clock source selection is PLL */ if(u8UartClkSrcSel == 1) u32ClkTbl[u8UartClkSrcSel] = CLK_GetPLLClockFreq(); /* Set UART baud rate */ if(u32baudrate != 0) { u32Baud_Div = UART_BAUD_MODE2_DIVIDER((u32ClkTbl[u8UartClkSrcSel]) / (u8UartClkDivNum + 1), u32baudrate); if(u32Baud_Div > 0xFFFF) uart->BAUD = (UART_BAUD_MODE0 | UART_BAUD_MODE0_DIVIDER((u32ClkTbl[u8UartClkSrcSel]) / (u8UartClkDivNum + 1), u32baudrate)); else uart->BAUD = (UART_BAUD_MODE2 | u32Baud_Div); } /* Set UART line configuration */ uart->LCR = u32data_width | u32parity | u32stop_bits; }
/** * @brief Update the Variable SystemCoreClock * * @param None * * @return None * * @details This function is used to update the variable SystemCoreClock * and must be called whenever the core clock is changed. */ void SystemCoreClockUpdate(void) { uint32_t u32Freq, u32ClkSrc; uint32_t u32HclkDiv; u32ClkSrc = CLK->CLKSEL0 & CLK_CLKSEL0_HCLK_S_Msk; /* Update PLL Clock */ PllClock = CLK_GetPLLClockFreq(); if(u32ClkSrc != CLK_CLKSEL0_HCLK_S_PLL) { /* Use the clock sources directly */ u32Freq = gau32ClkSrcTbl[u32ClkSrc]; } else { /* Use PLL clock */ u32Freq = PllClock; } u32HclkDiv = (CLK->CLKDIV & CLK_CLKDIV_HCLK_N_Msk) + 1; /* Update System Core Clock */ SystemCoreClock = u32Freq / u32HclkDiv; CyclesPerUs = (SystemCoreClock + 500000) / 1000000; }
/** * @brief Get current HCLK clock frquency. * @param None. * @return HCLK clock frquency. The clock UNIT is in Hz. */ uint32_t DrvSYS_GetHCLKFreq(void) { uint32_t u32Freqout, u32AHBDivider, u32ClkSel; u32ClkSel = CLK->CLKSEL0 & CLK_CLKSEL0_HCLK_S_Msk; if (u32ClkSel == CLK_HCLK_HXT) /* external HXT crystal clock */ { u32Freqout = __XTAL; } else if((u32ClkSel == CLK_HCLK_PLL) || (u32ClkSel == CLK_HCLK_PLL_2)) /* PLL clock */ { u32Freqout = CLK_GetPLLClockFreq(); if(u32ClkSel == CLK_HCLK_PLL_2) u32Freqout /= 2; } else if(u32ClkSel == CLK_HCLK_LIRC) /* internal LIRC oscillator clock */ { u32Freqout = __IRC10K; } else /* internal HIRC oscillator clock */ { u32Freqout = __IRC22M; } u32AHBDivider = (CLK->CLKDIV & CLK_CLKDIV_HCLK_N_Msk) + 1 ; return (u32Freqout/u32AHBDivider); }
//========================================================================= __myevic__ void SetPWMClock() { uint32_t clk; if ( gFlags.pwm_pll ) { clk = CLK_CLKSEL2_PWM0SEL_PLL; PWMCycles = CLK_GetPLLClockFreq() / BBC_PWM_FREQ; } else { clk = CLK_CLKSEL2_PWM0SEL_PCLK0; PWMCycles = CLK_GetPCLK0Freq() / BBC_PWM_FREQ; } MaxDuty = PWMCycles - 1; MinBuck = PWMCycles / 48; MaxBoost = PWMCycles / 12; ProbeDuty = PWMCycles / 8; BoostWindow = PWMCycles / 19; #define MaxBuck MaxDuty #define MinBoost MaxDuty if ( ISCUBO200 || ISRX200S || ISRX23 || ISRX300 ) { MaxDuty = 95 * PWMCycles / 100; } CLK_EnableModuleClock( PWM0_MODULE ); CLK_SetModuleClock( PWM0_MODULE, clk, 0 ); SYS_ResetModule( PWM0_RST ); }
uint32_t PWM_ConfigOutputChannelf(PWM_T *pwm, uint32_t u32ChannelNum, uint32_t u32Frequency, float u32DutyCycle) { uint32_t u32Src; uint32_t u32PWMClockSrc; uint32_t i; uint16_t u16Prescale = 1, u16CNR = 0xFFFF; if(pwm == PWM0) u32Src = CLK->CLKSEL2 & CLK_CLKSEL2_PWM0SEL_Msk; else//(pwm == PWM1) u32Src = CLK->CLKSEL2 & CLK_CLKSEL2_PWM1SEL_Msk; if(u32Src == 0) { //clock source is from PLL clock u32PWMClockSrc = CLK_GetPLLClockFreq(); } else { //clock source is from PCLK SystemCoreClockUpdate(); u32PWMClockSrc = SystemCoreClock; } for(u16Prescale = 1; u16Prescale < 0xFFF; u16Prescale++) { i = (u32PWMClockSrc / u32Frequency) / u16Prescale; if(i > (0x10000)) continue; u16CNR = i; break; } i = u32PWMClockSrc / ((u16Prescale + 1) * u16CNR); PWM_SET_PRESCALER(pwm, u32ChannelNum, --u16Prescale); /* Set Counter to upcount */ (pwm)->CTL1 = ((pwm)->CTL1 & ~(PWM_CTL1_CNTTYPE0_Msk << (2 * u32ChannelNum))) | (0UL << (2 * u32ChannelNum)); (pwm)->CTL1 &= ~(PWM_CTL1_CNTMODE0_Msk << u32ChannelNum); if(u32DutyCycle == 100) { PWM_SET_CMR(pwm, u32ChannelNum, u16CNR); PWM_SET_CNR(pwm, u32ChannelNum, --u16CNR); } else { PWM_SET_CMR(pwm, u32ChannelNum, (uint32_t)(u32DutyCycle * (u16CNR + 1) / 100 - 1)); PWM_SET_CNR(pwm, u32ChannelNum, --u16CNR); } (pwm)->WGCTL0 = ((pwm)->WGCTL0 & ~(PWM_WGCTL0_ZPCTL0_Msk << (u32ChannelNum * 2 + PWM_WGCTL0_ZPCTL0_Msk))) | (PWM_OUTPUT_HIGH << (u32ChannelNum * 2 + PWM_WGCTL0_ZPCTL0_Pos)); (pwm)->WGCTL1 = ((pwm)->WGCTL1 & ~(PWM_WGCTL1_CMPUCTL0_Msk << (u32ChannelNum * 2 + PWM_WGCTL1_CMPUCTL0_Pos))) | (PWM_OUTPUT_LOW << (u32ChannelNum * 2 + PWM_WGCTL1_CMPUCTL0_Pos)); return(i); }
/** * @brief Select and configure IrDA function * * @param[in] uart The pointer of the specified UART module. * @param[in] u32Buadrate The baudrate of UART module. * @param[in] u32Direction The direction of UART module in IrDA mode: * - \ref UART_IRDA_TXEN * - \ref UART_IRDA_RXEN * * @return None * * @details The function is used to configure IrDA relative settings. It consists of TX or RX mode and baudrate. */ void UART_SelectIrDAMode(UART_T* uart, uint32_t u32Buadrate, uint32_t u32Direction) { uint8_t u8UartClkSrcSel, u8UartClkDivNum; uint32_t u32ClkTbl[4] = {__HXT, 0, __HIRC, __HIRC}; uint32_t u32Baud_Div; /* Select IrDA function mode */ uart->FUNCSEL = UART_FUNCSEL_IrDA; /* Get UART clock source selection */ u8UartClkSrcSel = (CLK->CLKSEL1 & CLK_CLKSEL1_UARTSEL_Msk) >> CLK_CLKSEL1_UARTSEL_Pos; /* Get UART clock divider number */ u8UartClkDivNum = (CLK->CLKDIV0 & CLK_CLKDIV0_UARTDIV_Msk) >> CLK_CLKDIV0_UARTDIV_Pos; /* Get PLL clock frequency if UART clock source selection is PLL */ if(u8UartClkSrcSel == 1) u32ClkTbl[u8UartClkSrcSel] = CLK_GetPLLClockFreq(); /* Set UART IrDA baud rate in mode 0 */ if(u32Buadrate != 0) { u32Baud_Div = UART_BAUD_MODE0_DIVIDER((u32ClkTbl[u8UartClkSrcSel]) / (u8UartClkDivNum + 1), u32Buadrate); if(u32Baud_Div < 0xFFFF) uart->BAUD = (UART_BAUD_MODE0 | u32Baud_Div); } /* Configure IrDA relative settings */ if(u32Direction == UART_IRDA_RXEN) { uart->IRDA |= UART_IRDA_RXINV_Msk; //Rx signal is inverse uart->IRDA &= ~UART_IRDA_TXEN_Msk; } else { uart->IRDA &= ~UART_IRDA_TXINV_Msk; //Tx signal is not inverse uart->IRDA |= UART_IRDA_TXEN_Msk; } }
/** * @brief This function set PLL frequency * @param u32PllClkSrc is PLL clock source. Including : * - \ref CLK_PLLCTL_PLL_SRC_HIRC * - \ref CLK_PLLCTL_PLL_SRC_HXT * @param u32PllFreq is PLL frequency * @return None */ uint32_t CLK_EnablePLL(uint32_t u32PllClkSrc, uint32_t u32PllFreq) { uint32_t u32PllCr,u32PLL_N,u32PLL_M,u32PLLReg; if ( u32PllFreq < FREQ_16MHZ) u32PllFreq=FREQ_16MHZ; else if(u32PllFreq > FREQ_32MHZ) u32PllFreq=FREQ_32MHZ; if(u32PllClkSrc == CLK_PLLCTL_PLL_SRC_HIRC) { /* PLL source clock from HXT */ CLK->PLLCTL |= CLK_PLLCTL_PLL_SRC_HIRC; u32PllCr = __HXT; } else { /* PLL source clock from HIRC */ CLK->PLLCTL &= ~CLK_PLLCTL_PLL_SRC_HIRC; if(CLK->PWRCTL & CLK_PWRCTL_HIRC_FSEL_Msk) u32PllCr =__HIRC16M; else u32PllCr =__HIRC12M; } u32PLL_N=u32PllCr/1000000; u32PLL_M=u32PllFreq/1000000; while(1) { if(u32PLL_M<=32 && u32PLL_N<=16 ) break; u32PLL_M >>=1; u32PLL_N >>=1; } u32PLLReg = (u32PLL_M<<CLK_PLLCTL_PLL_MLP_Pos) | ((u32PLL_N-1)<<CLK_PLLCTL_PLL_SRC_N_Pos); CLK->PLLCTL = ( CLK->PLLCTL & ~(CLK_PLLCTL_PLL_MLP_Msk | CLK_PLLCTL_PLL_SRC_N_Msk ) )| u32PLLReg; if(u32PllClkSrc==CLK_PLLCTL_PLL_SRC_HIRC) CLK->PLLCTL = (CLK->PLLCTL & ~CLK_PLLCTL_PLL_SRC_HIRC) | (CLK_PLLCTL_PLL_SRC_HIRC); else CLK->PLLCTL = (CLK->PLLCTL & ~CLK_PLLCTL_PLL_SRC_HIRC); CLK->PLLCTL &= ~CLK_PLLCTL_PD_Msk; return CLK_GetPLLClockFreq(); }
/** * @brief Open and set UART function * * @param[in] uart The pointer of the specified UART module. * @param[in] u32baudrate The baudrate of UART module. * * @return None * * @details This function use to enable UART function and set baud-rate. */ void UART_Open(UART_T* uart, uint32_t u32baudrate) { uint8_t u8UartClkSrcSel, u8UartClkDivNum; uint32_t u32ClkTbl[4] = {__HXT, 0, 0, __HIRC}; uint32_t u32Baud_Div = 0; /* Get UART clock source selection */ u8UartClkSrcSel = (CLK->CLKSEL1 & CLK_CLKSEL1_UART_S_Msk) >> CLK_CLKSEL1_UART_S_Pos; /* Get UART clock divider number */ u8UartClkDivNum = (CLK->CLKDIV & CLK_CLKDIV_UART_N_Msk) >> CLK_CLKDIV_UART_N_Pos; /* Select UART function */ uart->FUN_SEL = UART_FUNC_SEL_UART; /* Set UART line configuration */ uart->LCR = UART_WORD_LEN_8 | UART_PARITY_NONE | UART_STOP_BIT_1; /* Set UART Rx and RTS trigger level */ uart->FCR &= ~(UART_FCR_RFITL_Msk | UART_FCR_RTS_TRI_LEV_Msk); /* Get PLL clock frequency if UART clock source selection is PLL */ if(u8UartClkSrcSel == 1) u32ClkTbl[u8UartClkSrcSel] = CLK_GetPLLClockFreq(); /* Set UART baud rate */ if(u32baudrate != 0) { u32Baud_Div = UART_BAUD_MODE2_DIVIDER((u32ClkTbl[u8UartClkSrcSel]) / (u8UartClkDivNum + 1), u32baudrate); if(u32Baud_Div > 0xFFFF) uart->BAUD = (UART_BAUD_MODE0 | UART_BAUD_MODE0_DIVIDER((u32ClkTbl[u8UartClkSrcSel]) / (u8UartClkDivNum + 1), u32baudrate)); else uart->BAUD = (UART_BAUD_MODE2 | u32Baud_Div); } }
/** * @brief Set PLL frequency * @param[in] u32PllClkSrc is PLL clock source. Including : * - \ref CLK_PLLCON_PLL_SRC_HXT * - \ref CLK_PLLCON_PLL_SRC_HIRC * @param[in] u32PllFreq is PLL frequency * @return PLL frequency * @details This function is used to configure PLLCON 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; uint32_t u32Tmp, u32Tmp2, u32Tmp3, u32Min, u32MinNF, u32MinNR; /* Disable PLL first to avoid unstable when setting PLL. */ CLK->PLLCON = CLK_PLLCON_PD_Msk; /* PLL source clock is from HXT */ if(u32PllClkSrc == CLK_PLLCON_PLL_SRC_HXT) { /* Enable HXT clock */ CLK->PWRCON |= CLK_PWRCON_XTL12M_EN_Msk; /* Wait for HXT clock ready */ CLK_WaitClockReady(CLK_CLKSTATUS_XTL12M_STB_Msk); /* Select PLL source clock from HXT */ u32CLK_SRC = CLK_PLLCON_PLL_SRC_HXT; u32PllSrcClk = __HXT; /* u32NR start from 2 */ u32NR = 2; } /* PLL source clock is from HIRC */ else { /* Enable HIRC clock */ CLK->PWRCON |= CLK_PWRCON_OSC22M_EN_Msk; /* Wait for HIRC clock ready */ CLK_WaitClockReady(CLK_CLKSTATUS_OSC22M_STB_Msk); /* Select PLL source clock from HIRC */ u32CLK_SRC = CLK_PLLCON_PLL_SRC_HIRC; u32PllSrcClk = __HIRC; /* u32NR start from 4 when FIN = 22.1184MHz to avoid calculation overflow */ u32NR = 4; } /* Select "NO" according to request frequency */ if((u32PllFreq <= FREQ_200MHZ) && (u32PllFreq > FREQ_100MHZ)) { u32NO = 0; } 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 <= 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) break; } } } } } /* Enable and apply new PLL setting. */ CLK->PLLCON = u32CLK_SRC | (u32NO << 14) | ((u32MinNR - 2) << 9) | (u32MinNF - 2); /* Waiting for PLL clock stable */ CLK_WaitClockReady(CLK_CLKSTATUS_PLL_STB_Msk); /* Return actual PLL output clock frequency */ return u32PllSrcClk / ((u32NO + 1) * u32MinNR) * u32MinNF; lexit: /* Apply default PLL setting and return */ if(u32PllClkSrc == CLK_PLLCON_PLL_SRC_HXT) CLK->PLLCON = 0xC22E; /* 48MHz */ else CLK->PLLCON = 0xD66F; /* 48.06498462MHz */ CLK_WaitClockReady(CLK_CLKSTATUS_PLL_STB_Msk); return CLK_GetPLLClockFreq(); }
/** * @brief This function set PLL frequency * @param u32PllClkSrc is PLL clock source. Including : * - \ref CLK_PLLCON_PLL_SRC_HXT * - \ref CLK_PLLCON_PLL_SRC_HIRC * @param u32PllFreq is PLL frequency * @return PLL frequency */ uint32_t CLK_EnablePLL(uint32_t u32PllClkSrc, uint32_t u32PllFreq) { uint32_t u32PllSrcClk, u32PLLReg, u32NR, u32NF, u32NO; if(u32PllClkSrc == CLK_PLLCON_PLL_SRC_HXT) { /* PLL source clock from HXT */ CLK->PLLCON &= ~CLK_PLLCON_PLL_SRC_Msk; u32PllSrcClk = __HXT; } else { /* PLL source clock from HIRC */ CLK->PLLCON |= CLK_PLLCON_PLL_SRC_Msk; u32PllSrcClk = __HIRC; } if((u32PllFreq <= FREQ_200MHZ) && (u32PllFreq > FREQ_100MHZ)) { u32NO = 0; } 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 { if(u32PllClkSrc == CLK_PLLCON_PLL_SRC_HXT) CLK->PLLCON = 0xC22E; else CLK->PLLCON = 0xD66F; CLK_WaitClockReady(CLK_CLKSTATUS_PLL_STB_Msk); return CLK_GetPLLClockFreq(); } u32NF = u32PllFreq / 1000000; u32NR = u32PllSrcClk / 1000000; while(1) { if((u32NR & 0x01) || (u32NF & 0x01) || (u32NR == 2) || (u32NF == 2)) { break; } else { u32NR >>= 1; u32NF >>= 1; } } u32PLLReg = (u32NO << 14) | ((u32NR - 2) << 9) | (u32NF - 2); CLK->PLLCON = (CLK->PLLCON & ~(CLK_PLLCON_FB_DV_Msk | CLK_PLLCON_IN_DV_Msk | CLK_PLLCON_OUT_DV_Msk)) | u32PLLReg; CLK->PLLCON &= ~(CLK_PLLCON_PD_Msk | CLK_PLLCON_OE_Msk); CLK_WaitClockReady(CLK_CLKSTATUS_PLL_STB_Msk); return ((u32PllSrcClk * u32NF) / (u32NR * (u32NO + 1))); }
/** * @brief Configure BPWM capture and get the nearest unit time. * @param[in] bpwm The pointer of the specified BPWM module * - BPWM0 : BPWM Group 0 * - BPWM1 : BPWM Group 1 * @param[in] u32ChannelNum BPWM channel number. Valid values are between 0~5 * @param[in] u32UnitTimeNsec The unit time of counter * @param[in] u32CaptureEdge The condition to latch the counter. This parameter is not used * @return The nearest unit time in nano second. * @details This function is used to Configure BPWM capture and get the nearest unit time. */ uint32_t BPWM_ConfigCaptureChannel(BPWM_T *bpwm, uint32_t u32ChannelNum, uint32_t u32UnitTimeNsec, uint32_t u32CaptureEdge) { uint32_t u32Src; uint32_t u32PWMClockSrc; uint32_t u32NearestUnitTimeNsec; uint16_t u16Prescale = 1U, u16CNR = 0xFFFFU; if(bpwm == BPWM0) { u32Src = CLK->CLKSEL2 & CLK_CLKSEL2_BPWM0SEL_Msk; } else { /* (bpwm == BPWM1) */ u32Src = CLK->CLKSEL2 & CLK_CLKSEL2_BPWM1SEL_Msk; } if(u32Src == 0U) { /* clock source is from PLL clock */ u32PWMClockSrc = CLK_GetPLLClockFreq(); } else { /* clock source is from PCLK */ SystemCoreClockUpdate(); if(bpwm == BPWM0) { u32PWMClockSrc = CLK_GetPCLK0Freq(); } else {/* (bpwm == BPWM1) */ u32PWMClockSrc = CLK_GetPCLK1Freq(); } } u32PWMClockSrc /= 1000UL; for(u16Prescale = 1U; u16Prescale <= 0x1000U; u16Prescale++) { uint32_t u32Exit = 0U; u32NearestUnitTimeNsec = (1000000UL * u16Prescale) / u32PWMClockSrc; if(u32NearestUnitTimeNsec < u32UnitTimeNsec) { if (u16Prescale == 0x1000U) { /* limit to the maximum unit time(nano second) */ u32Exit = 1U; } else { u32Exit = 0U; } if (!(1000000UL * (u16Prescale + 1UL) > (u32NearestUnitTimeNsec * u32PWMClockSrc))) { u32Exit = 1U; } else { u32Exit = 0U; } } else { u32Exit = 1U; } if (u32Exit == 1U) { break; } else {} } /* convert to real register value */ /* all channels share a prescaler */ u16Prescale -= 1U; BPWM_SET_PRESCALER(bpwm, u32ChannelNum, u16Prescale); /* set BPWM to down count type(edge aligned) */ (bpwm)->CTL1 = (1UL); BPWM_SET_CNR(bpwm, u32ChannelNum, u16CNR); return (u32NearestUnitTimeNsec); }
/** * @brief Set the SPI bus clock. Only available in Master mode. * @param spi is the base address of SPI module. * @param u32BusClock is the expected frequency of SPI bus clock in Hz. * @return Actual frequency of SPI peripheral clock. * @note If u32BusClock = 0, DIVIDER setting will be set to the maximum value. * @note If u32BusClock is larger than system clock rate, the SPI peripheral clock rate will be set to equal to system clock rate. */ uint32_t SPI_SetBusClock(SPI_T *spi, uint32_t u32BusClock) { uint32_t u32ClkSrc; uint32_t u32Div; /* Set BCn = 1: f_spi = f_spi_clk_src / (DIVIDER + 1) */ spi->CNTRL2 |= SPI_CNTRL2_BCn_Msk; /* Check clock source of SPI */ if(spi == SPI0) { if((CLK->CLKSEL1 & CLK_CLKSEL1_SPI0_S_Msk) == CLK_CLKSEL1_SPI0_S_HCLK) u32ClkSrc = CLK_GetHCLKFreq(); else u32ClkSrc = CLK_GetPLLClockFreq(); } else { if((CLK->CLKSEL1 & CLK_CLKSEL1_SPI1_S_Msk) == CLK_CLKSEL1_SPI1_S_HCLK) u32ClkSrc = CLK_GetHCLKFreq(); else u32ClkSrc = CLK_GetPLLClockFreq(); } if(u32BusClock >= u32ClkSrc) { /* Set DIVIDER = 0 */ spi->DIVIDER = 0; /* Return master peripheral clock rate */ return u32ClkSrc; } else if(u32BusClock == 0) { /* Set BCn = 0: f_spi = f_spi_clk_src / ((DIVIDER + 1) * 2) */ spi->CNTRL2 &= (~SPI_CNTRL2_BCn_Msk); /* Set DIVIDER to the maximum value 0xFF */ spi->DIVIDER = (spi->DIVIDER & (~SPI_DIVIDER_DIVIDER_Msk)) | (0xFF << SPI_DIVIDER_DIVIDER_Pos); /* Return master peripheral clock rate */ return (u32ClkSrc / ((0xFF + 1) * 2)); } else { u32Div = (((u32ClkSrc * 10) / u32BusClock + 5) / 10) - 1; /* Round to the nearest integer */ if(u32Div > 0xFF) { /* Set BCn = 0: f_spi = f_spi_clk_src / ((DIVIDER + 1) * 2) */ spi->CNTRL2 &= (~SPI_CNTRL2_BCn_Msk); u32Div = (((u32ClkSrc * 10) / (u32BusClock * 2) + 5) / 10) - 1; /* Round to the nearest integer */ if(u32Div > 0xFF) u32Div = 0xFF; spi->DIVIDER = (spi->DIVIDER & (~SPI_DIVIDER_DIVIDER_Msk)) | (u32Div << SPI_DIVIDER_DIVIDER_Pos); /* Return master peripheral clock rate */ return (u32ClkSrc / ((u32Div + 1) * 2)); } else { spi->DIVIDER = (spi->DIVIDER & (~SPI_DIVIDER_DIVIDER_Msk)) | (u32Div << SPI_DIVIDER_DIVIDER_Pos); /* Return master peripheral clock rate */ return (u32ClkSrc / (u32Div + 1)); } } }
/*---------------------------------------------------------------------------------------------------------*/ int main() { unsigned int u32ByteCount; unsigned int u32PageNumber; unsigned int u32ProgramFlashAddress = 0; unsigned int u32VerifyFlashAddress = 0; unsigned int MidDid; PDMA_T *PDMA_CH1, *PDMA_CH2; // PDMA Channel 1/2 control registers PDMA_CH1 = (PDMA_T *)((uint32_t) PDMA1_BASE + (0x100 * (CH1-1))); PDMA_CH2 = (PDMA_T *)((uint32_t) PDMA1_BASE + (0x100 * (CH2-1))); /* Initial system */ SYS_Init(); /* Initial UART1 to 115200-8n1 for print message */ UART1_Init(); printf("Hello World.\n"); printf("PLL Clock = %d Hz\n", CLK_GetPLLClockFreq()); printf("Core Clock = %d Hz\n\n", CLK_GetHCLKFreq()); printf("+-------------------------------------------------------+\n"); printf("| Nano100 Series SPI_Flash Sample Code with PDMA |\n"); printf("+-------------------------------------------------------+\n"); /* Open 7-Seg */ Open_Seven_Segment(); /* Open SPI for Serial Flash */ Open_SPI_Flash(); /* Initial PDMA Channels */ Init_PDMA_CH1_for_SPI0_TX((uint32_t)SrcArray); Init_PDMA_CH2_for_SPI0_RX((uint32_t)DestArray); /* Enable PDMA IRQ */ NVIC_EnableIRQ(PDMA_IRQn); /* Read MID & DID */ MidDid = SpiFlash_w_PDMA_ReadMidDid(); printf("\nMID and DID = %x", MidDid); /* Erase SPI Flash */ SpiFlash_w_PDMA_ChipErase(); printf("\nFlash Erasing... "); /* Wait ready */ SpiFlash_w_PDMA_WaitReady(); printf("Done!"); /* Fill the Source Data and clear Destination Data Buffer */ for(u32ByteCount=0; u32ByteCount<256; u32ByteCount++) { SrcArray[u32ByteCount] = u32ByteCount; DestArray[u32ByteCount] = 0; } u32ProgramFlashAddress = 0; u32VerifyFlashAddress = 0; for(u32PageNumber=0; u32PageNumber<TEST_NUMBER; u32PageNumber++) { printf("\n\nTest Page Number = %d", u32PageNumber); Show_Seven_Segment(u32PageNumber,1); CLK_SysTickDelay(200000); /*=== Program SPI Flash ===*/ printf("\n Flash Programming... "); /* Trigger PDMA specified Channel */ PDMA_CH1->CSR |= (PDMA_CSR_TRIG_EN_Msk | PDMA_CSR_PDMACEN_Msk); /* Page Program */ SpiFlash_w_PDMA_PageProgram(u32ProgramFlashAddress, 256); SpiFlash_w_PDMA_WaitReady(); u32ProgramFlashAddress += 0x100; printf("Done!"); /*=== Read Back and Compare Data ===*/ printf("\n Flash Verifying... "); /* Trigger PDMA specified Channel */ PDMA_CH2->CSR |= (PDMA_CSR_TRIG_EN_Msk | PDMA_CSR_PDMACEN_Msk); /* Page Read */ SpiFlash_w_PDMA_ReadData(u32VerifyFlashAddress, 256); u32VerifyFlashAddress += 0x100; for(u32ByteCount=0; u32ByteCount<256; u32ByteCount++) { if(DestArray[u32ByteCount]!=u32ByteCount) { /* Error */ printf("\n\nSPI Flash R/W Fail!"); while(1); } } /* Clear Destination Data Buffer */ for(u32ByteCount=0; u32ByteCount<256; u32ByteCount++) DestArray[u32ByteCount] = 0; printf("Done!"); } printf("\n\nSPI Flash with PDMA Test Ok!"); printf("\n\n"); while(1); }
/** * @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 spi is the base address of SPI module. * @param u32MasterSlave decides the SPI module is operating in master mode or in slave mode. (SPI_SLAVE, SPI_MASTER) * @param u32SPIMode decides the transfer timing. (SPI_MODE_0, SPI_MODE_1, SPI_MODE_2, SPI_MODE_03) * @param u32DataWidth decides the data width of a SPI transaction. * @param u32BusClock is the expected frequency of SPI bus clock in Hz. * @return Actual frequency of SPI peripheral clock. * @note If u32BusClock = 0, DIVIDER setting will be set to the maximum value. * @note In slave mode, the SPI peripheral clock rate will be set to equal to system clock rate. * @note If u32BusClock is equal to system clock rate, DIV_ONE will be set to 1. * So that byte reorder function, byte suspend function and variable clock function must be disabled. * @note if u32BusClock is larger than system clock rate, the SPI peripheral clock rate will be set to equal to system clock rate. */ uint32_t SPI_Open(SPI_T *spi, uint32_t u32MasterSlave, uint32_t u32SPIMode, uint32_t u32DataWidth, uint32_t u32BusClock) { uint32_t u32ClkSrc = 0, u32Div; if(u32DataWidth == 32) u32DataWidth = 0; /* Default setting: MSB first, disable unit transfer interrupt, SP_CYCLE = 0. */ spi->CNTRL = u32MasterSlave | (u32DataWidth << SPI_CNTRL_TX_BIT_LEN_Pos) | (u32SPIMode); /* Set BCn = 1: f_spi = f_spi_clk_src / (DIVIDER + 1) */ spi->CNTRL2 |= SPI_CNTRL2_BCn_Msk; if(u32MasterSlave == SPI_MASTER) { /* Default setting: slave select signal is active low; disable automatic slave select function. */ spi->SSR = SPI_SS_ACTIVE_LOW; /* Check clock source of SPI */ if(spi == SPI0) { if((CLK->CLKSEL1 & CLK_CLKSEL1_SPI0_S_Msk) == CLK_CLKSEL1_SPI0_S_HCLK) u32ClkSrc = CLK_GetHCLKFreq(); else u32ClkSrc = CLK_GetPLLClockFreq(); } else { if((CLK->CLKSEL1 & CLK_CLKSEL1_SPI1_S_Msk) == CLK_CLKSEL1_SPI1_S_HCLK) u32ClkSrc = CLK_GetHCLKFreq(); else u32ClkSrc = CLK_GetPLLClockFreq(); } if(u32BusClock >= u32ClkSrc) { /* Set DIVIDER = 0 */ spi->DIVIDER = 0; /* Return master peripheral clock rate */ return u32ClkSrc; } else if(u32BusClock == 0) { /* Set BCn = 0: f_spi = f_spi_clk_src / ((DIVIDER + 1) * 2) */ spi->CNTRL2 &= (~SPI_CNTRL2_BCn_Msk); /* Set DIVIDER to the maximum value 0xFF */ spi->DIVIDER = (spi->DIVIDER & (~SPI_DIVIDER_DIVIDER_Msk)) | (0xFF << SPI_DIVIDER_DIVIDER_Pos); /* Return master peripheral clock rate */ return (u32ClkSrc / ((0xFF + 1) * 2)); } else { u32Div = (((u32ClkSrc * 10) / u32BusClock + 5) / 10) - 1; /* Round to the nearest integer */ if(u32Div > 0xFF) { /* Set BCn = 0: f_spi = f_spi_clk_src / ((DIVIDER + 1) * 2) */ spi->CNTRL2 &= (~SPI_CNTRL2_BCn_Msk); u32Div = (((u32ClkSrc * 10) / (u32BusClock * 2) + 5) / 10) - 1; /* Round to the nearest integer */ if(u32Div > 0xFF) u32Div = 0xFF; spi->DIVIDER = (spi->DIVIDER & (~SPI_DIVIDER_DIVIDER_Msk)) | (u32Div << SPI_DIVIDER_DIVIDER_Pos); /* Return master peripheral clock rate */ return (u32ClkSrc / ((u32Div + 1) * 2)); } else { spi->DIVIDER = (spi->DIVIDER & (~SPI_DIVIDER_DIVIDER_Msk)) | (u32Div << SPI_DIVIDER_DIVIDER_Pos); /* Return master peripheral clock rate */ return (u32ClkSrc / (u32Div + 1)); } } } else /* For slave mode, force the SPI peripheral clock rate to system clock rate. */ { /* Default setting: slave select signal is low level active. */ spi->SSR = SPI_SSR_SS_LTRIG_Msk; /* Select HCLK as the clock source of SPI */ if(spi == SPI0) CLK->CLKSEL1 = (CLK->CLKSEL1 & (~CLK_CLKSEL1_SPI0_S_Msk)) | CLK_CLKSEL1_SPI0_S_HCLK; else CLK->CLKSEL1 = (CLK->CLKSEL1 & (~CLK_CLKSEL1_SPI1_S_Msk)) | CLK_CLKSEL1_SPI1_S_HCLK; /* Set DIVIDER = 0 */ spi->DIVIDER = 0; /* Return slave peripheral clock rate */ return u32ClkSrc; } }
/*---------------------------------------------------------------------------------------------------------*/ int32_t main(void) { unsigned int u32ByteCount; unsigned int u32PageNumber; unsigned int u32ProgramFlashAddress = 0; unsigned int u32VerifyFlashAddress = 0; unsigned int MidDid; /* Unlock protected registers */ SYS_UnlockReg(); /* Init System, peripheral clock and multi-function I/O */ SYS_Init(); /* Lock protected registers */ SYS_LockReg(); /* Init UART0 for printf */ UART0_Init(); printf("Hello World.\n"); printf("PLL Clock = %d Hz\n", CLK_GetPLLClockFreq()); printf("Core Clock = %d Hz\n\n", CLK_GetHCLKFreq()); printf("+-------------------------------------------------------+\n"); printf("| M451 Series SPI_Flash Sample Code |\n"); printf("+-------------------------------------------------------+\n"); /* Open 7-Seg */ Open_Seven_Segment(); /* Open SPI for Serial Flash */ Open_SPI_Flash(); /* Read MID & DID */ MidDid = SpiFlash_ReadMidDid(); printf("\nMID and DID = %x", MidDid); /* Erase SPI Flash */ SpiFlash_ChipErase(); printf("\nFlash Erasing... "); /* Wait ready */ SpiFlash_WaitReady(); printf("Done!"); /* Fill the Source Data and clear Destination Data Buffer */ for(u32ByteCount = 0; u32ByteCount < 256; u32ByteCount++) { SrcArray[u32ByteCount] = u32ByteCount; DestArray[u32ByteCount] = 0; } u32ProgramFlashAddress = 0; u32VerifyFlashAddress = 0; for(u32PageNumber = 0; u32PageNumber < TEST_NUMBER; u32PageNumber++) { printf("\n\nTest Page Number = %d", u32PageNumber); Show_Seven_Segment(u32PageNumber, 1); CLK_SysTickDelay(200000); /*=== Program SPI Flash ===*/ printf("\n Flash Programming... "); /* Page Program */ SpiFlash_PageProgram(SrcArray, u32ProgramFlashAddress, 256); SpiFlash_WaitReady(); u32ProgramFlashAddress += 0x100; printf("Done!"); /*=== Read Back and Compare Data ===*/ printf("\n Flash Verifying... "); /* Page Read */ SpiFlash_ReadData(DestArray, u32VerifyFlashAddress, 256); u32VerifyFlashAddress += 0x100; for(u32ByteCount = 0; u32ByteCount < 256; u32ByteCount++) { if(DestArray[u32ByteCount] != u32ByteCount) { /* Error */ printf("SPI Flash R/W Fail!"); while(1); } } /* Clear Destination Data Buffer */ for(u32ByteCount = 0; u32ByteCount < 256; u32ByteCount++) DestArray[u32ByteCount] = 0; printf("Done!"); } printf("\n\nSPI Flash Test Ok!"); printf("\n\n"); while(1); }
/** * @brief This function Configure BPWM generator and get the nearest frequency in edge aligned auto-reload mode * @param[in] bpwm The pointer of the specified BPWM module * - BPWM0 : BPWM Group 0 * - BPWM1 : BPWM Group 1 * @param[in] u32ChannelNum BPWM 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 all channels shares a prescaler. Call this API to configure BPWM frequency may affect * existing frequency of other channel. */ uint32_t BPWM_ConfigOutputChannel(BPWM_T *bpwm, uint32_t u32ChannelNum, uint32_t u32Frequency, uint32_t u32DutyCycle) { uint32_t u32Src; uint32_t u32PWMClockSrc; uint32_t i; uint32_t u32Prescale = 1U, u32CNR = 0xFFFFU; if(bpwm == BPWM0) { u32Src = CLK->CLKSEL2 & CLK_CLKSEL2_BPWM0SEL_Msk; } else { /* (bpwm == BPWM1) */ u32Src = CLK->CLKSEL2 & CLK_CLKSEL2_BPWM1SEL_Msk; } if(u32Src == 0U) { /* clock source is from PLL clock */ u32PWMClockSrc = CLK_GetPLLClockFreq(); } else { /* clock source is from PCLK */ SystemCoreClockUpdate(); if(bpwm == BPWM0) { u32PWMClockSrc = CLK_GetPCLK0Freq(); } else { /* (bpwm == BPWM1) */ u32PWMClockSrc = CLK_GetPCLK1Freq(); } } for(u32Prescale = 1U; u32Prescale < 0xFFFU; u32Prescale++) { /* prescale could be 0~0xFFF */ i = (u32PWMClockSrc / u32Frequency) / u32Prescale; /* If target value is larger than CNR, need to use a larger prescaler */ if(i < (0x10000U)) { u32CNR = i; break; } } /* Store return value here 'cos we're gonna change u16Prescale & u16CNR to the real value to fill into register */ i = u32PWMClockSrc / (u32Prescale * u32CNR); /* convert to real register value */ /* all channels share a prescaler */ u32Prescale -= 1U; BPWM_SET_PRESCALER(bpwm, u32ChannelNum, u32Prescale); /* set BPWM to down count type(edge aligned) */ (bpwm)->CTL1 = (1UL); u32CNR -= 1U; BPWM_SET_CNR(bpwm, u32ChannelNum, u32CNR); if(u32DutyCycle) { BPWM_SET_CMR(bpwm, u32ChannelNum, u32DutyCycle * (u32CNR + 1UL) / 100UL - 1UL); (bpwm)->WGCTL0 &= ~((BPWM_WGCTL0_PRDPCTLn_Msk | BPWM_WGCTL0_ZPCTLn_Msk) << (u32ChannelNum * 2U)); (bpwm)->WGCTL0 |= (BPWM_OUTPUT_LOW << ((u32ChannelNum * (2U)) + (uint32_t)BPWM_WGCTL0_PRDPCTLn_Pos)); (bpwm)->WGCTL1 &= ~((BPWM_WGCTL1_CMPDCTLn_Msk | BPWM_WGCTL1_CMPUCTLn_Msk) << (u32ChannelNum * 2U)); (bpwm)->WGCTL1 |= (BPWM_OUTPUT_HIGH << (u32ChannelNum * (2U) + (uint32_t)BPWM_WGCTL1_CMPDCTLn_Pos)); } else { BPWM_SET_CMR(bpwm, u32ChannelNum, 0U); (bpwm)->WGCTL0 &= ~((BPWM_WGCTL0_PRDPCTLn_Msk | BPWM_WGCTL0_ZPCTLn_Msk) << (u32ChannelNum * 2U)); (bpwm)->WGCTL0 |= (BPWM_OUTPUT_LOW << (u32ChannelNum * 2U + (uint32_t)BPWM_WGCTL0_ZPCTLn_Pos)); (bpwm)->WGCTL1 &= ~((BPWM_WGCTL1_CMPDCTLn_Msk | BPWM_WGCTL1_CMPUCTLn_Msk) << (u32ChannelNum * 2U)); (bpwm)->WGCTL1 |= (BPWM_OUTPUT_HIGH << (u32ChannelNum * 2U + (uint32_t)BPWM_WGCTL1_CMPDCTLn_Pos)); } return(i); }