apache / nuttx

Apache NuttX is a mature, real-time embedded operating system (RTOS)
https://nuttx.apache.org/
Apache License 2.0
2.51k stars 1.06k forks source link

Using UART with ESP32 #7150

Open SrivamsiMalladi opened 1 year ago

SrivamsiMalladi commented 1 year ago

I would like to use NuttX with ESP32 and I am looking for a UART driver. I see that there is the nuttx/include/nuttx/serial/serial.h file where I find the uart_setup(dev), uart_send(dev, ch) functions.

So what is the dev here? I figured out that I can pass CONSOLE_DEV from nuttx/arch/xtensa/src/esp32/esp32_serial.c, but there is a esp32_serial.h file missing which is why, I think, I keep getting this error

src/esp32_uart_driver.c:65:16: error: 'CONSOLE_DEV' undeclared (first use in this function)
   uart_setup(&(CONSOLE_DEV));

Please let me know if I have understood it incorrectly or if I am using the wrong files/functions thinking they are UART driver.

SrivamsiMalladi commented 1 year ago

I found https://nuttx.apache.org/docs/latest/components/drivers/character/serial.html where it says

Each serial device driver must implement an instance of struct uart_ops_s

which is implemented in the nuttx/arch/xtensa/src/esp32/esp32_serial.c in the case of ESP32, but I cannot use it because of the error I mentioned above.

acassis commented 1 year ago

@SrivamsiMalladi you need to define which UART will be your serial console, you do it on menuconfig ($ make menuconfig) then if you need UART0 as serial console your need to enable the symbol: CONFIG_UART0_SERIAL_CONSOLE You can search for the symbols just pressing "/" inside the menuconfig and typing the SYMBOL you want to search!

SrivamsiMalladi commented 1 year ago

The UART0 is chosen as serial console by default (Maybe because I am using the nsh config of ESP32). Also, when I check the .config file, I can see CONFIG_UART0_SERIAL_CONSOLE=y, so it is configured! The problem is that the definition of CONSOLE_DEV is not happening.

acassis commented 1 year ago

Please look the inside esp32_serial.c file, since CONFIG_UART0_SERIAL_CONSOLE is defined, the only way to CONSOLE_DEV be undefined is if USE_SERIALDRIVER is undefined. And this symbol is defined inside arch/xtensa/src/common/xtensa.h Probably you disabled CONFIG_DEV_CONSOLE or enabled CONFIG_CONSOLE_SYSLOG.

In order to get better results with NuttX you need to learn how to navigate inside the source code and search for symbols! :-)

SrivamsiMalladi commented 1 year ago

Apparently CONFIG_DEV_CONSOLE is enabled and CONFIG_CONSOLE_SYSLOG is disabled, but still CONSOLE_DEV is undefined.

acassis commented 1 year ago

@SrivamsiMalladi are you using the esp32-devkitc board or did you create your own board based on it? Seems like something is mis-defined/mis-configured. Try to figure-out if USE_SERIALDRIVER is undefined and then find why. You can force an error to confirm it:

#ifndef USE_SERIALDRIVER
#error "USE_SERIALDRIVER is not defined, please fix it to get serial console working"
#endif
SrivamsiMalladi commented 1 year ago

I am using adafruit huzzah32 - esp32 feather board which is similar to esp32-devkitc. (Both use WROOM32. Also, huzzah32 works fine with ESP-IDF when configured as esp32-devkitc) The USE_SERIALDRIVER is in fact defined when tested at the end of esp32_serial.c with the preprocessor conditional inclusions you have suggested. I also check if CONSOLE_DEV is defined too by the end of esp32_serial.c and it is, but it is not accessible in the driver I am trying to develop (nuttx/boards/xtensa/esp32/common/src/esp32_uart_driver.c). Is there a working example that uses the uart_setup(uart_dev_t *dev) from serial.h that you can direct me to, so that I can have a look at it and understand how it is configured, or to check if I am doing it differently? That would be really great.

acassis commented 1 year ago

@SrivamsiMalladi you don't need to create a esp32_uart_driver.c because the uart driver is already created inside arch/xtensa/! All you need to do it use the device from userspace. So, your application will open the /dev/ttyS1 (because /dev/ttyS0 is used as console) and read/write to it. This is the same way as things works on Linux, FreeBSD, MacOS, etc. Search inside apps/ and you will find a lot of examples.

acassis commented 1 year ago

Did you enable "[*] UART 1" in the menuconfig? Otherwise /dev/ttyS1 will not be created!

SrivamsiMalladi commented 1 year ago

you don't need to create a esp32_uart_driver.c because the uart driver is already created inside arch/xtensa/

Yea I saw that it is already available, but I am working on a custom UART driver, so wanted to create a separate driver wrapping the original driver.

your application will open the /dev/ttyS1 (because /dev/ttyS0 is used as console) and read/write to it.

Yea, I could get the UART to work this way with /dev/ttyS0 (UART0) (Need to try with /dev/ttyS1 or UART1), but I want to use the driver so that I need not rewrite the basic UART operations and interrupt methods.

Did you enable "[*] UART 1" in the menuconfig? Otherwise /dev/ttyS1 will not be created!

I did not enable it earlier. But after you told, I enabled it in the System Type > ESP32 peripheral Selection > [*] UART1. Even then the error 'CONSOLE_DEV' undeclared is occurring.

acassis commented 1 year ago

I suggest you to start with the basics, first clear everything:

$ make distclean

Then configure the board:

$ ./tools/configure.sh esp32-devkitc:nsh

Now compile/flash it:

$ make -j flash ESPTOOL_PORT=/dev/ttyUSB0

Use picocom/minicom/etc to see the nsh>

You should get UART0 working, then enable UART1 and compile/flash it again, you should see /dev/ttyS1

SrivamsiMalladi commented 1 year ago

Yes! I can see the /dev/ttyS1 after enabling UART1. But I the error 'CONSOLE_DEV' undeclared still exists when trying to use uart_setup(&CONSOLE_DEV);

acassis commented 1 year ago

I don't understand what exactly you are trying to do. If the code is creating /dev/ttyS0 and /dev/ttyS1 it means everything is correct. Why are you calling uart_setup(&CONSOLE_DEV)? I think console was already created, look /dev/console ! The console is registered using "esp32_setup(&CONSOLE_DEV);"

SrivamsiMalladi commented 1 year ago

@acassis, I got the /dev/ttySx to work. I can read and write to the /dev/ttyS1, for example, to send and receive messages over serial/UART. What I want to do is to use the predefined driver methods like uart_read(), uart_write() and also methods that deal with UART interrupts, so that I do not have to rewrite them again. This is why I am looking into using uart_setup() and other functions.

SrivamsiMalladi commented 1 year ago

My goal is to use interrupts with UART. For example, in ESP-IDF, the UART driver interrupts has several events like break detected or received data on rx line etc. I want to use them. Please let me know what I need to use to get this behavior. One thing I can think of to implement this is to have a task constantly running which continuously reads from /dev/ttySx. When something is read, the main thread is alerted about the data reception. Basically I am building the interrupt from scratch. Is there a better way to do it?