mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2025-12-25 22:43:50 +01:00
cortexm_common: Introduce bitbanding macros
This commit is contained in:
parent
2a2855631e
commit
dc3aa13e90
231
cpu/cortexm_common/include/bit.h
Normal file
231
cpu/cortexm_common/include/bit.h
Normal file
@ -0,0 +1,231 @@
|
||||
/*
|
||||
* Copyright (C) 2017 Eistec AB
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU Lesser
|
||||
* General Public License v2.1. See the file LICENSE in the top level
|
||||
* directory for more details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @ingroup cpu_cortexm_common
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
* @brief Bit access macros for Cortex-M based CPUs
|
||||
*
|
||||
* @author Joakim Nohlgård <joakim.nohlgard@eistec.se>
|
||||
*/
|
||||
|
||||
#ifndef BIT_H
|
||||
#define BIT_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include "cpu.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Define BITBAND_FUNCTIONS_PROVIDED 1 if the CPU provides its own
|
||||
* implementations for bit manipulation */
|
||||
#if !BITBAND_FUNCTIONS_PROVIDED
|
||||
|
||||
#if DOXYGEN
|
||||
/** @brief Flag for telling if the CPU has hardware bit band support */
|
||||
#define CPU_HAS_BITBAND 1 || 0 (1 for Cortex-M3 and up, 0 for Cortex-M0)
|
||||
#endif
|
||||
|
||||
#ifndef CPU_HAS_BITBAND
|
||||
#if (__CORTEX_M >= 3)
|
||||
#define CPU_HAS_BITBAND 1
|
||||
#else
|
||||
#define CPU_HAS_BITBAND 0
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if CPU_HAS_BITBAND || DOXYGEN
|
||||
/* Cortex-M3 and higher provide a bitband address space for atomically accessing
|
||||
* single bits of peripheral registers, and sometimes for RAM as well */
|
||||
/**
|
||||
* @name Bit manipulation functions
|
||||
* @{
|
||||
*/
|
||||
/* Generic bit band conversion routine */
|
||||
/**
|
||||
* @brief Convert bit band region address and bit number to bit band alias address
|
||||
*
|
||||
* @param[in] ptr base address in non bit banded memory
|
||||
* @param[in] bit bit number within the word
|
||||
*
|
||||
* @return Address of the bit within the bit band memory region
|
||||
*/
|
||||
static inline volatile void *bitband_addr(volatile void *ptr, uintptr_t bit)
|
||||
{
|
||||
return (volatile void *)((((uintptr_t)ptr) & 0xF0000000ul) + 0x2000000ul +
|
||||
((((uintptr_t)ptr) & 0xFFFFFul) << 5) + (bit << 2));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set a single bit in the 32 bit word pointed to by @p ptr
|
||||
*
|
||||
* The effect is the same as for the following snippet:
|
||||
*
|
||||
* @code{c}
|
||||
* *ptr |= (1 << bit);
|
||||
* @endcode
|
||||
*
|
||||
* There is a read-modify-write cycle occurring within the core, but this cycle
|
||||
* is atomic and can not be disrupted by IRQs
|
||||
*
|
||||
* @param[in] ptr pointer to target word
|
||||
* @param[in] bit bit number within the word
|
||||
*/
|
||||
static inline void bit_set32(volatile uint32_t *ptr, uint8_t bit)
|
||||
{
|
||||
*((volatile uint32_t *)bitband_addr(ptr, bit)) = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set a single bit in the 16 bit word pointed to by @p ptr
|
||||
*
|
||||
* The effect is the same as for the following snippet:
|
||||
*
|
||||
* @code{c}
|
||||
* *ptr |= (1 << bit);
|
||||
* @endcode
|
||||
*
|
||||
* There is a read-modify-write cycle occurring within the core, but this cycle
|
||||
* is atomic and can not be disrupted by IRQs
|
||||
*
|
||||
* @param[in] ptr pointer to target word
|
||||
* @param[in] bit bit number within the word
|
||||
*/
|
||||
static inline void bit_set16(volatile uint16_t *ptr, uint8_t bit)
|
||||
{
|
||||
*((volatile uint16_t *)bitband_addr(ptr, bit)) = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set a single bit in the 8 bit byte pointed to by @p ptr
|
||||
*
|
||||
* The effect is the same as for the following snippet:
|
||||
*
|
||||
* @code{c}
|
||||
* *ptr |= (1 << bit);
|
||||
* @endcode
|
||||
*
|
||||
* There is a read-modify-write cycle occurring within the core, but this cycle
|
||||
* is atomic and can not be disrupted by IRQs
|
||||
*
|
||||
* @param[in] ptr pointer to target byte
|
||||
* @param[in] bit bit number within the byte
|
||||
*/
|
||||
static inline void bit_set8(volatile uint8_t *ptr, uint8_t bit)
|
||||
{
|
||||
*((volatile uint8_t *)bitband_addr(ptr, bit)) = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Clear a single bit in the 32 bit word pointed to by @p ptr
|
||||
*
|
||||
* The effect is the same as for the following snippet:
|
||||
*
|
||||
* @code{c}
|
||||
* *ptr &= ~(1 << bit);
|
||||
* @endcode
|
||||
*
|
||||
* There is a read-modify-write cycle occurring within the core, but this cycle
|
||||
* is atomic and can not be disrupted by IRQs
|
||||
*
|
||||
* @param[in] ptr pointer to target word
|
||||
* @param[in] bit bit number within the word
|
||||
*/
|
||||
static inline void bit_clear32(volatile uint32_t *ptr, uint8_t bit)
|
||||
{
|
||||
*((volatile uint32_t *)bitband_addr(ptr, bit)) = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Clear a single bit in the 16 bit word pointed to by @p ptr
|
||||
*
|
||||
* The effect is the same as for the following snippet:
|
||||
*
|
||||
* @code{c}
|
||||
* *ptr &= ~(1 << bit);
|
||||
* @endcode
|
||||
*
|
||||
* There is a read-modify-write cycle occurring within the core, but this cycle
|
||||
* is atomic and can not be disrupted by IRQs
|
||||
*
|
||||
* @param[in] ptr pointer to target word
|
||||
* @param[in] bit bit number within the word
|
||||
*/
|
||||
static inline void bit_clear16(volatile uint16_t *ptr, uint8_t bit)
|
||||
{
|
||||
*((volatile uint16_t *)bitband_addr(ptr, bit)) = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Clear a single bit in the 8 bit byte pointed to by @p ptr
|
||||
*
|
||||
* The effect is the same as for the following snippet:
|
||||
*
|
||||
* @code{c}
|
||||
* *ptr &= ~(1 << bit);
|
||||
* @endcode
|
||||
*
|
||||
* There is a read-modify-write cycle occurring within the core, but this cycle
|
||||
* is atomic and can not be disrupted by IRQs
|
||||
*
|
||||
* @param[in] ptr pointer to target byte
|
||||
* @param[in] bit bit number within the byte
|
||||
*/
|
||||
static inline void bit_clear8(volatile uint8_t *ptr, uint8_t bit)
|
||||
{
|
||||
*((volatile uint8_t *)bitband_addr(ptr, bit)) = 0;
|
||||
}
|
||||
|
||||
/** @} */
|
||||
|
||||
#else /* CPU_HAS_BITBAND */
|
||||
/* CPU does not have bitbanding, fall back to plain C */
|
||||
static inline void bit_set32(volatile uint32_t *ptr, uint8_t bit)
|
||||
{
|
||||
*ptr |= (1 << (bit));
|
||||
}
|
||||
|
||||
static inline void bit_set16(volatile uint16_t *ptr, uint8_t bit)
|
||||
{
|
||||
*ptr |= (1 << (bit));
|
||||
}
|
||||
|
||||
static inline void bit_set8(volatile uint8_t *ptr, uint8_t bit)
|
||||
{
|
||||
*ptr |= (1 << (bit));
|
||||
}
|
||||
|
||||
static inline void bit_clear32(volatile uint32_t *ptr, uint8_t bit)
|
||||
{
|
||||
*ptr &= ~(1 << (bit));
|
||||
}
|
||||
|
||||
static inline void bit_clear16(volatile uint16_t *ptr, uint8_t bit)
|
||||
{
|
||||
*ptr &= ~(1 << (bit));
|
||||
}
|
||||
|
||||
static inline void bit_clear8(volatile uint8_t *ptr, uint8_t bit)
|
||||
{
|
||||
*ptr &= ~(1 << (bit));
|
||||
}
|
||||
|
||||
#endif /* CPU_HAS_BITBAND */
|
||||
|
||||
#endif /* !BITBAND_FUNCTIONS_PROVIDED */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* BIT_H */
|
||||
/** @} */
|
||||
Loading…
x
Reference in New Issue
Block a user