Hello Toradex Support Team,
I’m trying to configure UART3 (DMA_UART0) on the Apalis i.MX8QM with the Ixora carrier board, so that it can be used as the debug console for Cortex-M4 core 0.
What I have done so far
- SCFW configuration: Edited
board_system_config()to add the UART0 resource (SC_R_UART_0) and pads (SC_P_UART0_RX,SC_P_UART0_TX) to the M4_0 partition.
/*--------------------------------------------------------------------------*/
/* Configure the system (inc. additional resource partitions) */
/*--------------------------------------------------------------------------*/
void board_system_config(sc_bool_t early, sc_rm_pt_t pt_boot)
{
sc_err_t err = SC_ERR_NONE;
/* This function configures the system. It usually partitions
resources according to the system design. It must be modified by
customers. Partitions should then be specified using the mkimage
-p option. */
/* Note the configuration here is for NXP test purposes */
sc_bool_t alt_config = SC_FALSE;
sc_bool_t no_ap = SC_FALSE;
sc_bool_t ddrtest = SC_FALSE;
/* Get boot parameters. See the Boot Flags section for definition
of these flags.*/
boot_get_data(NULL, NULL, NULL, NULL, NULL, NULL, &alt_config,
NULL, &ddrtest, &no_ap, NULL);
board_print(3, "board_system_config(%d, %d)\n", early, alt_config);
/* Name default partitions */
PARTITION_NAME(SC_PT, "SCU");
PARTITION_NAME(SECO_PT, "SECO");
PARTITION_NAME(pt_boot, "BOOT");
/* Configure initial resource allocation (note additional allocation
and assignments can be made by the SCFW clients at run-time */
if (alt_config != SC_FALSE)
{
sc_rm_pt_t pt_m4_0 = SC_RM_NUM_PARTITION;
sc_rm_pt_t pt_m4_1 = SC_RM_NUM_PARTITION;
#ifdef BOARD_RM_DUMP
rm_dump(pt_boot);
#endif
/* Name boot partition */
PARTITION_NAME(pt_boot, "AP0");
/* Create M4 0 partition */
if (rm_is_resource_avail(SC_R_M4_0_PID0) != SC_FALSE)
{
sc_rm_mr_t mr;
/* List of resources */
static const sc_rsrc_t rsrc_list[9U] =
{
SC_R_SYSTEM,
SC_R_IRQSTR_M4_0,
SC_R_UART_0,
SC_R_CAN_0,
SC_R_MU_5B,
SC_R_MU_7A,
SC_R_MU_8B,
SC_R_GPT_4,
SC_R_SECO_MU_4
};
/* List of pads */
static const sc_pad_t pad_list[6U] =
{
RM_RANGE(SC_P_M40_I2C0_SCL, SC_P_M40_GPIO0_01),
RM_RANGE(SC_P_UART0_RX, SC_P_UART0_TX),
RM_RANGE(SC_P_FLEXCAN0_RX, SC_P_FLEXCAN0_TX)
};
/* List of memory regions */
static const sc_rm_mem_list_t mem_list[2U] =
{
{0x088000000ULL, 0x0887FFFFFULL},
{0x008081000ULL, 0x008180FFFULL}
};
/* Create partition */
BRD_ERR(rm_partition_create(pt_boot, &pt_m4_0, SC_FALSE,
SC_TRUE, SC_FALSE, SC_TRUE, SC_FALSE, SC_R_M4_0_PID0,
rsrc_list, ARRAY_SIZE(rsrc_list),
pad_list, ARRAY_SIZE(pad_list),
mem_list, ARRAY_SIZE(mem_list)));
/* Name partition for debug */
PARTITION_NAME(pt_m4_0, "MCU0");
/* Allow AP to use SYSTEM (not production!) */
BRD_ERR(rm_set_peripheral_permissions(SC_PT, SC_R_SYSTEM,
pt_boot, SC_RM_PERM_SEC_RW));
/* Move M4 0 TCM */
BRD_ERR(rm_find_memreg(pt_boot, &mr, 0x034FE0000ULL,
0x034FE0000ULL));
BRD_ERR(rm_assign_memreg(pt_boot, pt_m4_0, mr));
/* Move partition to be owned by SC */
BRD_ERR(rm_set_parent(pt_boot, pt_m4_0, SC_PT));
/* Check if booting with the no_ap flag set */
if (no_ap != SC_FALSE)
{
/* Move boot to be owned by M4 0 for Android Automotive */
BRD_ERR(rm_set_parent(SC_PT, pt_boot, pt_m4_0));
}
}
/* Create M4 1 partition */
if (rm_is_resource_avail(SC_R_M4_1_PID0) != SC_FALSE)
{
sc_rm_mr_t mr;
/* List of resources */
static const sc_rsrc_t rsrc_list[9U] =
{
SC_R_IRQSTR_M4_1,
SC_R_UART_2,
SC_R_MU_6B,
SC_R_MU_7B,
SC_R_MU_9B,
SC_R_GPT_3,
RM_RANGE(SC_R_CAN_1, SC_R_CAN_2),
SC_R_FSPI_0
};
/* List of pads */
static const sc_pad_t pad_list[8U] =
{
RM_RANGE(SC_P_M41_I2C0_SCL, SC_P_M41_GPIO0_01),
RM_RANGE(SC_P_LVDS0_I2C1_SCL,SC_P_LVDS0_I2C1_SDA),
RM_RANGE(SC_P_FLEXCAN1_RX, SC_P_FLEXCAN2_TX),
RM_RANGE(SC_P_QSPI0A_DATA0, SC_P_COMP_CTL_GPIO_1V8_3V3_QSPI0)
};
/* List of memory regions */
static const sc_rm_mem_list_t mem_list[2U] =
{
{0x088800000ULL, 0x08FFFFFFFULL},
{0x008181000ULL, 0x008280FFFULL}
};
/* Create partition */
BRD_ERR(rm_partition_create(pt_boot, &pt_m4_1, SC_FALSE,
SC_TRUE, SC_FALSE, SC_TRUE, SC_FALSE, SC_R_M4_1_PID0,
rsrc_list, ARRAY_SIZE(rsrc_list),
pad_list, ARRAY_SIZE(pad_list),
mem_list, ARRAY_SIZE(mem_list)));
/* Name partition for debug */
PARTITION_NAME(pt_m4_1, "MCU1");
/* Allow M4 1 to use SYSTEM (not production!) */
BRD_ERR(rm_set_peripheral_permissions(SC_PT, SC_R_SYSTEM,
pt_m4_1, SC_RM_PERM_SEC_RW));
/* Move M4 1 TCM */
BRD_ERR(rm_find_memreg(pt_boot, &mr, 0x038FE0000ULL,
0x038FE0000ULL));
BRD_ERR(rm_assign_memreg(pt_boot, pt_m4_1, mr));
/* Move partition to be owned by SC */
BRD_ERR(rm_set_parent(pt_boot, pt_m4_1, SC_PT));
}
/* Create partition for shared/hidden resources */
{
sc_rm_pt_t pt;
sc_rm_mr_t mr;
/* List of resources */
static const sc_rsrc_t rsrc_list[4U] =
{
RM_RANGE(SC_R_M4_0_PID1, SC_R_M4_0_PID4),
RM_RANGE(SC_R_M4_1_PID1, SC_R_M4_1_PID4)
};
/* List of memory regions */
static const sc_rm_mem_list_t mem_list[1U] =
{
{0x090000000ULL, 0x091FFFFFFULL}
};
/* Create shared partition */
BRD_ERR(rm_partition_create(SC_PT, &pt, SC_FALSE, SC_TRUE,
SC_FALSE, SC_FALSE, SC_FALSE, SC_NUM_RESOURCE,
rsrc_list, ARRAY_SIZE(rsrc_list), NULL, 0U,
mem_list, ARRAY_SIZE(mem_list)));
/* Name partition for debug */
PARTITION_NAME(pt, "Shared");
/* Share memory space */
BRD_ERR(rm_find_memreg(SC_PT, &mr,
mem_list[0U].addr_start, mem_list[0U].addr_start));
BRD_ERR(rm_set_memreg_permissions(pt, mr, pt_boot,
SC_RM_PERM_FULL));
if (pt_m4_0 != SC_RM_NUM_PARTITION)
{
BRD_ERR(rm_set_memreg_permissions(pt, mr, pt_m4_0,
SC_RM_PERM_FULL));
}
if (pt_m4_1 != SC_RM_NUM_PARTITION)
{
BRD_ERR(rm_set_memreg_permissions(pt, mr, pt_m4_1,
SC_RM_PERM_FULL));
}
}
/* Allow all to access the SEMA42s */
BRD_ERR(rm_set_peripheral_permissions(SC_PT, SC_R_M4_0_SEMA42,
SC_RM_PT_ALL, SC_RM_PERM_FULL));
BRD_ERR(rm_set_peripheral_permissions(SC_PT, SC_R_M4_1_SEMA42,
SC_RM_PT_ALL, SC_RM_PERM_FULL));
#ifdef BOARD_RM_DUMP
rm_dump(pt_boot);
#endif
}
}
- Rebuilt the boot image with:
make SOC=iMX8QM flash_regression_linux_m4
- For the m4 firmware, I use the MCUXpresso SDK hello_world example. Modified
board.hto useDMA__LPUART0.
#if defined(MIMX8QM_CM4_CORE0)
#define BOARD_DEBUG_UART_BASEADDR (uint32_t) DMA__LPUART0
#define BOARD_DEBUG_UART_INSTANCE 2U
#define BOARD_DEBUG_UART_SC_RSRC SC_R_UART_0
#define BOARD_DEBUG_UART_CLKSRC kCLOCK_DMA_Lpuart0
#define BOARD_UART_IRQ DMA_UART0_INT_IRQn
#define BOARD_UART_IRQ_HANDLER DMA_UART0_INT_IRQHandler
#define BOARD_M4_CPU_RSRC SC_R_M4_0_PID0
- Updated
pin_mux.h/cto configure UART0 RX/TX pins (SC_P_UART0_RX,SC_P_UART0_TX).BOARD_InitPins()callssc_pad_set_all()for RX and TX pads.
/* UART0_TX (number AV48), FTDI_UART0_TX */
#define BOARD_INITPINS_FTDI_UART0_TX_PERIPHERAL DMA__UART0 /*!< Peripheral name */
#define BOARD_INITPINS_FTDI_UART0_TX_SIGNAL uart_tx /*!< Signal name */
#define BOARD_INITPINS_FTDI_UART0_TX_PIN_NAME UART0_TX /*!< Routed pin name */
#define BOARD_INITPINS_FTDI_UART0_TX_PIN_FUNCTION_ID SC_P_UART0_TX /*!< Pin function id */
#define BOARD_INITPINS_FTDI_UART0_TX_LABEL "FTDI_UART0_TX" /*!< Label */
#define BOARD_INITPINS_FTDI_UART0_TX_NAME "FTDI_UART0_TX" /*!< Identifier */
/* UART0_RX (number AV50), FTDI_UART0_RX */
#define BOARD_INITPINS_FTDI_UART0_RX_PERIPHERAL DMA__UART0 /*!< Peripheral name */
#define BOARD_INITPINS_FTDI_UART0_RX_SIGNAL uart_rx /*!< Signal name */
#define BOARD_INITPINS_FTDI_UART0_RX_PIN_NAME UART0_RX /*!< Routed pin name */
#define BOARD_INITPINS_FTDI_UART0_RX_PIN_FUNCTION_ID SC_P_UART0_RX /*!< Pin function id */
#define BOARD_INITPINS_FTDI_UART0_RX_LABEL "FTDI_UART0_RX" /*!< Label */
#define BOARD_INITPINS_FTDI_UART0_RX_NAME "FTDI_UART0_RX" /*!< Identifier */
void BOARD_InitPins(sc_ipc_t ipc) /*!< Function assigned for the core: Cortex-M4F[cm4_core0] */
{
sc_err_t err = SC_ERR_NONE;
err = sc_pad_set_all(ipc, BOARD_INITPINS_FTDI_UART0_RX_PIN_FUNCTION_ID, 0U, SC_PAD_CONFIG_NORMAL, SC_PAD_ISO_OFF, 0x0 ,SC_PAD_WAKEUP_OFF);/* IOMUXD_UART0_RX register modification value */
if (SC_ERR_NONE != err)
{
assert(false);
}
err = sc_pad_set_all(ipc, BOARD_INITPINS_FTDI_UART0_TX_PIN_FUNCTION_ID, 0U, SC_PAD_CONFIG_NORMAL, SC_PAD_ISO_OFF, 0x0 ,SC_PAD_WAKEUP_OFF);/* IOMUXD_UART0_TX register modification value */
if (SC_ERR_NONE != err)
{
assert(false);
}
}
- The main program remains unchanged. Main loop simply does:
ch = GETCHAR();
PUTCHAR(ch);
The issue
- TX works: “hello world.” is printed on the serial terminal.
- RX does not work: characters typed in the terminal are not echoed back.
Thanks in advance!
apalis-imx8_hmp_overlay.dts (2.4 KB)