1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2024-12-29 04:50:03 +01:00

kinetis: Add Bit Manipulation Engine helpers

This commit is contained in:
Joakim Nohlgård 2017-03-19 17:29:12 +01:00
parent 18908667a3
commit ba76402d03
2 changed files with 265 additions and 0 deletions

256
cpu/kinetis/include/bme.h Normal file
View File

@ -0,0 +1,256 @@
/*
* 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.
*/
/**
* @defgroup cpu_kinetis_bme Kinetis Bit Manipulation Engine (BME)
* @ingroup cpu_kinetis
* @brief Macros for using decorated memory accesses with the Bit
* Manipulation Engine available in Kinetis Cortex-M0+ devices
*
* @{
* @file
* @brief Macro definitions for the Kinetis Bit Manipulation Engine (BME)
*
* @author Joakim Nohlgård <joakim.nohlgard@eistec.se>
*/
#ifndef BME_H
#define BME_H
#include <stdint.h>
#ifdef __cplusplus
extern "C"
{
#endif
/**
* @brief Tell bit.h that we provide CPU specific bit manipulation functions
*/
#define BITBAND_FUNCTIONS_PROVIDED 1
#define BME_AND_MASK (1 << 26) /**< AND decoration bitmask */
#define BME_OR_MASK (1 << 27) /**< OR decoration bitmask */
#define BME_XOR_MASK (3 << 26) /**< XOR decoration bitmask */
#define BME_LAC1_MASK(BIT) ((1 << 27) | ((BIT) << 21)) /**< Load-and-clear 1 bit */
#define BME_LAS1_MASK(BIT) ((3 << 26) | ((BIT) << 21)) /**< Load-and-set 1 bit */
/**
* @brief Bit field extraction bitmask
*
* @param bit LSB of the bitfield within the word/halfword/byte
* @param width Number of bits to extract
*/
#define BME_BF_MASK(bit, width) ((1 << 28) | ((bit) << 23) | (((width) - 1 ) << 19))
/**
* @brief Bit field address macro
*
* @pre The target address must lie within a part of the peripheral address
* space 0x40000000 - 0x40070000
*
* @param[in] ptr Pointer to target register
* @param[in] bit Location of the LSB of the bitfield within the register
* @param[in] width Width of the the bitfield, in bits
*
* @return bitfield address as an uintptr_t
*/
static inline volatile void *bme_bf_addr(volatile void *ptr, uintptr_t bit, uintptr_t width)
{
return (volatile void *)(((uintptr_t)ptr) | BME_BF_MASK(bit, width));
}
/**
* @brief Access a bitfield (32 bit load/store)
*
* This macro can be used both for store `(*bme_bitfield32(xxx) = y)` and
* load `(y = *bme_bitfield32(ptr, bit))`
*
* @pre The target address must lie within a part of the peripheral address
* space 0x40000000 - 0x40070000
*
* @param[in] ptr Pointer to target register
* @param[in] bit Location of the LSB of the bitfield within the register
* @param[in] width Width of the the bitfield, in bits
*
* @return bitfield extracted as a (modifiable) lvalue
*/
static inline volatile uint32_t *bme_bitfield32(volatile uint32_t *ptr, uint8_t bit, uint8_t width)
{
return (volatile uint32_t *)(bme_bf_addr(ptr, bit, width));
}
/**
* @brief Access a bitfield (16 bit load/store)
*
* This macro can be used both for store `(*bme_bitfield16(xxx) = y)` and
* load `(y = *bme_bitfield16(ptr, bit))`
*
* @pre The target address must lie within a part of the peripheral address
* space 0x40000000 - 0x40070000
*
* @param[in] ptr Pointer to target register
* @param[in] bit Location of the LSB of the bitfield within the register
* @param[in] width Width of the the bitfield, in bits
*
* @return bitfield extracted as a (modifiable) lvalue
*/
static inline volatile uint16_t *bme_bitfield16(volatile uint16_t *ptr, uint8_t bit, uint8_t width)
{
return (volatile uint16_t *)(bme_bf_addr(ptr, bit, width));
}
/**
* @brief Access a bitfield (8 bit load/store)
*
* This macro can be used both for store `(*bme_bitfield8(xxx) = y)` and
* load `(y = *bme_bitfield8(ptr, bit))`
*
* @pre The target address must lie within a part of the peripheral address
* space 0x40000000 - 0x40070000
*
* @param[in] ptr Pointer to target register
* @param[in] bit Location of the LSB of the bitfield within the register
* @param[in] width Width of the the bitfield, in bits
*
* @return bitfield extracted as a (modifiable) lvalue
*/
static inline volatile uint8_t *bme_bitfield8(volatile uint8_t *ptr, uint8_t bit, uint8_t width)
{
return (volatile uint8_t *)(bme_bf_addr(ptr, bit, width));
}
/* For compatibility with the M3/M4 bitbanding macros: */
/**
* @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 *)(((uintptr_t)ptr) | BME_OR_MASK)) = (uint32_t)((1ul << bit));
}
/**
* @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 *)(((uintptr_t)ptr) | BME_OR_MASK)) = (uint16_t)((1ul << bit));
}
/**
* @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 *)(((uintptr_t)ptr) | BME_OR_MASK)) = (uint8_t)((1ul << bit));
}
/**
* @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 *)(((uintptr_t)ptr) | BME_AND_MASK)) = (uint32_t)(~(1ul << bit));
}
/**
* @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 *)(((uintptr_t)ptr) | BME_AND_MASK)) = (uint16_t)(~(1ul << bit));
}
/**
* @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 *)(((uintptr_t)ptr) | BME_AND_MASK)) = (uint8_t)(~(1ul << bit));
}
#ifdef __cplusplus
}
#endif
#endif /* BME_H */
/** @} */

View File

@ -21,6 +21,15 @@
#include "cpu_conf_common.h"
#if (__CORTEX_M < 3)
/*
* Kinetis Cortex-M0+ devices have bit manipulation engine (BME) which provides
* the same functionality (and some more) as the bitband aliased memory found in
* Cortex-M3 and up
*/
#include "bme.h"
#endif
#ifdef __cplusplus
extern "C"
{