系统控制器固件 101 - 入门 使用评估套件时,你会获得一个包含在 BSP 中的系统控制器固件 (SCFW) 二进制文件。此 SCFW 二进制文件是为特定开发板量身定制的,你可能需要修改一些板级依赖项以适配你的特定硬件。
本文件旨在提供有关SCFW移植流程的概述,详细信息请参阅《系统控制器移植指南》(sc_fw_port.pdf)。
系统设置
SCFW 是在 Linux 主机上构建的。设置系统的步骤如下:
从 ARM 官网下载 GNU ARM 嵌入式工具链:6-2017-q2-update(2017 年 6 月 28 日版本):
选择一个目录解压该文件,例如: mkdir ~/gcc_toolchain
cp ~/Downloads/gcc-arm-none-eabi-6-2017-q2-update-linux.tar.bz2 ~/gcc_toolchain/
cd ~/gcc_toolchain/
tar xvjf gcc-arm-none-eabi-6-2017-q2-update-linux.tar.bz2
将 TOOLS 环境变量设置为包含工具链的目录,在上面的示例中为 “~/gcc_toolchain”,也可以修改 .bash_profile 来导出此环境变量:
export TOOLS=~/gcc_toolchain/
构建过程还需要 srec_cat,它通常包含在 srecord 包中,在 Ubuntu 上可以执行:
sudo apt-get update
sudo apt-get install srecord
现在你可以切换到移植工具包目录(例如 scfw_export_mx8qm)并构建 SCFW。
系统控制器固件移植工具包
SCFW移植套件包含源文件和目标文件,这些文件将允许您修改SCFW以使其与您的开发板兼容。
你可以从 i.MX 软件和开发网页获取最新的系统控制器固件移植工具包:
获取移植工具包后,解压它:
tar xvzf imx-scfw-porting-kit-1.1.tar.gz
您将看到以下的文件结构:
移植工具包包含在 packages 目录下,README 文件中包含提取移植工具包的说明,主要步骤如下:
cd packages/
chmod a+x imx-scfw-porting-kit-1.1.bin
./imx-scfw-porting-kit-1.1.bin
您将被提示接受最终用户许可协议:
接受协议后,移植工具包将被提取到一个新文件夹中,文件夹结构如下:
所有关于 SCFW 的文档都在 doc/pdf 目录下,也有 html 格式可供选择,建议阅读 sc_fw_port.pdf。
不同 SoC 变体(QM A0、QM B0 和 QXP B0)的移植工具包在 src 目录下,以 tar.gz 格式打包,其他所有文件都是用于不同软件包(如 Linux、QNX、FreeRTOS、U-boot、ARM 可信固件等)的 SCFW 库。
如果你要处理多个 SoC 变体(同时处理 QXP 和 QM),建议将所有移植工具包提取到一个目录中,这样你就可以从该目录为任何变体进行构建,执行以下命令:
cd imx-scfw-porting-kit-1.1/
cd src/
find scfw_export_mx8*.gz -exec tar --strip-components 1 --one-top-level=scfw_export_mx8 -xzvf {} \;
将创建一个 scfw_export_mx8 文件夹,从这里你可以为任何受支持的变体构建 SCFW。或者,你也可以只提取你感兴趣的变体的包并使用它。
cd scfw_export_mx8/
所有构建文件夹都包含 SCFW 的构建结果,而 platform 目录则存储 SCFW 的源代码。
所有特定于开发板配置的代码都在 “platform/board/mx8 _ ” 目录下,其中 derivative 是 i.MX8 芯片系列(如 QXP 或 QM),board name 是 SCFW 包所针对的开发板名称。
将 SCFW 移植到你的开发板的第一步是为你的 i.MX8 衍生产品和开发板创建一个文件夹,你可以选取一个现有的开发板示例并重命名该文件夹,这将为你提供一个入门项目,例如:
cp -r platform/board/mx8qm_val/ platform/board/mx8qm_myBoard/
在此示例中,该开发板将被称为 “myBoard”,它适用于 i.MX8QM B0 设备。要为该开发板构建 SCFW,只需执行:
make qm R=B0 B=myBoard
如果目标是 i.MX8QXP,只需选取一个基于该设备的开发板,并将命令改为 “make qx”。
更多信息(如构建选项和详细的启动信息)可以在《SCFW 移植指南》(sc_fw_port.pdf)中找到,该文档的第 2 章是对移植过程的清晰介绍。
概述和有用信息
PMIC 配置概述和 board.c 的常见修改
需要修改的主要文件(如果不是唯一的话)是 “board.c” 文件,它位于 “platform/board/mx8X_board/” 目录下。board.c 文件包含大多数与开发板相关的信息,如 SCU UART 端口、PMIC 初始化程序、PMIC 温度报警设置,你还可以修改它来配置 LDO 电压并与 PMIC 进行总体通信。board.c 文件中的所有函数都由 SCU 本身执行,这使你能够访问用于与 PMIC 通信的 I2C 接口。
由外部电源(例如 PMIC LDO)供电的 SoC 资源(如 AP 内核和 GPU)通过 board_set_power_mode 进行开关,资源到特定 PMIC 电源的映射在 board_get_pmic_info 中进行,例如,在我们的 i.MX8QM 验证板上,使用 A53 子系统由 PF100 PMIC 卡上第三个 PMIC(PMIC_2_ADDR 地址从 PMIC_0 开始)的 SW2 供电,由 PF8100 PMIC 卡上第一个 PMIC (PMIC_0_ADDR) 的 SW5 供电。 case SC_SUBSYS_A53:
pmic_init();
if (pmic_card == PF100)
{
pmic_id[0] = PMIC_2_ADDR;
pmic_reg[0] = SW2;
*num_regs = 1;
}
else
{/* PF8100_dual Card */
pmic_id[0] = PMIC_0_ADDR;
pmic_reg[0] = PF8100_SW5;
*num_regs = 1;
}
break;
由外部电源(AP 内核、GPU 等)供电的 SoC 资源的电压由 board.c 文件中的 board_set_voltage 管理。资源到电源的映射如上面的示例所示,在 board_get_pmic_info 中进行。
有八个 “板载资源” (SC_R_BOARD_R0,... SC_R_BOARD_R7)b 可用,这些资源允许你定义 SCU 可以管理的开发板上的组件,例如,开发板上由某个 PMIC LDO 供电的传感器可以映射到一个板载资源,并且可以修改 board.c 文件来开关该传感器以及修改其电压。
修改板载资源的电压可以通过修改 board_trans_resource_power 处的电压来完成(见下文),或者如果需要在运行时更改电压,可以修改 board_set_control 函数,以便在对该资源进行杂项调用(详见《杂项服务 101》)时更改电压。例如,要更改 SC_R_BOARD_R7 上的电压,你可以在 board_set_control 中使用以下情况: case SC_R_BOARD_R7:
if (ctrl == SC_C_VOLTAGE)
{
/* Example only PMIC_X_ADDR and PMIC_SUPPLY need to match an actual device */
pmic_interface.pmic_set_voltage(PMIC_X_ADDR, PMIC_SUPPLY, val, step);
}
else
return SC_ERR_PARM;
break;
每当应用程序调用以下函数时,SCU 将执行上面的代码:
sc_misc_set_control( ipc, SC_R_BOARD_R7, SC_C_VOLTAGE, voltage_val);
板载资源的开关在 board.c 文件的 board_trans_resource_power 中进行。例如,在 NXP 的验证板上,板上的 PTN5150 通过板载资源 0 进行管理,其开关管理如下: case BRD_R_BOARD_R0 : /* PTN5150 (use SC_R_BOARD_R0) */
if (pmic_ver.device_id == PF100_DEV_ID)
{
if (to_mode > SC_PM_PW_MODE_OFF)
{
pmic_interface.pmic_set_voltage(PMIC_2_ADDR, VGEN6,
3300, SW_RUN_MODE);
pmic_interface.pmic_set_mode(PMIC_2_ADDR, VGEN6,
VGEN_MODE_ON);
}
else
{
pmic_interface.pmic_set_mode(PMIC_2_ADDR, VGEN6,
VGEN_MODE_OFF);
}
}
else
{/* PF8100_dual Card */
if (to_mode > SC_PM_PW_MODE_OFF)
{
pmic_interface.pmic_set_voltage(PMIC_1_ADDR, PF8100_LDO1,
3300, REG_RUN_MODE);
pmic_interface.pmic_set_mode(PMIC_1_ADDR, PF8100_LDO1,
RUN_EN_STBY_EN);
}
else
{
pmic_interface.pmic_set_mode(PMIC_1_ADDR, PF8100_LDO1,
RUN_OFF_STBY_OFF);
}
}
break;
每当从应用程序端调用以下函数时,SCU 将执行上面的代码:
sc_pm_set_resource_power_mode(ipc, SC_R_BOARD_R0, SC_PM_PW_MODE_ON/OFF);
board_config_sc 用于标记 SCU 需要的资源,例如用于与 PMIC 通信的 I2C 模块和焊盘,board.c 函数工作所需的任何资源都应在此函数中标记为不可移动,例如,要保留 SCU I2C 模块,需添加以下行: rm_set_resource_movable(pt_sc, SC_R_SC_I2C, SC_R_SC_I2C, false);
以下焊盘属于 SCU,应用程序无法访问它们:
- SC_P_SCU_PMIC_MEMC_ON - SC_P_SCU_WDOG_OUT - SC_P_PMIC_EARLY_WARNING - SC_P_PMIC_INT_B - SC_P_SCU_BOOT_MODE0 到 SC_P_SCU_BOOT_MODE5
board_system_config 是早期资源管理发生的地方,该函数仅在图像中设置了 alt_config 标志时被调用,并且它可以创建分区并为其分配资源。更多详细信息可在资源管理服务 101 中找到。
board_get_pcie_clk_src 定义了 PCIe 使用的时钟,它可以是 BOARD_PCIE_PLL_EXTERNAL 或 BOARD_PCIE_PLL_INTERNAL。
board_print 对于调试你的更改非常有用,其语法如下: board_print(3, "Debug printout %d\n", val);
其中第一个参数是调试级别,从那里开始它的工作方式与标准 printf 相同。只有当 SCU 是在相应的调试级别下构建时,输出才会在 SCU 调试输出上可见,在上面的示例中,需要按以下方式构建 SCFW 才能看到输出:
make qm B=myBoard DL=3 or higher (debug level goes from 0 to 5)
用法示例
以下工具展示了如何发出系统控制器固件请求,并提供了一种通过 QNX 和 Linux 上的命令行界面发出此类请求的方法
适用于 Linux 和 QNX 的系统控制器固件命令行工具
系统控制器固件 101 i.MX 8 系列 | i.MX 8QuadMax (8QM) | 8QuadPlus
View full article