2121
2222#include < cstdint>
2323#include < cstring>
24+ #include < memory>
2425
2526// register names
2627#include " esp8266_peri.h"
@@ -43,10 +44,14 @@ namespace experimental {
4344 * Kept in a separate function to aid with precaching
4445 * PRECACHE_* saves having to make the function IRAM_ATTR.
4546 *
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+ *
4651 * Note: if porting to ESP32 mosi/miso bits are set in 2 registers, not 1.
4752 */
4853
49- #define PRELOAD_DST (DST,SRC )\
54+ #define PRELOAD_DST_SRC (DST,SRC )\
5055 __asm__ __volatile__ (\
5156 " mov %0, %1\n\t " \
5257 : " =r" (DST)\
@@ -61,13 +66,13 @@ namespace experimental {
6166 : "i"(SRC)\
6267 : "memory")
6368
64- #define PRELOAD_VAR (DST,SRC )\
69+ #define PRELOAD_VAL (DST,SRC )\
6570 decltype (SRC) DST;\
66- PRELOAD_DST (DST,SRC)
71+ PRELOAD_DST_SRC (DST,SRC)
6772
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)
7176
7277static SpiOpResult PRECACHE_ATTR
7378_SPICommand (uint32_t spiIfNum,
@@ -81,38 +86,38 @@ _SPICommand(uint32_t spiIfNum,
8186 // note that the function below only ever calls this one w/ spiIfNum==0
8287 // in case it is *really* necessary, preload spiIfNum as well
8388 #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))
8590
8691 // preload all required constants and functions into variables.
8792 // when modifying code below, always double-check the asm output
8893
8994 PRELOAD_IMMEDIATE (spi0cmd_addr, SPIADDR (SPI0CMD));
9095 PRELOAD_IMMEDIATE (spi1cmd_addr, SPIADDR (SPI1CMD));
9196 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);
9499 #define SPIREG (reg ) \
95100 (*VOLATILE_PTR (spibase + (SPIADDR (reg) - SPIADDR (SPI0CMD))))
96101
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);
99104
100- PRELOAD_VAR (fchip, flashchip);
105+ PRELOAD_VAL (fchip, flashchip);
101106
102107 PRELOAD_IMMEDIATE (spicmdusr, SPICMDUSR);
103108 PRELOAD_IMMEDIATE (saved_ps, 0 );
104109
105110 // also force 'pre_cmd' & 'spiu' mask constant to be loaded right now
106111 // (TODO write all of the preamble in asm directly?)
107- PRELOAD_VAR (pre_cmd, _pre_cmd);
112+ PRELOAD_VAL (pre_cmd, _pre_cmd);
108113
109114 PRELOAD_IMMEDIATE (pre_cmd_spiu_mask, ~(SPIUMOSI | SPIUMISO));
110115 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);
112117
113118 PRELOAD_IMMEDIATE (pre_cmd_spiu2_mask, ~0xFFFFu );
114119 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);
116121
117122 if (!spiIfNum) {
118123 // Only need to disable interrupts and precache when using SPI0
0 commit comments