rk3399-uboot2017-增加串口通信

news/2025/2/19 16:33:58/

一、主要还是解决这个问题,最后没办法,只能进行串口通信,来识别屏幕的类型了。

基本步骤如下:

1. uboot阶段发送串口指令,等待串口回复数据,根据数据识别屏幕类型

2.在bootargs增加一个自定义的参数,告诉内核屏幕的类型,驱动中更加屏幕类型使用不同的时序

本文只讲uboot中串口的设置,本次项目中使用的是串口4.

参考文件:drivers/serial/ns16550.c (uboot2017.09源码)

二、遇到的问题:

1.要不要使用dts?,由于能力有限,没有使用dts设置

2.如何初始化?

3.如何进行io复用?

4.调试的时候遇到的问题,就是无法通信,使用ttl的串口连着,看到又0xff,00,00三个字节输出,但是这三个字节都不是我自己发送的。开始时怀疑波特率的问题,因为我实际发送了8个字节,而只收到了3个字节,那就时钟配置不对,又把时钟的配置找了一圈,后面确认是24MHz。

5.时钟确认之后,后来发现是引脚复用不对,由于不熟悉3399的结构,弄混了GRF和PMUGRF,以为是同一个东西。直接就用错了,后来改了过来。

6.还是要适当使用uboot的md和mm工具,这样能方便直接读取寄存器的内容,根据实际的值去判断设置是否正确。

7.serial_din和serial_in也是一定要慎重,这个地方用错了,直接导致uboot崩了,无法进入loader模式,差点成砖了,还好最后发现还能用短路(emmc_clk和GND)的办法进入到maskrom模式。

三、代码

直接在ns16550.c中参考,并写在了该文件中。

 特别说明以下:

1.接收函数我使用了一个超时返回的方法,因为接收不到值得时候(比如没有连接屏,或者连接的屏型号不对呢等等各种因素吧),我不能一直卡着,就直接启动了。

2.发送函数我写死了,因为我只有一条查询指令,干脆就直接写了,要灵活使用的朋友注意一下。

