UEFI阶段uart通信

最近有几个类似的需求,修改过程遇到了一些问题,咨询了供应商搞好了学到了点东西记录一下。

需求主要是在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总线权限不释放也白瞎,别忘了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值