最近有几个类似的需求,修改过程遇到了一些问题,咨询了供应商搞好了学到了点东西记录一下。
需求主要是在abl阶段让模块和外设能通过uart通信,速度有快(一般2~3M)有慢(115200)。实现过程也不复杂,其实就和常用tlmm这些类似,主要是一些细节要注意下。
1、驱动
有些平台是已经集成了驱动,有些没集成,可以直接复制粘贴改点东西就行。路径在
boot_images/QcomPkg/Library/HSUartQupv3Lib/下面,有十几个文件主要注意俩就行,HSUartXBL.c和HSUartSettings.h,不同gpio和uart 速率控制基本就改这俩。
HSUartXBL.c先来,这个函数就是初始化uart的一些配置,包括波特率、停止位、回环测试等等,波特率的选择不能乱写,文件开头有给定义,不同平台我看给的可选项还有差异,根据给的选就行,其它项根据设计需求自己调整,回环测试前期测试方便可以打开,实际使用时候要关掉。
static const CLOCK_SETTINGS baud_table[] =
{
// bit_rate, input_freq, divider
{ 115200, 7372800, 64 },
{ 3000000, 48000000, 16 },
{0}
};
/*==================================================================================================
FUNCTION: hsuart_initialize
DESCRIPTION:
==================================================================================================*/
RETURN_STATUS EFIAPI
hsuart_initialize(void)
{
hsuart_open_config c;
c.baud_rate = 3000000; //波特率
c.parity_mode = HSUART_NO_PARITY;
c.num_stop_bits = HSUART_1_0_STOP_BITS; //停止位
c.bits_per_char = HSUART_8_BITS_PER_CHAR;
c.enable_loopback = FALSE; //回环
c.tx_cb_isr = NULL;
c.rx_cb_isr = NULL;
hsuart_open(&hsuart_port_handle, HSUART_DEBUG_PORT, &c);
return RETURN_SUCCESS;
}
再来是HSUartSettings.h嗷,这货更关键点,选择哪一路uart和具体哪个gpio都要靠他来控制,这家没它不行,不多比比上代。主要控制函数就是下面这位牢弟
static HSUART_PROPERTIES devices =
{
// MAIN_PORT
0x04A80000, // uart_base 你选的哪一路就写哪一路,我这里是se0,
//qupv3_se0_4uart: i2c@4a80000,选的时候要注意这路qup支不支持uart功能,不支持你配的再对也白瞎
0x04AC0000, // qup_common_base qup 基地址,不用动,如果你是从别的平台拷的驱动怕不对就去看你
//ap代码xx-qupv3.dtsi里开头这一句就行
//&soc {
// /* QUPv3_0 wrapper instance */
// qupv3_0: qcom,qupv3_0_geni_se@4ac0000 {
//我jio得好像都是一样的吧,不一样额,那就不一样呗
0x2001c021, // gpio_tx_config
0x20008031, // gpio_rx_config
0, // gpio_cts_config
0, // gpio_rfr_config //这几个寄存器配置下面专门说
0, // clock_id_index
(uint8 **)common_clocks_str_0, // common_clock_id 跟上头那个基地址差不多,不管
(uint8 **)(se_clocks_str_0 + 0), // core_clock_id
// 例子,选qup1_se2,这里就是(uint8 **)(se_clocks_str_1 + 2)
0, // irq number
0,
//TCSR base
0, // TCSR offset
0 // TCSR value
};
然后细嗦一下那几个gpio_xx_config的配置方法哈。已上面代码为例,我是se0,对应gpio2、gpio3,tx是gpio2,rx是gpio3,具体二进制转化方法如图所示,主要就是修改标颜色的地方,其它地方不用动,然后转化成16进制就行,可以自己找几个gpio算算。

