/***************************************************************************//**
* @brief
* Initialize a CSEN measurement mode.
*
* @details
* Used to configure any type of measurement mode. After the measurement
* has been configured, calling @ref CSEN_Enable() will enable CSEN and
* allow it to start a conversion from the selected trigger source. To
* manually start a conversion use @ref CSEN_Start(). To check if a
* conversion is in progress use @ref CSEN_IsBusy(), or alternatively
* use the interrupt flags returned by @ref CSEN_IntGet() to detect when
* a conversion is completed.
*
* @note
* This function will stop any ongoing conversion and disable CSEN.
*
* @param[in] csen
* Pointer to CSEN peripheral register block.
*
* @param[in] init
* Pointer to CSEN measurement mode initialization structure.
******************************************************************************/
void CSEN_InitMode(CSEN_TypeDef *csen, const CSEN_InitMode_TypeDef *init)
{
uint32_t tmp;
EFM_ASSERT(CSEN_REF_VALID(csen));
EFM_ASSERT(init->dmIterPerCycle < 0x10);
EFM_ASSERT(init->dmCycles < 0x10);
/* Initialize CTRL. This will stop any conversion in progress.
* These composite inputs set multiple fields. They do not need
* to be shifted. */
tmp = ((uint32_t)init->sampleMode
| (uint32_t)init->convSel
| (uint32_t)init->cmpMode);
tmp |= (init->trigSel << _CSEN_CTRL_STM_SHIFT)
| (init->accMode << _CSEN_CTRL_ACU_SHIFT)
| (init->sarRes << _CSEN_CTRL_SARCR_SHIFT);
if (init->enableDma) {
tmp |= CSEN_CTRL_DMAEN_ENABLE;
}
if (init->sumOnly) {
tmp |= CSEN_CTRL_DRSF_ENABLE;
}
if (init->autoGnd) {
tmp |= CSEN_CTRL_AUTOGND_ENABLE;
}
/* Preserve the fields that were initialized by CSEN_Init(). */
tmp |= csen->CTRL & (_CSEN_CTRL_CPACCURACY_MASK
| _CSEN_CTRL_LOCALSENS_MASK
| _CSEN_CTRL_WARMUPMODE_MASK);
csen->CTRL = tmp;
/* EMACTRL only has one field */
csen->EMACTRL = init->emaSample << _CSEN_EMACTRL_EMASAMPLE_SHIFT;
/* CMPTHR only has one field */
csen->CMPTHR = init->cmpThr << _CSEN_CMPTHR_CMPTHR_SHIFT;
/* SINGLECTRL only has one field */
csen->SINGLECTRL = init->singleSel << _CSEN_SINGLECTRL_SINGLESEL_SHIFT;
/* Set all input enables */
csen->SCANMASK0 = init->inputMask0;
csen->SCANMASK1 = init->inputMask1;
/* Initialize DMCFG. */
tmp = (init->dmRes << _CSEN_DMCFG_CRMODE_SHIFT)
| (init->dmCycles << _CSEN_DMCFG_DMCR_SHIFT)
| (init->dmIterPerCycle << _CSEN_DMCFG_DMR_SHIFT)
| (init->dmDelta << _CSEN_DMCFG_DMG_SHIFT);
if (init->dmFixedDelta) {
tmp |= CSEN_DMCFG_DMGRDIS;
}
csen->DMCFG = tmp;
/* Initialize ANACTRL. */
csen->ANACTRL = (init->resetPhase << _CSEN_ANACTRL_TRSTPROG_SHIFT)
| (init->driveSel << _CSEN_ANACTRL_IDACIREFS_SHIFT)
| (init->gainSel << _CSEN_ANACTRL_IREFPROG_SHIFT);
}
开发者ID:sg-,项目名称:mbed-os,代码行数:90,代码来源:em_csen.c
示例2: MSC_LoadWriteData
__ramfunc
#endif
#endif /* !EM_MSC_RUN_FROM_FLASH */
__STATIC_INLINE MSC_Status_TypeDef
MSC_LoadWriteData(uint32_t* data,
uint32_t numWords,
MSC_WriteStrategy_Typedef writeStrategy)
{
uint32_t timeOut;
uint32_t wordIndex;
uint32_t wordsPerDataPhase;
MSC_Status_TypeDef retval = mscReturnOk;
#if defined(_MSC_WRITECTRL_LPWRITE_MASK) && defined(_MSC_WRITECTRL_WDOUBLE_MASK)
/* If LPWRITE (Low Power Write) is NOT enabled, set WDOUBLE (Write Double word) */
if (!(MSC->WRITECTRL & MSC_WRITECTRL_LPWRITE))
{
/* If the number of words to be written are odd, we need to align by writing
a single word first, before setting the WDOUBLE bit. */
if (numWords & 0x1)
{
/* Wait for the MSC to become ready for the next word. */
timeOut = MSC_PROGRAM_TIMEOUT;
while ((!(MSC->STATUS & MSC_STATUS_WDATAREADY)) && (timeOut != 0))
{
timeOut--;
}
/* Check for timeout */
if (timeOut == 0)
{
return mscReturnTimeOut;
}
/* Clear double word option, in order to write the initial single word. */
MSC->WRITECTRL &= ~MSC_WRITECTRL_WDOUBLE;
/* Write first data word. */
MSC->WDATA = *data++;
MSC->WRITECMD = MSC_WRITECMD_WRITEONCE;
/* Wait for the operation to finish. It may be required to change the WDOUBLE
config after the initial write. It should not be changed while BUSY. */
timeOut = MSC_PROGRAM_TIMEOUT;
while((MSC->STATUS & MSC_STATUS_BUSY) && (timeOut != 0))
{
timeOut--;
}
/* Check for timeout */
if (timeOut == 0)
{
return mscReturnTimeOut;
}
/* Subtract this initial odd word for the write loop below */
numWords -= 1;
retval = mscReturnOk;
}
/* Now we can set the double word option in order to write two words per
data phase. */
MSC->WRITECTRL |= MSC_WRITECTRL_WDOUBLE;
wordsPerDataPhase = 2;
}
else
#endif /* defined( _MSC_WRITECTRL_LPWRITE_MASK ) && defined( _MSC_WRITECTRL_WDOUBLE_MASK ) */
{
wordsPerDataPhase = 1;
}
/* Write the rest as double word write if wordsPerDataPhase == 2 */
if (numWords > 0)
{
/**** Write strategy: mscWriteIntSafe ****/
if (writeStrategy == mscWriteIntSafe)
{
/* Requires a system core clock at 1MHz or higher */
EFM_ASSERT(SystemCoreClockGet() >= 1000000);
wordIndex = 0;
while(wordIndex < numWords)
{
MSC->WDATA = *data++;
wordIndex++;
if (wordsPerDataPhase == 2)
{
while (!(MSC->STATUS & MSC_STATUS_WDATAREADY));
MSC->WDATA = *data++;
wordIndex++;
}
MSC->WRITECMD = MSC_WRITECMD_WRITEONCE;
/* Wait for the transaction to finish. */
timeOut = MSC_PROGRAM_TIMEOUT;
while ((MSC->STATUS & MSC_STATUS_BUSY) && (timeOut != 0))
{
timeOut--;
}
/* Check for timeout */
if (timeOut == 0)
{
retval = mscReturnTimeOut;
break;
}
#if defined( _EFM32_GECKO_FAMILY )
MSC->ADDRB += 4;
//.........这里部分代码省略.........
/***************************************************************************//**
* @brief
* Set bits GPIO data out register to 1.
*
* @note
* In order for the setting to take effect on the respective output pads, the
* pins must have been configured properly. If not, it will take effect
* whenever the pin has been properly configured.
*
* @param[in] port
* The GPIO port to access.
*
* @param[in] pins
* Bit mask for bits to set to 1 in DOUT register.
******************************************************************************/
void GPIO_PortOutSet(GPIO_Port_TypeDef port, uint32_t pins)
{
EFM_ASSERT(GPIO_PORT_VALID(port));
GPIO->P[port].DOUTSET = pins & _GPIO_P_DOUTSET_DOUTSET_MASK;
}
/***************************************************************************//**
* @brief
* Toggle a single pin in GPIO port data out register.
*
* @note
* In order for the setting to take effect on the output pad, the pin must
* have been configured properly. If not, it will take effect whenever the
* pin has been properly configured.
*
* @param[in] port
* The GPIO port to access.
*
* @param[in] pins
* Bitmask with pins to toggle.
******************************************************************************/
void GPIO_PortOutToggle(GPIO_Port_TypeDef port, uint32_t pins)
{
EFM_ASSERT(GPIO_PORT_VALID(port));
GPIO->P[port].DOUTTGL = pins & _GPIO_P_DOUTTGL_DOUTTGL_MASK;
}
/***************************************************************************//**
* @brief
* Configure USART/UART operating in asynchronous mode to use a given
* baudrate (or as close as possible to specified baudrate).
*
* @param[in] usart
* Pointer to USART/UART peripheral register block.
*
* @param[in] refFreq
* USART/UART reference clock frequency in Hz that will be used. If set to 0,
* the currently configured reference clock is assumed.
*
* @param[in] baudrate
* Baudrate to try to achieve for USART/UART.
*
* @param[in] ovs
* Oversampling to be used. Normal is 16x oversampling, but lower oversampling
* may be used to achieve higher rates or better baudrate accuracy in some
* cases. Notice that lower oversampling frequency makes channel more
* vulnerable to bit faults during reception due to clock inaccuracies
* compared to link partner.
******************************************************************************/
void USART_BaudrateAsyncSet(USART_TypeDef *usart,
uint32_t refFreq,
uint32_t baudrate,
USART_OVS_TypeDef ovs)
{
uint32_t clkdiv;
uint32_t oversample;
/* Inhibit divide by 0 */
EFM_ASSERT(baudrate);
/*
* We want to use integer division to avoid forcing in float division
* utils, and yet keep rounding effect errors to a minimum.
*
* CLKDIV in asynchronous mode is given by:
*
* CLKDIV = 256 * (fHFPERCLK/(oversample * br) - 1)
* or
* CLKDIV = (256 * fHFPERCLK)/(oversample * br) - 256
*
* The basic problem with integer division in the above formula is that
* the dividend (256 * fHFPERCLK) may become higher than max 32 bit
* integer. Yet, we want to evaluate dividend first before dividing in
* order to get as small rounding effects as possible. We do not want
* to make too harsh restrictions on max fHFPERCLK value either.
*
* One can possibly factorize 256 and oversample/br. However,
* since the last 6 bits of CLKDIV are don't care, we can base our
* integer arithmetic on the below formula
*
* CLKDIV / 64 = (4 * fHFPERCLK)/(oversample * br) - 4
*
* and calculate 1/64 of CLKDIV first. This allows for fHFPERCLK
* up to 1GHz without overflowing a 32 bit value!
*/
/* HFPERCLK used to clock all USART/UART peripheral modules */
if (!refFreq)
{
refFreq = CMU_ClockFreqGet(cmuClock_HFPER);
}
/* Map oversampling */
switch (ovs)
{
case USART_CTRL_OVS_X16:
EFM_ASSERT(baudrate <= (refFreq / 16));
oversample = 16;
break;
case USART_CTRL_OVS_X8:
EFM_ASSERT(baudrate <= (refFreq / 8));
oversample = 8;
break;
case USART_CTRL_OVS_X6:
EFM_ASSERT(baudrate <= (refFreq / 6));
oversample = 6;
break;
case USART_CTRL_OVS_X4:
EFM_ASSERT(baudrate <= (refFreq / 4));
oversample = 4;
break;
default:
/* Invalid input */
EFM_ASSERT(0);
return;
}
/* Calculate and set CLKDIV with fractional bits.
* The addend (oversample*baudrate)/2 in the first line is to round the
* divisor up by half the divisor before the division in order to reduce the
* integer division error, which consequently results in a higher baudrate
* than desired. */
clkdiv = 4 * refFreq + (oversample * baudrate) / 2;
//.........这里部分代码省略.........
开发者ID:MatKub,项目名称:RIOT,代码行数:101,代码来源:em_usart.c
示例9: LDMA_EnableChannelRequest
/***************************************************************************//**
* @brief
* Enable or disable a LDMA channel request.
*
* @details
* Use this function to enable or disable a LDMA channel request. This will
* prevent the LDMA from proceeding after its current transaction if disabled.
*
* @param[in] channel
* LDMA channel to enable or disable requests on.
*
* @param[in] enable
* If 'true' request will be enabled. If 'false' request will be disabled.
******************************************************************************/
void LDMA_EnableChannelRequest( int ch, bool enable)
{
EFM_ASSERT( ch < DMA_CHAN_COUNT );
BUS_RegBitWrite (&LDMA->REQDIS, ch, !enable);
}
/***************************************************************************//**
* @brief
* Configure bias level for a specific segment line for Direct Segment Control
*
* @note
* When DSC is active, each configuration takes up 4 bits in the Segment
* Registers (SEGD0L/SEGD1H) which defines bias level.
* For optimal use of this feature, the entire SEGD-registers should be set
* at once in a optimized routine, so this function is mainly here to
* demonstrate how to correctly configure the bias levels, and should be used
* with care.
*
* @param[in] segmentLine
* Segment line number
*
* @param[in] biasLevel
* Bias configuration level, 0-4. This value must be within the constraint
* defined by the LCD_DISPCTRL bias setting, see Reference Manual/Datasheet
******************************************************************************/
void LCD_BiasSegmentSet(int segmentLine, int biasLevel)
{
int biasRegister;
int bitShift;
volatile uint32_t *segmentRegister;
#if defined(_EFM32_TINY_FAMILY)
EFM_ASSERT(segmentLine < 20);
#endif
#if defined(_EFM32_GIANT_FAMILY) || defined(_EFM32_WONDER_FAMILY)
EFM_ASSERT(segmentLine < 40);
#endif
#if defined(_EFM32_TINY_FAMILY)
/* Bias config for 8 segment lines per SEGDnL register */
biasRegister = segmentLine / 8;
bitShift = (segmentLine % 8) * 4;
switch (biasRegister)
{
case 0:
segmentRegister = &LCD->SEGD0L;
break;
case 1:
segmentRegister = &LCD->SEGD1L;
break;
case 2:
segmentRegister = &LCD->SEGD2L;
break;
case 3:
segmentRegister = &LCD->SEGD3L;
break;
default:
segmentRegister = (uint32_t *)0x00000000;
EFM_ASSERT(0);
break;
}
#endif
#if defined(_EFM32_GIANT_FAMILY) || defined(_EFM32_WONDER_FAMILY)
/* Bias config for 10 segment lines per SEGDn L+H registers */
biasRegister = segmentLine / 10;
bitShift = (segmentLine % 10) * 4;
switch (biasRegister)
{
case 0:
if (bitShift < 32)
{
segmentRegister = &LCD->SEGD0L;
}
else
{
segmentRegister = &LCD->SEGD0H;
bitShift -= 32;
}
break;
case 1:
if (bitShift < 32)
{
segmentRegister = &LCD->SEGD1L;
}
else
{
segmentRegister = &LCD->SEGD1H;
bitShift -= 32;
}
break;
case 2:
if (bitShift < 32)
{
segmentRegister = &LCD->SEGD2L;
}
else
{
segmentRegister = &LCD->SEGD1H;
bitShift -= 32;
}
break;
case 3:
if (bitShift < 32)
{
segmentRegister = &LCD->SEGD3L;
//.........这里部分代码省略.........
/***************************************************************************//**
* @brief
* Set bits in DOUT register for a port to 0.
*
* @note
* In order for the setting to take effect on the output pad, the pin must
* have been configured properly. If not, it will take effect whenever the
* pin has been properly configured.
*
* @param[in] port
* The GPIO port to access.
*
* @param[in] pins
* Bit mask for bits to clear in DOUT register.
******************************************************************************/
void GPIO_PortOutClear(GPIO_Port_TypeDef port, uint32_t pins)
{
EFM_ASSERT(GPIO_PORT_VALID(port));
GPIO->P[port].DOUTCLR = pins & _GPIO_P_DOUTCLR_DOUTCLR_MASK;
}
/***************************************************************************//**
* @brief
* Get current setting for a GPIO port data out register.
*
* @param[in] port
* The GPIO port to access.
*
* @return
* The data out setting for the requested port.
******************************************************************************/
uint32_t GPIO_PortOutGet(GPIO_Port_TypeDef port)
{
EFM_ASSERT(GPIO_PORT_VALID(port));
return(GPIO->P[port].DOUT & _GPIO_P_DOUT_DOUT_MASK);
}
/***************************************************************************//**
* @brief
* Configure a single LESENSE sensor channel.
*
* @details
* This function configures a single sensor channel of the LESENSE interface.
* Please refer to the configuration parameter type definition
* (LESENSE_ChDesc_TypeDef) for more details.
*
* @note
* This function has been designed to minimize the effects of sensor channel
* reconfiguration while LESENSE is in operation, however one shall be aware
* of these effects and the right timing of calling this function.
* Parameter @p useAltEx must be true in the channel configuration in order to
* use alternate excitation pins.
*
* @param[in] confCh
* Configuration structure for a single LESENSE sensor channel.
*
* @param[in] chIdx
* Channel index to configure (0-15).
******************************************************************************/
void LESENSE_ChannelConfig(LESENSE_ChDesc_TypeDef const *confCh,
uint32_t const chIdx)
{
uint32_t tmp; /* Service variable. */
/* Sanity check of configuration parameters */
EFM_ASSERT(chIdx < 16U);
EFM_ASSERT(confCh->exTime < 64U);
EFM_ASSERT(confCh->sampleDelay < 128U);
EFM_ASSERT(confCh->measDelay < 128U);
/* Not a complete assert, as the max. value of acmpThres depends on other
* configuration parameters, check the parameter description of acmpThres for
* for more details! */
EFM_ASSERT(confCh->acmpThres < 4096U);
EFM_ASSERT(!(confCh->chPinExMode == lesenseChPinExDACOut &&
(chIdx != 2U) && (chIdx != 3U) && (chIdx != 4U) && (chIdx != 5U)));
EFM_ASSERT(!(confCh->chPinIdleMode == lesenseChPinIdleDACCh1 &&
((chIdx != 12U) && (chIdx != 13U) && (chIdx != 14U) && (chIdx != 15U))));
EFM_ASSERT(!(confCh->chPinIdleMode == lesenseChPinIdleDACCh0 &&
((chIdx != 0U) && (chIdx != 1U) && (chIdx != 2U) && (chIdx != 3U))));
/* Configure chIdx setup in LESENSE idle phase.
* Read-modify-write in order to support reconfiguration during LESENSE
* operation. */
tmp = (LESENSE->IDLECONF & ~((uint32_t)0x3UL << (chIdx * 2UL)));
tmp |= ((uint32_t)confCh->chPinIdleMode << (chIdx * 2UL));
LESENSE->IDLECONF = tmp;
/* Channel specific timing configuration on scan channel chIdx.
* Set excitation time, sampling delay, measurement delay. */
LESENSE_ChannelTimingSet(chIdx,
(uint32_t)confCh->exTime,
(uint32_t)confCh->sampleDelay,
(uint32_t)confCh->measDelay);
/* Channel specific configuration of clocks, sample mode, excitation pin mode
* alternate excitation usage and interrupt mode on scan channel chIdx in
* LESENSE_CHchIdx_INTERACT. */
LESENSE->CH[chIdx].INTERACT = ((uint32_t)confCh->exClk <<
_LESENSE_CH_INTERACT_EXCLK_SHIFT) |
((uint32_t)confCh->sampleClk <<
_LESENSE_CH_INTERACT_SAMPLECLK_SHIFT) |
(uint32_t)confCh->sampleMode |
(uint32_t)confCh->intMode |
(uint32_t)confCh->chPinExMode |
((uint32_t)confCh->useAltEx <<
_LESENSE_CH_INTERACT_ALTEX_SHIFT);
/* Configure channel specific counter comparison mode, optional result
* forwarding to decoder, optional counter value storing and optional result
* inverting on scan channel chIdx in LESENSE_CHchIdx_EVAL. */
LESENSE->CH[chIdx].EVAL = (uint32_t)confCh->compMode |
((uint32_t)confCh->shiftRes <<
_LESENSE_CH_EVAL_DECODE_SHIFT) |
((uint32_t)confCh->storeCntRes <<
_LESENSE_CH_EVAL_STRSAMPLE_SHIFT) |
((uint32_t)confCh->invRes <<
_LESENSE_CH_EVAL_SCANRESINV_SHIFT);
/* Configure analog comparator (ACMP) threshold and decision threshold for
* counter separately with the function provided for that. */
LESENSE_ChannelThresSet(chIdx,
(uint32_t)confCh->acmpThres,
(uint32_t)confCh->cntThres);
/* Enable/disable interrupts on channel.
* Note: BITBAND_Peripheral() function is used for setting/clearing single
* bit peripheral register bitfields. Read the function description in
* efm32_bitband.h for more details. */
BITBAND_Peripheral(&(LESENSE->IEN),
(uint32_t)chIdx,
(uint32_t)confCh->enaInt);
/* Enable/disable CHchIdx pin. */
BITBAND_Peripheral(&(LESENSE->ROUTE),
(uint32_t)chIdx,
//.........这里部分代码省略.........
/***************************************************************************//**
* @brief
* Set GPIO port data out register.
*
* @note
* In order for the setting to take effect on the respective output pads, the
* pins must have been configured properly. If not, it will take effect
* whenever the pin has been properly configured.
*
* @param[in] port
* The GPIO port to access.
*
* @param[in] val
* Value to write to port data out register.
*
* @param[in] mask
* Mask indicating which bits to modify.
******************************************************************************/
void GPIO_PortOutSetVal(GPIO_Port_TypeDef port, uint32_t val, uint32_t mask)
{
EFM_ASSERT(GPIO_PORT_VALID(port));
GPIO->P[port].DOUT = (GPIO->P[port].DOUT & ~mask) | (val & mask);
}
请发表评论