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