21
21
22
22
#include < cstdint>
23
23
#include < cstring>
24
+ #include < memory>
24
25
25
26
// register names
26
27
#include " esp8266_peri.h"
@@ -43,10 +44,14 @@ namespace experimental {
43
44
* Kept in a separate function to aid with precaching
44
45
* PRECACHE_* saves having to make the function IRAM_ATTR.
45
46
*
47
+ * PRELOAD_* allows access to consts and external values
48
+ * through a different name, while also forcing immediate load.
49
+ * (but, note that compiler only knows about DST and SRC as dependencies)
50
+ *
46
51
* Note: if porting to ESP32 mosi/miso bits are set in 2 registers, not 1.
47
52
*/
48
53
49
- #define PRELOAD_DST (DST,SRC )\
54
+ #define PRELOAD_DST_SRC (DST,SRC )\
50
55
__asm__ __volatile__ (\
51
56
" mov %0, %1\n\t " \
52
57
: " =r" (DST)\
@@ -61,13 +66,13 @@ namespace experimental {
61
66
: "i"(SRC)\
62
67
: "memory")
63
68
64
- #define PRELOAD_VAR (DST,SRC )\
69
+ #define PRELOAD_VAL (DST,SRC )\
65
70
decltype (SRC) DST;\
66
- PRELOAD_DST (DST,SRC)
71
+ PRELOAD_DST_SRC (DST,SRC)
67
72
68
- #define PRELOAD_FUNC (DST,SRC )\
69
- decltype (& SRC) DST;\
70
- PRELOAD_DST (DST,SRC)
73
+ #define PRELOAD_PTR (DST,SRC )\
74
+ decltype (std::addressof( SRC) ) DST;\
75
+ PRELOAD_DST_SRC (DST,SRC)
71
76
72
77
static SpiOpResult PRECACHE_ATTR
73
78
_SPICommand (uint32_t spiIfNum,
@@ -81,38 +86,38 @@ _SPICommand(uint32_t spiIfNum,
81
86
// note that the function below only ever calls this one w/ spiIfNum==0
82
87
// in case it is *really* necessary, preload spiIfNum as well
83
88
#define VOLATILE_PTR (X ) reinterpret_cast <volatile uint32_t *>(X)
84
- #define SPIADDR (X ) const_cast <uint32_t *>(& (X))
89
+ #define SPIADDR (X ) const_cast <uint32_t *>(std::addressof (X))
85
90
86
91
// preload all required constants and functions into variables.
87
92
// when modifying code below, always double-check the asm output
88
93
89
94
PRELOAD_IMMEDIATE (spi0cmd_addr, SPIADDR (SPI0CMD));
90
95
PRELOAD_IMMEDIATE (spi1cmd_addr, SPIADDR (SPI1CMD));
91
96
uint32_t *spibase = spiIfNum
92
- ? reinterpret_cast <uint32_t *>(spi1cmd_addr)
93
- : reinterpret_cast <uint32_t *>(spi0cmd_addr);
97
+ ? reinterpret_cast <uint32_t *>(spi1cmd_addr)
98
+ : reinterpret_cast <uint32_t *>(spi0cmd_addr);
94
99
#define SPIREG (reg ) \
95
100
(*VOLATILE_PTR (spibase + (SPIADDR (reg) - SPIADDR (SPI0CMD))))
96
101
97
- PRELOAD_FUNC (SPI_write_enablep, SPI_write_enable);
98
- PRELOAD_FUNC (Wait_SPI_Idlep, Wait_SPI_Idle);
102
+ PRELOAD_PTR (SPI_write_enablep, SPI_write_enable);
103
+ PRELOAD_PTR (Wait_SPI_Idlep, Wait_SPI_Idle);
99
104
100
- PRELOAD_VAR (fchip, flashchip);
105
+ PRELOAD_VAL (fchip, flashchip);
101
106
102
107
PRELOAD_IMMEDIATE (spicmdusr, SPICMDUSR);
103
108
PRELOAD_IMMEDIATE (saved_ps, 0 );
104
109
105
110
// also force 'pre_cmd' & 'spiu' mask constant to be loaded right now
106
111
// (TODO write all of the preamble in asm directly?)
107
- PRELOAD_VAR (pre_cmd, _pre_cmd);
112
+ PRELOAD_VAL (pre_cmd, _pre_cmd);
108
113
109
114
PRELOAD_IMMEDIATE (pre_cmd_spiu_mask, ~(SPIUMOSI | SPIUMISO));
110
115
uint32_t _pre_cmd_spiu = spiu & pre_cmd_spiu_mask;
111
- PRELOAD_VAR (pre_cmd_spiu, _pre_cmd_spiu);
116
+ PRELOAD_VAL (pre_cmd_spiu, _pre_cmd_spiu);
112
117
113
118
PRELOAD_IMMEDIATE (pre_cmd_spiu2_mask, ~0xFFFFu );
114
119
uint32_t _pre_cmd_spiu2 = (spiu2 & pre_cmd_spiu2_mask) | pre_cmd;
115
- PRELOAD_VAR (pre_cmd_spiu2, _pre_cmd_spiu2);
120
+ PRELOAD_VAL (pre_cmd_spiu2, _pre_cmd_spiu2);
116
121
117
122
if (!spiIfNum) {
118
123
// Only need to disable interrupts and precache when using SPI0
0 commit comments