Loading...
Searching...
No Matches
atomic_utils_arch.h
Go to the documentation of this file.
1/*
2 * Copyright (C) 2020 Otto-von-Guericke-Universität Magdeburg
3 *
4 * This file is subject to the terms and conditions of the GNU Lesser General
5 * Public License v2.1. See the file LICENSE in the top level directory for more
6 * details.
7 */
8
19#ifndef ATOMIC_UTILS_ARCH_H
20#define ATOMIC_UTILS_ARCH_H
21#ifndef DOXYGEN
22
23#include "bit.h"
24#include "periph_cpu.h"
25
26#ifdef __cplusplus
27extern "C" {
28#endif
29
30/* clang provides no built-in atomic access to regular variables */
31#ifndef __clang__
32
33#define HAS_ATOMIC_LOAD_U8
34static inline uint8_t atomic_load_u8(const volatile uint8_t *var)
35{
36 return __atomic_load_1(var, __ATOMIC_SEQ_CST);
37}
38
39#define HAS_ATOMIC_LOAD_U16
40static inline uint16_t atomic_load_u16(const volatile uint16_t *var)
41{
42 return __atomic_load_2(var, __ATOMIC_SEQ_CST);
43}
44
45#define HAS_ATOMIC_LOAD_U32
46static inline uint32_t atomic_load_u32(const volatile uint32_t *var)
47{
48 return __atomic_load_4(var, __ATOMIC_SEQ_CST);
49}
50
51#define HAS_ATOMIC_STORE_U8
52static inline void atomic_store_u8(volatile uint8_t *dest, uint8_t val)
53{
54 __atomic_store_1(dest, val, __ATOMIC_SEQ_CST);
55}
56
57#define HAS_ATOMIC_STORE_U16
58static inline void atomic_store_u16(volatile uint16_t *dest, uint16_t val)
59{
60 __atomic_store_2(dest, val, __ATOMIC_SEQ_CST);
61}
62
63#define HAS_ATOMIC_STORE_U32
64static inline void atomic_store_u32(volatile uint32_t *dest, uint32_t val)
65{
66 __atomic_store_4(dest, val, __ATOMIC_SEQ_CST);
67}
68
69#endif /* __clang__ */
70
71#if CPU_HAS_SRAM_BITBAND
72#define HAS_ATOMIC_BIT
73
74typedef volatile uint32_t *atomic_bit_u8_t;
75typedef volatile uint32_t *atomic_bit_u16_t;
76typedef volatile uint32_t *atomic_bit_u32_t;
77typedef volatile uint32_t *atomic_bit_u64_t;
78
79static inline void __attribute__((always_inline)) _bit_barrier_pre(void)
80{
81 __asm__ volatile ("" : : : "memory");
82}
83
84static inline void __attribute__((always_inline)) _bit_barrier_post(void)
85{
86 __asm__ volatile ("" : : : "memory");
87}
88
89static inline bool _is_addr_valid_for_bitbanding(volatile void *_addr)
90{
91 /* SRAM bit-band region goes from 0x20000000 to 0x200fffff,
92 * peripheral bit-band region goes from 0x40000000 to 0x400fffff */
93 uintptr_t addr = (uintptr_t)_addr;
94 if ((addr < 0x20000000UL) || (addr > 0x400fffffUL)) {
95 return false;
96 }
97
98 if ((addr >= 0x200fffffUL) && (addr < 0x40000000UL)) {
99 return false;
100 }
101
102 return true;
103}
104
105static inline atomic_bit_u8_t atomic_bit_u8(volatile uint8_t *dest, uint8_t bit)
106{
107 assert(_is_addr_valid_for_bitbanding(dest));
108 return bitband_addr(dest, bit);
109}
110
111static inline atomic_bit_u16_t atomic_bit_u16(volatile uint16_t *dest, uint8_t bit)
112{
113 assert(_is_addr_valid_for_bitbanding(dest));
114 return bitband_addr(dest, bit);
115}
116
117static inline atomic_bit_u32_t atomic_bit_u32(volatile uint32_t *dest, uint8_t bit)
118{
119 assert(_is_addr_valid_for_bitbanding(dest));
120 return bitband_addr(dest, bit);
121}
122
123static inline atomic_bit_u64_t atomic_bit_u64(volatile uint64_t *dest, uint8_t bit)
124{
125 assert(_is_addr_valid_for_bitbanding(dest));
126 return bitband_addr(dest, bit);
127}
128
129static inline void atomic_set_bit_u8(atomic_bit_u8_t bit)
130{
131 _bit_barrier_pre();
132 *bit = 1;
133 _bit_barrier_post();
134}
135
136static inline void atomic_set_bit_u16(atomic_bit_u16_t bit)
137{
138 _bit_barrier_pre();
139 *bit = 1;
140 _bit_barrier_post();
141}
142
143static inline void atomic_set_bit_u32(atomic_bit_u32_t bit)
144{
145 _bit_barrier_pre();
146 *bit = 1;
147 _bit_barrier_post();
148}
149
150static inline void atomic_set_bit_u64(atomic_bit_u64_t bit)
151{
152 _bit_barrier_pre();
153 *bit = 1;
154 _bit_barrier_post();
155}
156
157static inline void atomic_clear_bit_u8(atomic_bit_u8_t bit)
158{
159 _bit_barrier_pre();
160 *bit = 0;
161 _bit_barrier_post();
162}
163static inline void atomic_clear_bit_u16(atomic_bit_u16_t bit)
164{
165 _bit_barrier_pre();
166 *bit = 0;
167 _bit_barrier_post();
168}
169
170static inline void atomic_clear_bit_u32(atomic_bit_u32_t bit)
171{
172 _bit_barrier_pre();
173 *bit = 0;
174 _bit_barrier_post();
175}
176
177static inline void atomic_clear_bit_u64(atomic_bit_u64_t bit)
178{
179 _bit_barrier_pre();
180 *bit = 0;
181 _bit_barrier_post();
182}
183
184#endif /* CPU_HAS_BITBAND */
185
186#ifdef __cplusplus
187}
188#endif
189
190#endif /* DOXYGEN */
191#endif /* ATOMIC_UTILS_ARCH_H */
#define assert(cond)
abort the program if assertion is false
Definition assert.h:136
Bit access macros with bit-banding support for Cortex-M based CPUs.
static volatile void * bitband_addr(volatile void *ptr, uintptr_t bit)
Convert bit band region address and bit number to bit band alias address.
Definition bit.h:74
static atomic_bit_u32_t atomic_bit_u32(volatile uint32_t *dest, uint8_t bit)
Create a reference to a bit in an uint32_t
static void atomic_store_u8(volatile uint8_t *dest, uint8_t val)
Store an uint8_t atomically.
static void atomic_set_bit_u8(atomic_bit_u8_t bit)
Atomic version of *dest |= (1 << bit)
static atomic_bit_u64_t atomic_bit_u64(volatile uint64_t *dest, uint8_t bit)
Create a reference to a bit in an uint64_t
static void atomic_clear_bit_u32(atomic_bit_u32_t bit)
Atomic version of *dest &= ~(1 << bit)
static uint32_t atomic_load_u32(const volatile uint32_t *var)
Load an uint32_t atomically.
static uint16_t atomic_load_u16(const volatile uint16_t *var)
Load an uint16_t atomically.
static void atomic_set_bit_u64(atomic_bit_u64_t bit)
Atomic version of *dest |= (1 << bit)
static void atomic_clear_bit_u8(atomic_bit_u8_t bit)
Atomic version of *dest &= ~(1 << bit)
static uint8_t atomic_load_u8(const volatile uint8_t *var)
Load an uint8_t atomically.
static atomic_bit_u8_t atomic_bit_u8(volatile uint8_t *dest, uint8_t bit)
Create a reference to a bit in an uint8_t
static void atomic_clear_bit_u16(atomic_bit_u16_t bit)
Atomic version of *dest &= ~(1 << bit)
static void atomic_store_u16(volatile uint16_t *dest, uint16_t val)
Store an uint16_t atomically.
static void atomic_store_u32(volatile uint32_t *dest, uint32_t val)
Store an uint32_t atomically.
static atomic_bit_u16_t atomic_bit_u16(volatile uint16_t *dest, uint8_t bit)
Create a reference to a bit in an uint16_t
static void atomic_set_bit_u32(atomic_bit_u32_t bit)
Atomic version of *dest |= (1 << bit)
static void atomic_clear_bit_u64(atomic_bit_u64_t bit)
Atomic version of *dest &= ~(1 << bit)
static void atomic_set_bit_u16(atomic_bit_u16_t bit)
Atomic version of *dest |= (1 << bit)
Type specifying a bit in an uint16_t
Type specifying a bit in an uint32_t
Type specifying a bit in an uint64_t
Type specifying a bit in an uint8_t