ADC  8.0
atomic.h
1 #ifndef ATOMIC_H
2 #define ATOMIC_H
3 
4 // kinetis.h has the following types for addresses: uint32_t, uint16_t, uint8_t, int32_t, int16_t
5 
7 namespace atomic
8 {
10  /* Clear bit in address (make it zero), set bit (make it one), or return the value of that bit
11  * We can change this functions depending on the board.
12  * Teensy 3.x use bitband while Teensy LC has a more advanced bit manipulation engine.
13  */
14  #if defined(KINETISK) // Teensy 3.x
15 
21  template<typename T>
22  __attribute__((always_inline)) inline volatile T& bitband_address(volatile T& reg, uint8_t bit) {
23  return (*(volatile T*)(((uint32_t)&reg - 0x40000000)*32 + bit*4 + 0x42000000));
24  }
25 
26  template<typename T>
27  __attribute__((always_inline)) inline void setBit(volatile T& reg, uint8_t bit) {
28  bitband_address(reg, bit) = 1;
29  }
30  template<typename T>
31  __attribute__((always_inline)) inline void setBitFlag(volatile T& reg, uint32_t flag) {
32  // 31-__builtin_clzl(flag) = gets bit number in flag
33  // __builtin_clzl works for long ints, which are guaranteed by standard to be at least 32 bit wide.
34  // there's no difference in the asm emitted.
35  bitband_address(reg, 31-__builtin_clzl(flag)) = 1;
36  }
37 
38  template<typename T>
39  __attribute__((always_inline)) inline void clearBit(volatile T& reg, uint8_t bit) {
40  bitband_address(reg, bit) = 0;
41  }
42  template<typename T>
43  __attribute__((always_inline)) inline void clearBitFlag(volatile T& reg, uint32_t flag) {
44  bitband_address(reg, 31-__builtin_clzl(flag)) = 0;
45  }
46 
47  template<typename T>
48  __attribute__((always_inline)) inline void changeBit(volatile T& reg, uint8_t bit, bool state) {
49  bitband_address(reg, bit) = state;
50  }
51  template<typename T>
52  __attribute__((always_inline)) inline void changeBitFlag(volatile T& reg, uint32_t flag, bool state) {
53  bitband_address(reg, 31-__builtin_clzl(flag)) = state;
54  }
55 
56  template<typename T>
57  __attribute__((always_inline)) inline volatile bool getBit(volatile T& reg, uint8_t bit) {
58  return (volatile bool)bitband_address(reg, bit);
59  }
60  template<typename T>
61  __attribute__((always_inline)) inline volatile bool getBitFlag(volatile T& reg, uint32_t flag) {
62  return (volatile bool)bitband_address(reg, 31-__builtin_clzl(flag));
63  }
64 
65  #elif defined(KINETISL) // Teensy LC
66  // bit manipulation engine
67  //#define ADC_SETBIT_ATOMIC(reg, bit) (*(uint32_t *)(((uint32_t)&(reg) - 0xF8000000) | 0x48000000) = 1 << (bit)) // OR
68  //#define ADC_CLRBIT_ATOMIC(reg, bit) (*(uint32_t *)(((uint32_t)&(reg) - 0xF8000000) | 0x44000000) = ~(1 << (bit))) // XOR
69 
70  template<typename T>
71  __attribute__((always_inline)) inline void setBit(volatile T& reg, uint8_t bit) {
72  //temp = *(uint32_t *)((uint32_t)(reg) | (1<<26) | (bit<<21)); // LAS
73  *(volatile T*)((uint32_t)(&reg) | (1<<27)) = 1<<bit; // OR
74  }
75  template<typename T>
76  __attribute__((always_inline)) inline void setBitFlag(volatile T& reg, uint32_t flag) {
77  //temp = *(uint32_t *)((uint32_t)(reg) | (1<<26) | (bit<<21)); // LAS
78  *(volatile T*)((uint32_t)(&reg) | (1<<27)) = flag; // OR
79  }
80 
81  template<typename T>
82  __attribute__((always_inline)) inline void clearBit(volatile T& reg, uint8_t bit) {
83  //temp = *(uint32_t *)((uint32_t)(reg) | (3<<27) | (bit<<21)); // LAC
84  *(volatile T*)((uint32_t)(&reg) | (1<<26)) = ~(1<<bit); // AND
85  }
86  template<typename T>
87  __attribute__((always_inline)) inline void clearBitFlag(volatile T& reg, uint32_t flag) {
88  //temp = *(uint32_t *)((uint32_t)(reg) | (3<<27) | (bit<<21)); // LAC
89  *(volatile T*)((uint32_t)(&reg) | (1<<26)) = ~flag; // AND
90  }
91 
92  template<typename T>
93  __attribute__((always_inline)) inline void changeBit(volatile T& reg, uint8_t bit, bool state) {
94  //temp = *(uint32_t *)((uint32_t)(reg) | ((3-2*!!state)<<27) | (bit<<21)); // LAS/LAC
95  state ? setBit(reg, bit) : clearBit(reg, bit);
96  }
97  template<typename T>
98  __attribute__((always_inline)) inline void changeBitFlag(volatile T& reg, uint32_t flag, bool state) {
99  //temp = *(uint32_t *)((uint32_t)(reg) | ((3-2*!!state)<<27) | (bit<<21)); // LAS/LAC
100  state ? setBitFlag(reg, flag) : clearBitFlag(reg, flag);
101  }
102 
103  template<typename T>
104  __attribute__((always_inline)) inline volatile bool getBit(volatile T& reg, uint8_t bit) {
105  return (volatile bool)*(volatile T *)((uint32_t)(&reg) | (1<<28) | (bit<<23) ); // UBFX
106  }
107  template<typename T>
108  __attribute__((always_inline)) inline volatile bool getBitFlag(volatile T& reg, uint32_t flag) {
109  return (volatile bool)*(volatile T *)((uint32_t)(&reg) | (1<<28) | ((31-__builtin_clzl(flag))<<23) ); // UBFX
110  }
111 
112  #endif
113 
114 }
115 
116 #endif // ATOMIC_H
Atomic set, clear, change, or get bit in a register.
Definition: atomic.h:7