#define PMUCRU_BASE	0xff750000void board_com4_init(void)
{
//gpio的初始化
#define PMUGRF_BASE	0xff320000struct rk3399_pmugrf_regs * const pmugrf = (void *)PMUGRF_BASE;/* Enable early UART4 channel on the RK3399/RK3399PRO */rk_clrsetreg(&pmugrf->gpio1a_iomux,PMUGRF_GPIO1A7_SEL_MASK,PMUGRF_UART4_RXD << PMUGRF_GPIO1A7_SEL_SHIFT);rk_clrsetreg(&pmugrf->gpio1b_iomux,PMUGRF_GPIO1B0_SEL_MASK,PMUGRF_UART4_TXD << PMUGRF_GPIO1B0_SEL_SHIFT);printf("board_com4_init done..\n");}void com4_init(void)
{struct NS16550 *com_port = (struct NS16550 *)0xff370000;  //com4int baud_divisor;//	unsigned int val_temp;//	volatile unsigned long* pmucru_clksel_con5 = (volatile unsigned long*)(PMUCRU_BASE + 0x0094);
//	val_temp = *pmucru_clksel_con5;
//	printf("1. val_temp = %u\n",val_temp);
//	val_temp &= ~(3 << 8);
//	val_temp |= (2<<8) | (2<<14);   //默认值是2,     时钟源选择24M输入
//	* pmucru_clksel_con5 = val_temp;/** We copy the code from above because it is already horribly messy.* Trying to refactor to nicely remove the duplication doesn't seem* feasible. The better fix is to move all users of this driver to* driver model.*/baud_divisor = ns16550_calc_divisor(com_port, 24000000,115200);serial_dout(&com_port->ier, CONFIG_SYS_NS16550_IER);serial_dout(&com_port->mdr1, 0x7);serial_dout(&com_port->mcr, 0);serial_dout(&com_port->fcr, UART_FCR_DEFVAL);
//	serial_dout(&com_port->fcr, UART_FCR_RXSR | UART_FCR_TXSR);   //不使能FIFOserial_dout(&com_port->lcr, UART_LCR_BKSE | UART_LCRVAL);   //设置波特率serial_dout(&com_port->dll, baud_divisor & 0xff);serial_dout(&com_port->dlm, (baud_divisor >> 8) & 0xff);	serial_dout(&com_port->lcr, UART_LCRVAL);serial_dout(&com_port->mdr1, 0x0);//1. gpio 初始化board_com4_init();printf("12-07-1,end com4_init\n");}void com4_send_cmd(void)
{	struct NS16550 *com_port = (struct NS16550 *)0xff370000;  //com4char cmd_buf[] = {0xa5,0x5a,0x88,0,0,0,0,0x87};int i;for(i=0;i<8;i++){while (!(serial_din(&com_port->lsr) & UART_LSR_THRE));serial_dout(&com_port->thr, cmd_buf[i]);//	printf("cmd_buf[i] = %d\n",cmd_buf[i]);}//	NS16550_putc(com_port, cmd_buf[i]);}//int is_com4_recv_data(void)
//{
//	struct NS16550 *com_port = (struct NS16550 *)0xff370000;  //com4
//
//	return(serial_in(&com_port->lsr) & UART_LSR_DR);
//
//}//-1 表示出错
int com4_recv_a_byte_data(void)
{struct NS16550 *com_port = (struct NS16550 *)0xff370000;  //com4int i = 0;while(!(serial_din(&com_port->lsr) & UART_LSR_DR))  //返回0表示没有数据{mdelay(1);   //延时1msi++;if(i>=200)   //最多等待200msreturn -1;}return serial_din(&com_port->rbr);   //收到数据了
}

宏定义自己加一下,grf_rk3399.h

 

实际使用的代码如下:

接收8个字节的代码,不是阻塞等待,是超时处理!!!! 


//返回-1 就是超时,-3表示校验和错误。
int com4_recv_lcd_type_data(void)
{char cmd_buf[12];int count = 0;int ret_val = 0;
//	int val;while(1){ret_val = com4_recv_a_byte_data();if(ret_val == -1)  //出错了return -1;cmd_buf[count] = ret_val;if(count == 0){if(cmd_buf[count] != 0xa5){count = 0;continue;}}else if(count == 1){if(cmd_buf[count] != 0x5a){count = 0;continue;}}else if(count >= 7)   //接收结束{printf("com4 lcd_type data :%x %x %x %x-- %x %x %x - %x\n",cmd_buf[0],cmd_buf[1],cmd_buf[2],cmd_buf[3],cmd_buf[4],cmd_buf[5],cmd_buf[6],cmd_buf[7]);//val = cmd_buf[0]+cmd_buf[1]+cmd_buf[2]+cmd_buf[3]+cmd_buf[4]+cmd_buf[5]+cmd_buf[6];if(((cmd_buf[2]+cmd_buf[3])&0xff) ==  cmd_buf[7])return cmd_buf[3];//			printf("%x %x %x %x-- %x %x %x - %x\n",cmd_buf[0],cmd_buf[1],cmd_buf[2],cmd_buf[3],
//					cmd_buf[4],cmd_buf[5],cmd_buf[6],
//					cmd_buf[7]);break;}count ++;}return -3;
}

 


http://www.ppmy.cn/news/3343.html

相关文章

类的六个默认成员函数

1.类的6个默认成员函数 如果一个类中什么成员都没有&#xff0c;简称为空类。空类中什么都没有吗&#xff1f;并不是的&#xff0c;任何一个类在我们不写的情 况下&#xff0c;都会自动生成下面6个默认成员函数。 2.构造函数 构造函数是一个特殊的成员函数&#xff0c;名字与…

[附源码]Node.js计算机毕业设计房屋中介管理信息系统Express

项目运行 环境配置&#xff1a; Node.js最新版 Vscode Mysql5.7 HBuilderXNavicat11Vue。 项目技术&#xff1a; Express框架 Node.js Vue 等等组成&#xff0c;B/S模式 Vscode管理前后端分离等等。 环境需要 1.运行环境&#xff1a;最好是Nodejs最新版&#xff0c;我…

对数据库索引的理解以及索引在MySQL中的数据结构

引言 索引在本质上相当于书的目录&#xff0c;通过目录就可以快速的找到某个章节对应的位置。索引的效果&#xff0c;就是加快了查找的速度。日常进行数据库的操作&#xff0c;一般地都是进行增删查改&#xff0c;而在很多场景中&#xff0c;进行查找的概率要比增删改大很多。…

java.security.NoSuchProviderException: no such provider: BC

1.问题描述&#xff1a;支付宝支付回调验签的时候出现错误&#xff1a;java.security.NoSuchProviderException: no such provider: BC 2.解决方法&#xff1a;引入下面依赖包 <dependency> <groupId>org.bouncycastle</groupId> &…

Go1.19.3 数组与切片原理简析

数组 Go语言数组&#xff0c;声明有如下几种方式&#xff1a; var arr1 [10]intarr1[0] 10000var arr2 [10]int{0:0,2:2}var arr3 [...]int{1,2,3}其中arr1只是进行声明&#xff0c;数组在声明时&#xff0c;内存空间已经被开辟过&#xff0c;所以可以赋值。arr2是声明的同…

Linux基本指令(2)

Linux基本指令(2) &#x1f4df;作者主页&#xff1a;慢热的陕西人 &#x1f334;专栏链接&#xff1a;Linux &#x1f4e3;欢迎各位大佬&#x1f44d;点赞&#x1f525;关注&#x1f693;收藏&#xff0c;&#x1f349;留言 本博客将展示25-30个LInux中常用的命令&#xff0c;…

SparkSQL 数据清洗API

文章目录常见数据清洗APIdropDuplicates数据去重dropna缺失值处理fillna缺失值填充Shuffle分区数目常见数据清洗API 在我们进行数据处理的时候&#xff0c;往往很多数据都是杂乱无章的数据&#xff0c;所以我们在处理数据时需要对数据进行预处理操作&#xff08;数据清洗&…

混检阳性概率的计算(贝叶斯定理的一个应用例)

目录 1. 混检阳性概率的计算 2. 混管阳性时你阳性的概率有多大&#xff1f; 2.1 贝叶斯分析结果的解释 1. 混检阳性概率的计算 目前核酸混检的基本做法是十混一&#xff0c;如果阳性人群分布完全随机&#xff0c;那么做十混一混检为阳性的概率有多大呢&#xff1f; …