Quantum Leaps bd38a964cb 5.6.5
2016-06-10 21:51:18 -04:00

330 lines
12 KiB
C

/***************************************************************************//**
* @file em_bus.h
* @brief RAM and peripheral bit-field set and clear API
* @version 4.3.0
*******************************************************************************
* @section License
* <b>Copyright 2016 Silicon Laboratories, Inc. http://www.silabs.com</b>
*******************************************************************************
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*
* DISCLAIMER OF WARRANTY/LIMITATION OF REMEDIES: Silicon Labs has no
* obligation to support this Software. Silicon Labs is providing the
* Software "AS IS", with no express or implied warranties of any kind,
* including, but not limited to, any implied warranties of merchantability
* or fitness for any particular purpose or warranties against infringement
* of any proprietary rights of a third party.
*
* Silicon Labs will not be liable for any consequential, incidental, or
* special damages, or any other relief, or for any claim by any third party,
* arising from your use of this Software.
*
******************************************************************************/
#ifndef EM_BUS__
#define EM_BUS__
#include "em_device.h"
#ifdef __cplusplus
extern "C" {
#endif
/***************************************************************************//**
* @addtogroup emlib
* @{
******************************************************************************/
/***************************************************************************//**
* @addtogroup BUS
* @brief BUS RAM and register bit/field read/write API
* @details
* API to perform bitbanded and masked accesses to SRAM and peripheral memory.
* @{
******************************************************************************/
/***************************************************************************//**
* @brief
* Perform a single-bit write operation on a 32-bit word in RAM
*
* @details
* This function uses Cortex-M bit-banding hardware to perform an atomic
* read-modify-write operation on a single bit write on a 32-bit word in RAM.
* Please refer to the reference manual for further details about bit-banding.
*
* @note
* This function is atomic on Cortex-M cores with bit-banding support. Bit-
* banding is a multicycle read-modify-write bus operation. RAM bit-banding is
* performed using the memory alias region at BITBAND_RAM_BASE.
*
* @param[in] addr Address of 32-bit word in RAM
*
* @param[in] bit Bit position to write, 0-31
*
* @param[in] val Value to set bit to, 0 or 1
******************************************************************************/
__STATIC_INLINE void BUS_RamBitWrite(volatile uint32_t *addr,
unsigned int bit,
unsigned int val)
{
#if defined( BITBAND_RAM_BASE )
uint32_t aliasAddr =
BITBAND_RAM_BASE + (((uint32_t)addr - SRAM_BASE) * 32) + (bit * 4);
*(volatile uint32_t *)aliasAddr = (uint32_t)val;
#else
uint32_t tmp = *addr;
/* Make sure val is not more than 1, because we only want to set one bit. */
*addr = (tmp & ~(1 << bit)) | ((val & 1) << bit);
#endif
}
/***************************************************************************//**
* @brief
* Perform a single-bit read operation on a 32-bit word in RAM
*
* @details
* This function uses Cortex-M bit-banding hardware to perform an atomic
* read operation on a single register bit. Please refer to the
* reference manual for further details about bit-banding.
*
* @note
* This function is atomic on Cortex-M cores with bit-banding support.
* RAM bit-banding is performed using the memory alias region
* at BITBAND_RAM_BASE.
*
* @param[in] addr RAM address
*
* @param[in] bit Bit position to read, 0-31
*
* @return
* The requested bit shifted to bit position 0 in the return value
******************************************************************************/
__STATIC_INLINE unsigned int BUS_RamBitRead(volatile const uint32_t *addr,
unsigned int bit)
{
#if defined( BITBAND_RAM_BASE )
uint32_t aliasAddr =
BITBAND_RAM_BASE + (((uint32_t)addr - SRAM_BASE) * 32) + (bit * 4);
return *(volatile uint32_t *)aliasAddr;
#else
return ((*addr) >> bit) & 1;
#endif
}
/***************************************************************************//**
* @brief
* Perform a single-bit write operation on a peripheral register
*
* @details
* This function uses Cortex-M bit-banding hardware to perform an atomic
* read-modify-write operation on a single register bit. Please refer to the
* reference manual for further details about bit-banding.
*
* @note
* This function is atomic on Cortex-M cores with bit-banding support. Bit-
* banding is a multicycle read-modify-write bus operation. Peripheral register
* bit-banding is performed using the memory alias region at BITBAND_PER_BASE.
*
* @param[in] addr Peripheral register address
*
* @param[in] bit Bit position to write, 0-31
*
* @param[in] val Value to set bit to, 0 or 1
******************************************************************************/
__STATIC_INLINE void BUS_RegBitWrite(volatile uint32_t *addr,
unsigned int bit,
unsigned int val)
{
#if defined( BITBAND_PER_BASE )
uint32_t aliasAddr =
BITBAND_PER_BASE + (((uint32_t)addr - PER_MEM_BASE) * 32) + (bit * 4);
*(volatile uint32_t *)aliasAddr = (uint32_t)val;
#else
uint32_t tmp = *addr;
/* Make sure val is not more than 1, because we only want to set one bit. */
*addr = (tmp & ~(1 << bit)) | ((val & 1) << bit);
#endif
}
/***************************************************************************//**
* @brief
* Perform a single-bit read operation on a peripheral register
*
* @details
* This function uses Cortex-M bit-banding hardware to perform an atomic
* read operation on a single register bit. Please refer to the
* reference manual for further details about bit-banding.
*
* @note
* This function is atomic on Cortex-M cores with bit-banding support.
* Peripheral register bit-banding is performed using the memory alias
* region at BITBAND_PER_BASE.
*
* @param[in] addr Peripheral register address
*
* @param[in] bit Bit position to read, 0-31
*
* @return
* The requested bit shifted to bit position 0 in the return value
******************************************************************************/
__STATIC_INLINE unsigned int BUS_RegBitRead(volatile const uint32_t *addr,
unsigned int bit)
{
#if defined( BITBAND_PER_BASE )
uint32_t aliasAddr =
BITBAND_PER_BASE + (((uint32_t)addr - PER_MEM_BASE) * 32) + (bit * 4);
return *(volatile uint32_t *)aliasAddr;
#else
return ((*addr) >> bit) & 1;
#endif
}
/***************************************************************************//**
* @brief
* Perform a masked set operation on peripheral register address.
*
* @details
* Peripheral register masked set provides a single-cycle and atomic set
* operation of a bit-mask in a peripheral register. All 1's in the mask are
* set to 1 in the register. All 0's in the mask are not changed in the
* register.
* RAMs and special peripherals are not supported. Please refer to the
* reference manual for further details about peripheral register field set.
*
* @note
* This function is single-cycle and atomic on cores with peripheral bit set
* and clear support. It uses the memory alias region at PER_BITSET_MEM_BASE.
*
* @param[in] addr Peripheral register address
*
* @param[in] mask Mask to set
******************************************************************************/
__STATIC_INLINE void BUS_RegMaskedSet(volatile uint32_t *addr,
uint32_t mask)
{
#if defined( PER_BITSET_MEM_BASE )
uint32_t aliasAddr = PER_BITSET_MEM_BASE + ((uint32_t)addr - PER_MEM_BASE);
*(volatile uint32_t *)aliasAddr = mask;
#else
*addr |= mask;
#endif
}
/***************************************************************************//**
* @brief
* Perform a masked clear operation on peripheral register address.
*
* @details
* Peripheral register masked clear provides a single-cycle and atomic clear
* operation of a bit-mask in a peripheral register. All 1's in the mask are
* set to 0 in the register.
* All 0's in the mask are not changed in the register.
* RAMs and special peripherals are not supported. Please refer to the
* reference manual for further details about peripheral register field clear.
*
* @note
* This function is single-cycle and atomic on cores with peripheral bit set
* and clear support. It uses the memory alias region at PER_BITCLR_MEM_BASE.
*
* @param[in] addr Peripheral register address
*
* @param[in] mask Mask to clear
******************************************************************************/
__STATIC_INLINE void BUS_RegMaskedClear(volatile uint32_t *addr,
uint32_t mask)
{
#if defined( PER_BITCLR_MEM_BASE )
uint32_t aliasAddr = PER_BITCLR_MEM_BASE + ((uint32_t)addr - PER_MEM_BASE);
*(volatile uint32_t *)aliasAddr = mask;
#else
*addr &= ~mask;
#endif
}
/***************************************************************************//**
* @brief
* Perform peripheral register masked clear and value write.
*
* @details
* This function first clears the mask in the peripheral register, then
* writes the value. Typically the mask is a bit-field in the register, and
* the value val is within the mask.
*
* @note
* This operation is not atomic. Note that the mask is first set to 0 before
* the val is set.
*
* @param[in] addr Peripheral register address
*
* @param[in] mask Peripheral register mask
*
* @param[in] val Peripheral register value. The value must be shifted to the
correct bit position in the register.
******************************************************************************/
__STATIC_INLINE void BUS_RegMaskedWrite(volatile uint32_t *addr,
uint32_t mask,
uint32_t val)
{
#if defined( PER_BITCLR_MEM_BASE )
BUS_RegMaskedClear(addr, mask);
BUS_RegMaskedSet(addr, val);
#else
*addr = (*addr & ~mask) | val;
#endif
}
/***************************************************************************//**
* @brief
* Perform a peripheral register masked read
*
* @details
* Read an unshifted and masked value from a peripheral register.
*
* @note
* This operation is not hardware accelerated.
*
* @param[in] addr Peripheral register address
*
* @param[in] mask Peripheral register mask
*
* @return
* Unshifted and masked register value
******************************************************************************/
__STATIC_INLINE uint32_t BUS_RegMaskedRead(volatile const uint32_t *addr,
uint32_t mask)
{
return *addr & mask;
}
/** @} (end addtogroup BUS) */
/** @} (end addtogroup emlib) */
#ifdef __cplusplus
}
#endif
#endif /* EM_BUS__ */