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

User avatar
By RFZ
#86492 Hey,
I'm using UART1 on the ESP8266 to generate a precise timed pulse on IO2 / D4 in hardware.
In my code I need to know if the pulse is finished or not before I accidentally start a new one.
I found that when using IO2 with UART, the pin level cannot be read by GPI / digitalRead().
Also, despite esp8266_peri.h defining that U1S should reflect the pin level, it does not work...

Code: Select all//UART 1 Registers
#define U1F   ESP8266_REG(0xF00) //UART FIFO
#define U1S   ESP8266_REG(0xF1C) //STATUS

//UART STATUS Registers Bits
#define USTX    31 //TX PIN Level


This is my test code:

Code: Select all#include <Arduino.h>
#include <Ticker.h>
Ticker tick;
// U1 TX: GPIO_02 / D4
#define P_DEBUG 14 // D5
#define DEBUG_HIGH GPOS = 1<<P_DEBUG
#define DEBUG_LOW GPOC = 1<<P_DEBUG

void ICACHE_RAM_ATTR send() {
  DEBUG_HIGH;
  DEBUG_LOW;
  U1F = 0x80;
}

void setup() {
  Serial1.begin(9600);
  pinMode(P_DEBUG,OUTPUT);
  U1S |= 0x01 << USTXC;
  U1D = 10*100;
  tick.attach(0.01, send);
}

void loop() {
  if(U1S & (1<<USTX)) DEBUG_HIGH;
  else DEBUG_LOW;
  if(GPI & (1<<2)) DEBUG_HIGH;
  else DEBUG_LOW;
}

// What I get:
// IO_02: ‾‾‾‾|_______________|‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾|___
// DEBUG: ____|_________________________________|___
// What I expect: Debug HIGH/PULSING on either IO_02 LOW or HIGH


Am I missing something?
Is there a way to find out when IO2 is HIGH again after the LOW pulse?

Thx!
User avatar
By eriksl
#86535 There is a mux between GPIO and UART, so, yeah, you can't read the UART output from GPIO. Either one of them is active, never both.

If you need to know whether the UART (queue) is finished, check the write queue length. You could, in theory, even do it with an interrupt, but I think in your case that will yield too much latency.

Or leave out the UART altogether and implement a bit-banging alternative, for maximum control.
User avatar
By RFZ
#86627
eriksl wrote:There is a mux between GPIO and UART, so, yeah, you can't read the UART output from GPIO. Either one of them is active, never both.


Thx, already guessed that this is the case...

eriksl wrote:If you need to know whether the UART (queue) is finished, check the write queue length. You could, in theory, even do it with an interrupt, but I think in your case that will yield too much latency.


You mean USTXC? That actually won't change... If you have a look at my example code, I only set USTXC once and am able to generate unlimited pulses just by filling U1F.

eriksl wrote:Or leave out the UART altogether and implement a bit-banging alternative, for maximum control.


No :p I need the UART because I want to generate a precise pulse that won't be disturbed by an interrupt but also won't lock the CPU :)

For now I save the time when I start the pulse and check if the time passed was long enough before I start the next pulse...
User avatar
By eriksl
#86628 I don't know the mnemonics you're using. You mean these:

UART_TXFIFO_CNT = 0x000000ff, /* REG_UART_BASE(i) + 0x20) */

that's what I was referring to. This value should auto-increment each time you add a byte to the queue and auto-decrement for each byte actually sent. So it should go 0 -> 1 -> 0 if you send one byte.

If you need real precise control of the bit pattern, you may need to look at alternatives and how to "abuse" them, like the SPI interface or the I2S interface.

Actually there may very well be a register that mirrors the pin, but as usual it's not documented so we'll never know. Blame Espressif.