Enabling second UART in U-Boot - embedded-linux

I am working on a project with SAMA5D3-xplained board with CortexA5 processor and embedded Linux. I would like to send and receive some data via UART during U-Boot is running and before a kernel is loaded to the RAM. I have no idea what I should do. Should I add the second UART to U-Boot device tree source file? Should I change something in a board configuration file? Do you have any ideas on what steps I should take to achieve my goal? Thank you in advance for any help.
EDIT
I would like to use UART from U-Boot C code, not from U-Boot commands. I need to communicate with one of a peripheral device before the kernel is loaded to the RAM.

I assume that you are using the upstream U-Boot from https://source.denx.de/u-boot/u-boot.git.
The device-tree arch/arm/dts/at91-sama5d3_xplained.dts already contains the definitions for six different uarts called serial0 - serial5. serial0 is set in the /chosen node as the standard serial connection. You should be able to see all six devices with the 'dm tree' command.
The currently used UART can be switched by setting the stdin and stdout environment variables.
If you do not want to switch these variables, because you still want output on the default UART you will have to access the device driver. Unfortunately drivers/serial/serial-uclass.c does not yet export functions for this. But _serial_putc(), __serial_getc(), and __serial_tstc() should give you an idea how this is done.

Related

Flashing ESP32's memory without installing the whole IDF?

Problem
I'm looking for a way to flash an ESP32 module's memory without installing the whole IDF software suite.
Why
Because I want to integrate ESP32 onto a custom board along with a low-performance ARM-powered CPU which runs a tiny Linux distro (based on Debian), and I want to flash ESP32 from this tiny Linux distro.
I know I could use the bootloader, but who will upload the initial bootloader? I don't want to do extra steps, so my idea is to embed the ESP32 module onto my custom board, and let the Linux to flash it from factory-state (when it's flash is empty, ie. no preloaded bootloader). Or is the serial bootloader always preinstalled on all ESP32 modules (like on ESP-WROOM-32)?
Why I don't want to use IDF? Because I don't want to build or debug anything, I just want to flash myprogram.bin onto ESP32. Also, as the board is low-performance, it would take ages to download everything for running IDF.
Current state
The ESP32 module is now visible via UART (RX,TX,GND), and if I held low the GPIO0, it runs the bootloader (my current module is embedded onto a NodeMCU - but there is no USB connected, this is raw UART!):
rst:0x1 (POWERON_RESET),boot:0x3 (DOWNLOAD_BOOT(UART0/UART1/SDIO_REI_REO_V2))
waiting for download
Could I expect the same behavior (controlling GPIO0 for running the bootloader) for all ESP32 modules, or this works just because guys at NodeMCU preprogrammed already some bootloader onto it?
I'm looking for a way to flash this ESP32 preferrably without any python script.
The ESP32 has a first-stage bootloader in ROM capable of writing to Flash - that's what's printing your output. You can talk to it if you know the protocol - this is implemented by the Python scripts in ESP IDF. If you don't want to use the official implementation because it's too heavy, you'll have to write your own implementation of this protocol which scratches your specific itch. Fortunately it's more or less documented and you can likely reverse engineer any missing knowledge from official Python scripts.
Actually Espressif also provides a nice and small binary for flashing ESPs:
https://github.com/espressif/esp-serial-flasher
Serial flasher component provides portable library for flashing Espressif SoCs (ESP32, ESP32-S2, ESP8266) from other host microcontroller. Espressif SoCs are normally programmed via serial interface (UART). Port layer for given host microcontroller has to be implemented, if not available.
One more (but very important) addition:
You have to modify this repo to make it work correctly, and also you might have to upload not just your binary, but also bootloader and partition_table.

Can USB-OTG be used for U-Boot and Linux consoles?

I have a custom i.MX6Q-based board with working U-Boot and Linux (Ubuntu) setups. The micro and board have support for USB-OTG and one serial port; currently, the serial port serves the console for both U-Boot and Linux. However, we may need to use the serial port for another purpose, but we don't want to lose the console for U-Boot and Linux. Is it possible to use the USB-OTG port for the system console for both U-Boot and Linux?
I've done some research and found a couple of promising articles here and here, though the second article says this tidbit:
Unfortunately it won't work as system console as the gadget driver is loaded as a module, but we can use it for serial console.
I'm not sure I understand this, but it sounds like the method won't meet my needs, which is to use USB-OTG for both U-Boot and Linux system consoles. I did try these methods, but without luck, which may mean that U-Boot and Linux aren't built properly for the desired functionality.
So here are my questions:
Can this work for U-Boot?
Can this work for Linux?
Am I insane for contemplating this path?
For either, any guidance (e.g. tutorials, examples, etc.) would be greatly appreciated.
Thanks!
Can this work for U-Boot?
Yes, at least since U-Boot version 2008.10, the README file has stated:
Define the below if you wish to use the USB console.
CONFIG_USB_DEVICE
Define this to build a UDC device
CONFIG_USB_TTY
Define this to have a tty type of device available to
talk to the UDC device
CFG_CONSOLE_IS_IN_ENV
Define this if you want stdin, stdout &/or stderr to
be set to usbtty.
Note that these configuration symbols are not accessible using the menuconfig, and must be enabled in a configuration file.
Currently at least five boards use this U-Boot capability, based on the occurrence of CONFIG_USB_TTY in files in include/configs/, for example include/configs/ti_omap4_common.h.
This USB configuration requires non-default definitions for the stdin and stdout environment variables. Refer to the README documentation for the details.
Can this work for Linux?
Yes, Linux (at least since version 4.5) can have a serial console on a USB connection, either a USB-to-serial adapter on a host port or a USB serial gadget on a device port (using CDC/ACM).
For instance, in drivers/usb/gadget/Kconfig there's the selection:
config U_SERIAL_CONSOLE
bool "Serial gadget console support"
depends on USB_G_SERIAL
help
It supports the serial gadget can be used as a console.
In the Linux 5.7.8 kernel only two boards have default configurations that use this capability, for example see arch/arm/configs/aspeed_g4_defconfig.
Besides a proper configuration to build the necessary drivers, a serial-gadget console requires (1) the kernel parameter specification (e.g. console=ttyGS0,...), and (2) a login session initiated by a getty command (e.g. in the inittab file).
Am I insane for contemplating this path?
No comment.
Beware that should you encounter a kernel boot issue, the Linux serial-gadget console does not support earlycon nor earlyprintk capability.
Personally I prefer to use a serial link that is persistent regardless of the target board's state. That ensures the terminal emulator program does not complain about lost connections.
Addendum
Unfortunately this Linux console on a USB serial gadget does not display boot messages generated by the kernel (before the login prompt), even if all drivers are statically linked in to the kernel image.
Although the syslog has messages like
console [ttyGS0] enabled
g_serial gadget: g_serial ready
...
gs_open: ttyGS0 ((ptrval),(ptrval))
before the salient Freeing unused kernel memory message, the host side does not receive any console messages until userspace is active.
This shortcoming is also reported in this guide: https://linux-sunxi.org/USB_Gadget/Serial

