Use this forum to chat about hardware specific topics for the ESP8266 (peripherals, memory, clocks, JTAG, programming)

User avatar
By tinhead
#1278 this is actually described in "6-ESP8266 FAQ文档_v0.2.pdf" (under GPIO, shift register).

I tested it once, however with org. defines (here for GPIO4):

WRITE_PERI_REG(PERIPHS_GPIO_BASEADDR+GPIO_OUT_W1TS_ADDRESS,BIT4);
WRITE_PERI_REG(PERIPHS_GPIO_BASEADDR+GPIO_OUT_W1TC_ADDRESS,BIT4);

one can of course use predefined macro (and that is described in the pdf above):

GPIO_REG_WRITE(GPIO_OUT_W1TS_ADDRESS,BIT4);
GPIO_REG_WRITE(GPIO_OUT_W1TC_ADDRESS,BIT4)

(a quick look into eagle_soc.h, #define GPIO_REG_WRITE(reg, val) WRITE_PERI_REG(PERIPHS_GPIO_BASEADDR + reg, val))

Anyway, the result is of course exact the same.

When writing directly to the out register one can toggle a PIN with ~5714kHz instead of ~825kHz, which was the
case when using GPIO_OUTPUT_SET(GPIO_ID_PIN(4), 1) instead.

One need to know that only GPIO0 to GPIO15 can be accessed like that, to use GPIO16 one need to use the slow API.
User avatar
By Bert
#1280
mamalala wrote:In your C code or an include file you can then define these as external variables to access them:

Code: Select allextern uint32_t PIN_OUT;
extern uint32_t PIN_OUT_SET;
extern uint32_t PIN_OUT_CLEAR;

extern uint32_t PIN_DIR;
extern uint32_t PIN_DIR_OUTPUT;
extern uint32_t PIN_DIR_INPUT;

extern uint32_t PIN_IN;

extern uint32_t PIN_0;
extern uint32_t PIN_2;

You'd better mark those integers as volatile, or the compiler may just optimize away any access to them.
User avatar
By mamalala
#1281
Bert wrote:You'd better mark those integers as volatile, or the compiler may just optimize away any access to them.


True, thanks. I was just poking around and wanted to share that info quickly.

Greetings,

Chris
User avatar
By mamalala
#1283
Squonk wrote:Thanks Crhis for sharing!

But why don't you sue the defines from "eagle_soc.h" as-is? They provide all the required access to the hardware peripheral registers, without having to redefine them in the linker script.

These are only pre-processor statements, so even if they look over-complicated, they will be reduced to the just the correct register address when compiled (actually pre-processed).

As for your "PIN_0" and "PIN_2" above, I guess that this is something similar to the ARM Cortex "bit banding" (NOT bit banging!) feature, that allows you to access bits as memory locations, saving you all the pain to shift/mask bits within words to access them from everywhere in your code. Thus, once configured as either input or output, you can access say PIN_0 by reading or writing directly to this location.


Well, i'm a fan of using names that more or less directly tell what they do. Sure, calling it "PIN_*" isn't the best either, should be "GPIO_*" instead. But still, the names used in the macros in eagle_soc.h are rather awkward and clumsy to write. Also, i'm sure that many people go by the gpio_output_set(), which is calling a function in ROM instead of being just another macro accessing the registers directly. Last but not least, peeking and poking around at that new chip is fun ;)

As for the other two registers, yes and no. Yes because they directly corrospond to a given pin. No because just writing 0/1 to it does not really change the output state of the pin, at least not the way one would expect. For example, PIN_2 is obviously masked internally. You can "only" set bits in a bitmaks of 0000.0000.0000.0001.1111.1000.0101. Now, for just setting an output state, those are too many bits. I'm sure there is more to them than just setting the output.

Greetings,

Chris

Edit: I mean, reding the include files for that chip is really a mess. Take the GPIO_REG_WRITE example. For one, it doesn't directly say that it will also toggle pins. Then, if you look it up you see that it expands to WRITE_PERI_REG(). Which then more or less finally expands to (*((volatile uint32_t *)ETS_UNCACHED_ADDR(addr))) = (uint32_t)(val). And the ETS_UNCACHED_ADDR() in that is rather superfluos, since that ends up as just (addr).

Maybe it's just me, but i think that a "PROVIDE(PIN_OUT_SET = 0x60000304);" in the .ld and an "extern volatile uint32_t PIN_OUT_SET;" in the source or preferably an include makes it much easier to follow what is going on. Sometimes i think they deliberately obfuscated their include files...