/**************************************************************************//** * @file bmc.c * @version V3.00 * @brief M460 series BMC driver source file * * @copyright SPDX-License-Identifier: Apache-2.0 * @copyright Copyright (C) 2021 Nuvoton Technology Corp. All rights reserved. *****************************************************************************/ #include "NuMicro.h" /** @addtogroup Standard_Driver Standard Driver @{ */ /** @addtogroup BMC_Driver BMC Driver @{ */ /** @addtogroup BMC_EXPORTED_FUNCTIONS BMC Exported Functions @{ */ /** * @brief Set the BMC bit clock * @param[in] u32BitClock The expected frequency of BMC bit clock in Hz * @return Actual frequency of BMC bit clock * @details The actual clock rate may be different from the target BMC bit clock rate. * For example, if the system clock rate is 200 MHz and the target BMC bit clock rate is 3 MHz, the actual BMC bit clock * rate will be 2 MHz. * \hideinitializer */ uint32_t BMC_SetBitClock(uint32_t u32BitClock) { uint32_t u32HCLKFreq, u32Div, u32RetValue; /* Get system clock frequency */ u32HCLKFreq = CLK_GetHCLKFreq(); u32Div = ((u32HCLKFreq * 10UL) / u32BitClock + 5UL) / 10UL; /* Round to the nearest integer */ BMC->CTL = (BMC->CTL & (~BMC_CTL_BTDIV_Msk)) | (u32Div << BMC_CTL_BTDIV_Pos); /* Return BMC bit clock rate */ u32RetValue = u32HCLKFreq / u32Div; return u32RetValue; } /** * @brief Get the actual frequency of BMC bit clock * @return Actual BMC bit frequency in Hz * @details This API will calculate the actual BMC bit clock rate according to the HBTDIV setting. * \hideinitializer */ uint32_t BMC_GetBitClock(void) { uint32_t u32HCLKFreq, u32Div; /* Get BTDIV setting */ u32Div = (BMC->CTL & BMC_CTL_BTDIV_Msk) >> BMC_CTL_BTDIV_Pos; /* Get system clock frequency */ u32HCLKFreq = CLK_GetHCLKFreq(); /* Return BMC bit clock rate */ return (u32HCLKFreq / u32Div); } /** * @brief Set the dummy delay time period of each group * @param[in] u32ChGroup BMC channel group selection, valid values are: * - \ref BMC_GROUP_0 * - \ref BMC_GROUP_1 * - \ref BMC_GROUP_2 * - \ref BMC_GROUP_3 * - \ref BMC_GROUP_4 * - \ref BMC_GROUP_5 * - \ref BMC_GROUP_6 * - \ref BMC_GROUP_7 * @param[in] u32DumDelay The expected BMC dummy delay period in microsecond * @return Actual dummy delay time period in microsecond * @details This API is used to set each group dummy delay time period. * \hideinitializer */ uint32_t BMC_SetDummyDelayPeriod(uint32_t u32ChGroup, uint32_t u32DumDelay) { uint32_t i, u32BitNum; u32BitNum = ((BMC_GetBitClock() * u32DumDelay) / 1000000UL) / 8UL; for(i = 0UL; i < (uint32_t)BMC_CHANNEL_NUM; i += 4UL) { if((u32ChGroup == i) && (u32ChGroup <= BMC_GROUP_3)) { outp8((uint32_t)&(BMC->DNUM0) + (i >> 2UL), u32BitNum); break; } else if((u32ChGroup == i) && (u32ChGroup > BMC_GROUP_3)) { outp8((uint32_t)&(BMC->DNUM1) + ((i >> 2UL) - 4UL), u32BitNum); break; } } /* Return BMC dummy delay time period */ return (8UL * 1000000UL / BMC_GetBitClock() * u32BitNum); } /** * @brief Enable interrupt function * @param[in] u32Mask The combination of all related interrupt enable bits. * Each bit corresponds to a interrupt enable bit. * This parameter decides which interrupts will be enabled. It is combination of: * - \ref BMC_FTXD_INT_MASK * - \ref BMC_TXUND_INT_MASK * @return None * @details This API is used to enable BMC related interrupts specified by u32Mask parameter. * \hideinitializer */ void BMC_EnableInt(uint32_t u32Mask) { /* Enable frame transmit done interrupt flag */ if((u32Mask & BMC_FTXD_INT_MASK) == BMC_FTXD_INT_MASK) { BMC->INTEN |= BMC_INTEN_FTXDIEN_Msk; } /* Enable transmit data under run interrupt flag */ if((u32Mask & BMC_TXUND_INT_MASK) == BMC_TXUND_INT_MASK) { BMC->INTEN |= BMC_INTEN_TXUNDIEN_Msk; } } /** * @brief Disable interrupt function * @param[in] u32Mask The combination of all related interrupt enable bits. * Each bit corresponds to a interrupt enable bit. * This parameter decides which interrupts will be disabled. It is combination of: * - \ref BMC_FTXD_INT_MASK * - \ref BMC_TXUND_INT_MASK * @return None * @details This API is used to disable BMC related interrupts specified by u32Mask parameter. * \hideinitializer */ void BMC_DisableInt(uint32_t u32Mask) { /* Disable frame transmit done interrupt flag */ if((u32Mask & BMC_FTXD_INT_MASK) == BMC_FTXD_INT_MASK) { BMC->INTEN &= ~BMC_INTEN_FTXDIEN_Msk; } /* Disable transmit data under run interrupt flag */ if((u32Mask & BMC_TXUND_INT_MASK) == BMC_TXUND_INT_MASK) { BMC->INTEN &= ~BMC_INTEN_TXUNDIEN_Msk; } } /** * @brief Get interrupt flag * @param[in] u32Mask The combination of all related interrupt sources. * Each bit corresponds to a interrupt source. * This parameter decides which interrupt flags will be read. It is combination of: * - \ref BMC_FTXD_INT_MASK * - \ref BMC_TXUND_INT_MASK * @return Interrupt flags of selected sources * @details This API is used to get BMC related interrupt flags specified by u32Mask parameter. * \hideinitializer */ uint32_t BMC_GetIntFlag(uint32_t u32Mask) { uint32_t u32IntStatus; uint32_t u32IntFlag = 0UL; u32IntStatus = BMC->INTSTS; /* Check frame transmit done interrupt flag */ if((u32Mask & BMC_FTXD_INT_MASK) && (u32IntStatus & BMC_INTSTS_FTXDIF_Msk)) { u32IntFlag |= BMC_FTXD_INT_MASK; } /* Check transmit data under run interrupt flag */ if((u32Mask & BMC_TXUND_INT_MASK) && (u32IntStatus & BMC_INTSTS_TXUNDIF_Msk)) { u32IntFlag |= BMC_TXUND_INT_MASK; } return u32IntFlag; } /** * @brief Clear interrupt flag * @param[in] u32Mask The related interrupt source. * This parameter decides which interrupt flag will be cleared. Possible option is: * - \ref BMC_FTXD_INT_MASK * @return None * @details This API is used to clear BMC related interrupt flag specified by u32Mask parameter. * \hideinitializer */ void BMC_ClearIntFlag(uint32_t u32Mask) { if(u32Mask & BMC_FTXD_INT_MASK) { BMC->INTSTS = BMC_INTSTS_FTXDIF_Msk; /* Clear frame transmit done interrupt flag */ } } /** * @brief Get BMC status * @param[in] u32Mask The combination of all related sources. * Each bit corresponds to a related source. * This parameter decides which flags will be read. It is combination of: * - \ref BMC_G0TXUND_MASK * - \ref BMC_G1TXUND_MASK * - \ref BMC_G2TXUND_MASK * - \ref BMC_G3TXUND_MASK * - \ref BMC_G4TXUND_MASK * - \ref BMC_G5TXUND_MASK * - \ref BMC_G6TXUND_MASK * - \ref BMC_G7TXUND_MASK * @return Flags of selected sources * @details This API is used to get BMC related status specified by u32Mask parameter. * \hideinitializer */ uint32_t BMC_GetStatus(uint32_t u32Mask) { uint32_t u32TmpStatus; uint32_t u32Flag = 0UL; u32TmpStatus = BMC->INTSTS; /* Check group 0 transmit data under run status */ if((u32Mask & BMC_G0TXUND_MASK) && (u32TmpStatus & BMC_INTSTS_G0TXUND_Msk)) { u32Flag |= BMC_G0TXUND_MASK; } /* Check group 1 transmit data under run status */ if((u32Mask & BMC_G1TXUND_MASK) && (u32TmpStatus & BMC_INTSTS_G1TXUND_Msk)) { u32Flag |= BMC_G1TXUND_MASK; } /* Check group 2 transmit data under run status */ if((u32Mask & BMC_G2TXUND_MASK) && (u32TmpStatus & BMC_INTSTS_G2TXUND_Msk)) { u32Flag |= BMC_G2TXUND_MASK; } /* Check group 3 transmit data under run status */ if((u32Mask & BMC_G3TXUND_MASK) && (u32TmpStatus & BMC_INTSTS_G3TXUND_Msk)) { u32Flag |= BMC_G3TXUND_MASK; } /* Check group 4 transmit data under run status */ if((u32Mask & BMC_G4TXUND_MASK) && (u32TmpStatus & BMC_INTSTS_G4TXUND_Msk)) { u32Flag |= BMC_G4TXUND_MASK; } /* Check group 5 transmit data under run status */ if((u32Mask & BMC_G5TXUND_MASK) && (u32TmpStatus & BMC_INTSTS_G5TXUND_Msk)) { u32Flag |= BMC_G5TXUND_MASK; } /* Check group 6 transmit data under run status */ if((u32Mask & BMC_G6TXUND_MASK) && (u32TmpStatus & BMC_INTSTS_G6TXUND_Msk)) { u32Flag |= BMC_G6TXUND_MASK; } /* Check group 7 transmit data under run status */ if((u32Mask & BMC_G7TXUND_MASK) && (u32TmpStatus & BMC_INTSTS_G7TXUND_Msk)) { u32Flag |= BMC_G7TXUND_MASK; } return u32Flag; } /** * @brief Clear BMC status * @param[in] u32Mask The combination of all related sources. * Each bit corresponds to a related source. * This parameter decides which flags will be cleared. It is combination of: * - \ref BMC_G0TXUND_MASK * - \ref BMC_G1TXUND_MASK * - \ref BMC_G2TXUND_MASK * - \ref BMC_G3TXUND_MASK * - \ref BMC_G4TXUND_MASK * - \ref BMC_G5TXUND_MASK * - \ref BMC_G6TXUND_MASK * - \ref BMC_G7TXUND_MASK * @return None * @details This API is used to clear BMC related status specified by u32Mask parameter. * \hideinitializer */ void BMC_ClearStatus(uint32_t u32Mask) { if(u32Mask & BMC_G0TXUND_MASK) { BMC->INTSTS = BMC_INTSTS_G0TXUND_Msk; /* Check group 0 transmit data under run status */ } if(u32Mask & BMC_G1TXUND_MASK) { BMC->INTSTS = BMC_INTSTS_G1TXUND_Msk; /* Check group 1 transmit data under run status */ } if(u32Mask & BMC_G2TXUND_MASK) { BMC->INTSTS = BMC_INTSTS_G2TXUND_Msk; /* Check group 2 transmit data under run status */ } if(u32Mask & BMC_G3TXUND_MASK) { BMC->INTSTS = BMC_INTSTS_G3TXUND_Msk; /* Check group 3 transmit data under run status */ } if(u32Mask & BMC_G4TXUND_MASK) { BMC->INTSTS = BMC_INTSTS_G4TXUND_Msk; /* Check group 4 transmit data under run status */ } if(u32Mask & BMC_G5TXUND_MASK) { BMC->INTSTS = BMC_INTSTS_G5TXUND_Msk; /* Check group 5 transmit data under run status */ } if(u32Mask & BMC_G6TXUND_MASK) { BMC->INTSTS = BMC_INTSTS_G6TXUND_Msk; /* Check group 6 transmit data under run status */ } if(u32Mask & BMC_G7TXUND_MASK) { BMC->INTSTS = BMC_INTSTS_G7TXUND_Msk; /* Check group 7 transmit data under run status */ } } /*@}*/ /* end of group BMC_EXPORTED_FUNCTIONS */ /*@}*/ /* end of group BMC_Driver */ /*@}*/ /* end of group Standard_Driver */