How to setup GDB for kernel debug to view serial port activity?

Good day all!
I have an issue in code that I cannot find.
See here
Is it possible to setup GDB to see what the UART is getting in incoming serial data?
Thanks!
I'd suggest you to modify UART driver for Linux kernel and inside of this driver dump the incoming data. The GDB works in user space but you need to do this on the lower level - in UART driver. GDB has no access to registers of the physical device as the UART is.

Detect spi device from another driver

I have a Freescale imx.6q (arm) based board.
Hardware is configured with devicetree.
It had a change major incompatible change to timings and voltage for an onboard fpga, but these changes are invisible to the kernel.
The EE's tell us we shouldn't load the old fpga firmware for fear of damaging it. I would like to support both hardware from the same code (It is already causing confusion)
The solution I have thought of is this:
There are several new spi temperature sensors on the board. If I can read from one of those devices, I can infer that I need the new firmware.
How can I (in one driver) grab an spi device and then release it?
I suspect that I might be able to do something like this with device tree,
But I don't want to make the device unavailable.
Any ideas or examples of something like this being done?
After reading question i think your concern is how to add software support for more than one hardware.
If that is the case i think we can write two drivers supporting both hardware's with different configuration such as irq, voltage, register set etc.
So i will enable both drivers in Makefile and config file.
So at the time of boot when probe of drivers gets called we can check the hardware id by using spi_read command from driver.
If hardware id matches then driver probe gets successful and driver can be used to interact with hardware.
If spi_read fails then driver probe itself will fail.
I think this will do the trick.
EDIT (answer the question)
To detect use an SPI device from another driver use a reference to the device in the devicetree structure.
Short answer: add a reference to the spi device in your devices dts entry.
Slightly longer answer:
When adding spi to another device driver, you are effectively adding a subdevice, which may want its own driver. I have an FPGA which loads its firmware over (something close enough to be considered) SPI. I started with the idea of just treating the spi device as part of the larger driver, but the more work went into it, the more obvious it was that it is its own device, with a purpose and function that is distinct from the rest of the driver. I separated that code into its own driver.
Now instead of a reference to an SPI device, my driver just has a reference to an FPGA Manager device.
See line 98, 370 of https://github.com/d4ddi0/linux/blob/v4.12evi/arch/arm/boot/dts/imx6q-evi.dts
and
make sure the spi driver is loaded before your driver completes loading
My original answer to my question (for historical purposes):
What I ended up doing was using different devicetree files. The difference is know at initial install time (based on the serial number). The bootloader knows which dts filename to load.
There are multiple FPGA firmware versions and the right one is chosen based on the description in the dts.
This way, I can still update the driver and/or dts without breakage.
This works well in practice even though it does not detect anything at runtime.
One problem still exists, if I take an SD card from a new revision, and put it into an old one, the incorrect firmware will be loaded. To really solve this last problem, we've talked about adding an EEPROM to uniquely identify the hardware revision on future boards.

Easiest way to export board info in embedded linux

So I'm look at sysfs for this. I'm looking at making a module/daemon that can read i2c devices and a couple of other things and export information in the filesystem for our main application.
For instance one of our io expanders is used as a board id, its a tca7408 but I don't need a GPIO interface to it. I just need to read it as an input and export the 0xXX number as an ID for userspace applications.
Just to add to this... is there a way to add custom data to sysfs? Or export application data to files similar to the functionality of sysfs?
If all of your devices are on i2c I would recommend creating a library with an easy to use API, things such as:
BoardId_t getBoardId();
Then you can hide all the i2c details in the library and reuse it where needed.
http://elinux.org/Interfacing_with_I2C_Devices
I tend to only write device drivers for things that actually NEED device drivers, in this case i2c already has a device driver so you can just use it. This will make your code easier to port to different versions of the linux kernel, and even different operating systems, and there is no need to mess with sysfs either.

Resources