除了驱动这部分剩下的就是协议相关的几个文件,不需要动,其它没啥了
boot_images/QcomPkg/Drivers/HSUartDxe/HSUartDxe.c
boot_images/QcomPkg/Drivers/HSUartDxe/HSUartDxe.inf
boot_images/QcomPkg/Include/Protocol/EFIHSUart.h
2、bootable部分
驱动那边改好,abl这边其实就调用。方法跟调用tlmm大致无二,无非就是添加头文件,添加uuid,这些在xbl代码里面都是现成的,抄过来放到对应代码位置即可,然后就是自己调用下接口做个测试,没问题就可以了,如下是代码示例,放fastboot代码里,调用一下open/read/write/close这几个接口,自己收发测一下,没问题就可以了。你说这接口在哪儿?当然在代码里了,去看协议文件还有驱动。
--- a/bootable/bootloader/edk2/QcomModulePkg/Library/FastbootLib/FastbootCmds.c
+++ b/bootable/bootloader/edk2/QcomModulePkg/Library/FastbootLib/FastbootCmds.c
@@ -114,7 +114,7 @@ found at
#include <Protocol/SimpleTextOut.h>
#include <Protocol/EFIDisplayUtils.h>
#include <Protocol/EFIRecoveryInfo.h>
-
+#include <Protocol/EFIHSUart.h>
#include "AutoGen.h"
#include "BootImage.h"
#include "BootLinux.h"
@@ -3869,6 +3869,56 @@ CmdOemSelectDisplayPanel (CONST CHAR8 *arg, VOID *data, UINT32 sz)
UINTN CurStrLen = 0;
UINTN TotalStrLen = 0;
BOOLEAN Append = FALSE;
+ CHAR8 logbuf[64];
+ UINT8 RX_DATA[32];
+ UINT8 TX_DATA[32]= {0x11,0x22,0x33};
+
+ EFI_QCOM_HSUART_PROTOCOL *VbSerialPort;
+
+ AsciiSPrint (logbuf, sizeof (logbuf), "Start uart test!!");
+ FastbootInfo (logbuf);
+ WaitForTransferComplete ();
+
+ Status = gBS->LocateProtocol (&gQcomHSUartProtocolGuid, NULL, (VOID **)&VbSerialPort);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR,
+ "Locate EFI_QCOM_HSUART_PROTOCOL failed, Status = (0x%x)\r\n", Status));
+ return;
+ }
+ if (Status != EFI_SUCCESS) {
+ AsciiSPrint (logbuf, sizeof (logbuf), "Open gQcomHSUartProtocolGuid fail %d!",Status);
+ FastbootInfo (logbuf);
+ WaitForTransferComplete ();
+ return ;
+ }
+
+ Status = VbSerialPort->open();
+ if (Status != EFI_SUCCESS) {
+ AsciiSPrint (logbuf, sizeof (logbuf), "Open fail %d!",Status);
+ FastbootInfo (logbuf);
+ WaitForTransferComplete ();
+ } else {
+ AsciiSPrint (logbuf, sizeof (logbuf), "Open success");
+ FastbootInfo (logbuf);
+ WaitForTransferComplete ();
+ }
+
+ VbSerialPort->write((UINT8*)TX_DATA,3);
+ VbSerialPort->read((UINT8*)RX_DATA,3);
+ AsciiSPrint (logbuf, sizeof (logbuf), "RX data: 0x%x 0x%x 0x%x ",RX_DATA[0],RX_DATA[1],RX_DATA[2]);
+ FastbootInfo (logbuf);
+ WaitForTransferComplete ();
+
+ Status = VbSerialPort->close();
+ if (Status != EFI_SUCCESS) {
+ AsciiSPrint (logbuf, sizeof (logbuf), "close fail %d!",Status);
+ FastbootInfo (logbuf);
+ WaitForTransferComplete ();
+ } else {
+ AsciiSPrint (logbuf, sizeof (logbuf), "close success !");
+ FastbootInfo (logbuf);
+ WaitForTransferComplete ();
+ }
for (Pos = 0; Pos < AsciiStrLen (arg); Pos++) {
if (arg[Pos] == ' ') {
3、其它
上面这些改了还有tz也要改,tz总线权限不释放也白瞎,别忘了。
3652

被折叠的 条评论
为什么被折叠?



