my dev environment: imx-6.1.55-2.2.1
(repo init -u https://github.com/nxp-imx/imx-manifest -b imx-linux-mickledore -m imx-6.1.55-2.2.1.xml)
<< u-boot log >>
U-Boot SPL 2023.04-lf_v2023.04+g49b102d9888 (Nov 21 2023 - 07:28:53 +0000)
DDR Initialization
DDRINFO: start DRAM init...
DDRINFO: DRAM rate 1600MTS
DDRINFO:ddrphy calibration done
DDRINFO: ddrmix config done
DDRINFO: end DRAM init...
SEC0: RNG instantiated
Normal Boot
Trying to boot from BOOTROM
Boot Stage: Primary boot
image offset 0x0, pagesize 0x200, ivt offset 0x0
NOTICE: Do not release JR0 to NS as it can be used by HAB
NOTICE: BL31: v2.8(release):lf-6.1.55-2.2.1-rc1-0-g08e9d4eef-dirty
NOTICE: BL31: Built : 06:43:30, Nov 21 2023
U-Boot 2023.04-lf_v2023.04+g49b102d9888 (Nov 21 2023 - 07:28:53 +0000)
CPU: i.MX8MNano UltraLite Quad rev1.0 1400 MHz (running at 1200 MHz)
CPU: Industrial temperature grade (-40C to 105C) at 30C
Reset cause: POR
Model: NXP i.MX8MNano DDR3L EVK board
DRAM: 992 MiB
tcpc_init: Can't find device id=0x52
setup_typec: tcpc port2 init failed, err=-19
tcpc_init: Can't find device id=0x50
setup_typec: tcpc port1 init failed, err=-19
Core: 199 devices, 27 uclasses, devicetree: separate
MMC: FSL_SDHC: 1, FSL_SDHC: 2
Loading Environment from MMC... Select HS400ES failed -5
Select HS400 failed -5
OK
In: serial
Out: serial
Err: serial
SEC0: RNG instantiated
Select HS400ES failed -5
Select HS400 failed -5
switch to partitions #0, OK
mmc2(part 0) is current device
flash target is MMC:2
Select HS400ES failed -5
Select HS400 failed -5
Net: ksz-switch switch@5f: ksz_i2c_probe switch@5f master:ethernet@30be0000
ksz-switch switch@5f: ksz_i2c_probe id=0x00989600
KSZ9896CS: eth0: ethernet@30be0000
Fastboot: Normal
Normal Boot
Hit any key to stop autoboot: 0
u-boot=>
<< u-boot, arch/arm/dts/imx8mn-evk.dtsi >>
&uart1 { /* console */
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_uart1>;
u-boot,dm-spl;
status = "okay";
};
&uart2 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_uart2>;
status = "okay";
};
&uart3 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_uart3>;
assigned-clocks = <&clk IMX8MN_CLK_UART3>;
assigned-clock-parents = <&clk IMX8MN_SYS_PLL1_80M>;
u-boot,dm-spl;
uart-has-rtscts;
status = "okay";
};
<< u-boot, board/freescale/imx8mn_evk/imx8mn_evk.c>>
static iomux_v3_cfg_t const uart_pads[] = {
IMX8MN_PAD_UART1_RXD__UART1_DCE_RX | MUX_PAD_CTRL(UART_PAD_CTRL),
IMX8MN_PAD_UART1_TXD__UART1_DCE_TX | MUX_PAD_CTRL(UART_PAD_CTRL),
IMX8MN_PAD_UART2_RXD__UART2_DCE_RX | MUX_PAD_CTRL(UART_PAD_CTRL),
IMX8MN_PAD_UART2_TXD__UART2_DCE_TX | MUX_PAD_CTRL(UART_PAD_CTRL),
IMX8MN_PAD_ECSPI1_SCLK__UART3_DCE_RX | MUX_PAD_CTRL(UART_PAD_CTRL),
IMX8MN_PAD_ECSPI1_MOSI__UART3_DCE_TX | MUX_PAD_CTRL(UART_PAD_CTRL),
IMX8MN_PAD_ECSPI1_MISO__UART3_DCE_CTS_B | MUX_PAD_CTRL(UART_PAD_CTRL),
IMX8MN_PAD_ECSPI1_SS0__UART3_DCE_RTS_B | MUX_PAD_CTRL(UART_PAD_CTRL),
};
int board_early_init_f(void)
{
struct wdog_regs *wdog = (struct wdog_regs *)WDOG1_BASE_ADDR;
imx_iomux_v3_setup_multiple_pads(wdog_pads, ARRAY_SIZE(wdog_pads));
set_wdog_reset(wdog);
imx_iomux_v3_setup_multiple_pads(uart_pads, ARRAY_SIZE(uart_pads));
init_uart_clk(0);
init_uart_clk(1);
init_uart_clk(2);
#ifdef CONFIG_NAND_MXS
setup_gpmi_nand(); /* SPL will call the board_early_init_f */
#endif
return 0;
}
<< u-boot, cmd/uart_test.c>>
abc@dev:~/yocto/build/tmp/work/imx8mnul_ddr3l_evk-poky-linux/u-boot-imx/2023.04-r0/git/cmd (lf_v2023.04)$ cat uart_test.c
#include <common.h>
#include <command.h>
#include <dm.h>
#include <serial.h>
#include <dm/device.h>
#include <dm/uclass.h>
#include <dm/device-internal.h> // device_probe()
#include <dm/uclass-internal.h> // uclass_first_device(), uclass_next_device()
static const struct {
const char *alias;
const char *device_name;
} uart_aliases[] = {
{ "uart2", "serial@30890000" },
{ "uart3", "serial@30880000" },
{ "uart4", "serial@308a0000" }
};
static const char *get_uart_device_name(const char *alias) {
for (int i = 0; i < ARRAY_SIZE(uart_aliases); i++) {
if (strcmp(alias, uart_aliases[i].alias) == 0) {
return uart_aliases[i].device_name;
}
}
return alias;
}
static int do_uart_test(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
{
const char *uart_name;
const char *device_name;
struct udevice *dev;
struct udevice *iter_dev;
const struct dm_serial_ops *ops;
const char *baudrate_str;
const char *hex_message;
int baudrate;
int ret;
bool found = false;
if (argc != 4) {
printf("Usage: uart_test <uart_name> <baudrate> <hex message>\n");
return CMD_RET_USAGE;
}
uart_name = argv[1];
baudrate_str = argv[2];
hex_message = argv[3];
baudrate = simple_strtoul(baudrate_str, NULL, 10);
device_name = get_uart_device_name(uart_name);
if (!gd->dm_root) {
ret = dm_scan_fdt(gd->fdt_blob, false);
if (ret) {
printf("Failed to scan FDT (error: %d)\n", ret);
return CMD_RET_FAILURE;
}
}
printf("trying to uclass_get_device_by_name: %s...\n", device_name);
ret = uclass_get_device_by_name(UCLASS_SERIAL, device_name, &dev);
if (ret) {
printf("UART device %s not found, trying to probe...\n", device_name);
ret = device_probe(dev);
if (ret) {
printf("Error: Unable to probe UART device %s (ret=%d)\n", device_name, ret);
return CMD_RET_FAILURE;
}
printf("devcie probe finished: %s ...\n", device_name);
printf("trying to uclass_get_device_by_name: %s...\n", device_name);
ret = uclass_get_device_by_name(UCLASS_SERIAL, device_name, &dev);
if (ret) {
printf("Still failed to find UART device: %s (error: %d)\n", device_name, ret);
return CMD_RET_FAILURE;
}
}
printf("UART device %s found...\n", device_name);
#if 0
if (!dev) {
printf("Error: Device not found!\n");
return CMD_RET_FAILURE;
}
ret = device_probe(dev);
if (ret) {
printf("Error: Unable to probe UART device %s (ret=%d)\n", device_name, ret);
return CMD_RET_FAILURE;
}
printf("UART device %s probed successfully.\n", device_name);
#endif
/* Set baudrate */
ops = serial_get_ops(dev);
if (!ops || !ops->putc || !ops->setbrg) {
printf("UART device does not support putc, setbrg operation\n");
return CMD_RET_FAILURE;
}
/* Get DM serial operations */
/* Set baudrate */
ret = ops->setbrg(dev, baudrate);
if (ret) {
printf("Failed to set baudrate %d on %s (error: %d)\n", baudrate, device_name, ret);
return CMD_RET_FAILURE;
}
printf("UART device: %s\n", device_name);
printf("BaudRate: %d\n", baudrate);
/* Convert hex string to binary and send */
while (*hex_message && *(hex_message + 1)) {
char hex_byte[3] = {hex_message[0], hex_message[1], '\0'};
char byte = (char) simple_strtoul(hex_byte, NULL, 16);
ops->putc(dev, byte);
hex_message += 2;
}
printf("Message sent successfully.\n");
return CMD_RET_SUCCESS;
}
U_BOOT_CMD(
uart_test, 4, 1, do_uart_test,
"Send hex message over UART",
"<uart_name> <baudrate> <hex_message>\n"
" - Send <hex_message> (hex format) to specified UART device.\n"
" example) - uart2, 115200, Hello, UART! \n => uart_test uart2 115200 48656C6C6F2C2055415254210A\n"
" example) - uart3, 9600, Hello, UART! \n => uart_test uart3 9600 48656C6C6F2C2055415254210A\n"
" example) - uart4, 9600, Hello, 1122aabb\n => uart_test uart4 9600 1122aabb\n"
);
abc@dev:~/yocto/build/tmp/work/imx8mnul_ddr3l_evk-poky-linux/u-boot-imx/2023.04-r0/git/cmd (lf_v2023.04)$