[RK3399][Uboot]使用内存映射方式直接控制IO

这篇具有很好参考价值的文章主要介绍了[RK3399][Uboot]使用内存映射方式直接控制IO。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

系列文章目录

第一章 [RK3399][Uboot]使用内存映射方式直接控制IO



前言

嵌入式工作这么多年,经常会用到GPIO,通常是使用内核的API或Sysfs来操作GPIO,直接操作GPIO寄存器的情况或GPIO内存映射的情况比较少,本文就针对RK3399平台的GPIO,以操作GPIO地址映射的方式来控制一下GPIO。会涉及到GPIO的IOMUX,Pull Up/Pull Down, 设置输入输出,给输出设置高电平等方面。本文重点会跟踪GPIO4_A1和GPIO4_D6这两个GPIO。


目标

1.查看并设置GPIO4_A1的IOMUX和Pull Up/Pull Down状态,并设置其默认Pull Down.
2.查看并设置GPIO4_D6输入输出状态,并设置其输出高电平。

一、GPIO的地址映射

[RK3399][Uboot]使用内存映射方式直接控制IO

[RK3399][Uboot]使用内存映射方式直接控制IO
[RK3399][Uboot]使用内存映射方式直接控制IO

上两图中我标出了GPIO使用的几个基地址。
涉及到GPIO的IOMUX和Pull Up/Pull Down的有GRF和PMUGRF。
涉及到具体GPIO输入输出的有GPIO0/GPIO1/GPIO2/GPIO3/GPIO4这几个基地址。
GPIO4_A1要查看IOMUX和Pull Up/Pull Down,所以要用到它的GRF基地址,从第二个图中可知,GRF基地址为:0xFF770000
IOMUX用GRF_GPIO4A_IOMUX地址:GRF基地址+偏移地址=0xFF770000 + 0x0E020 = 0xFF77E020
Pull Up/Pull Down用GRF_GPIO4A_P地址:GRF基地址 + 偏移地址 = 0xFF7700 + 0x0E060 = 0xFF77E060
GPIO4_D6要查看并设置输入输出,所以要用到GPIO4的基地址,从第二个图中可知,GPIO4的基地址为:0xFF790000
DDR输入输出方向设置寄存器,使用GPIO_SWPORTA_DDR地址:GPIO4基地址+偏移地址 = 0xFF790000 + 0x0004 = 0xFF790004
DR数据寄存器,使用GPIO_SWPORTA_DR地址:GPIO4基地址+偏移地址 = 0xFF790000 + 0x0000 = 0xFF790000

二、设置GPIO

1.GPIO的IOMUX及PULL

[RK3399][Uboot]使用内存映射方式直接控制IO
IOMUX 默认值为:0x00000000
二进制表示为:【0000 0000 0000 0000 0000 0000 0000 0000】
从寄存器的详细描述中可以看出,高16位用来标记低16位是否可写,1代表可写,从左往右,GPIO4_A7到GPIO4_A0共占用16位,每个IO占用2位。同时可以看到GPIO4_A1在CPU Reset时,默认的IOMUX为GPIO功能。

PU/PD默认值为: 0x0000aa96
二进制制表示:【0000 0000 0000 0000 1010 1010 1001 0110】
从寄存器的详细描述中可以看出,高16位用来标记低16位是否可写,1代表可写,从左往右,GPIO4_A7到GPIO4_A0共占用16位,每个IO占用2位。同时可以看到GPIO4_A1在CPU Reset时,默认的PU/PD 为01,即Pull-Up。

2.设置GPIO的PULL

IOMUX设置与PU/PD设置类似,这里以PU/PD设置举例。
设置GPIO4_A1由默认的Pull-Up为Pull-Down,高16位设置为1,IO对应位由01变成10即 【1111 1111 1111 1111 1010 1010 1001 1010】,16进制表示为0xffffaa9a
代码设置如下:

/* GPIO4_A1 PU/PD 设置为Pull-Down */
u32 value;
value = 0xffffaa9a;
iowrite32(value,(void *)(0xFF77E060));
value = ioread32((void *)(0xFF77E060));
printf("GPIO4_Ax PU/PD Setting value:[0xFF77E060] 0x%08x\n",value);

上面的value为我们要设置GPIO4_A1为Pull-Down的值0xffffaa9a,使用iowrite32这个函数,把它写到GPIO4的PULL地址0xFF77E060,然后再通过ioread32这个函数打印出来验证我们是否写成功。

3.GPIO的DDR及DR

DDR: 0x00000000
二进制表示为:【00000000 00000000 00000000 00000000】
DDR寄存器32位,每8位一组,位置从左往右,代表GPIOD到GPIOA。
比如一个DR值为: 0x11223344,其中0x11代表GPIOD中的8个IO,从左往右为GPIOx_D7到GPIOx_D0,0x44代表GPIOA中的8个IO,从左往右为GPIOx_A7到GPIOx_A0。
再看GPIOA中的8个IO用0x44是怎么表示的,它换成二进制为0100 0100,从左往右依次代表GPIOx_A7 到 GPIOx_A0,即GPIOx_A6和GPIOx_A2为1,其它为0。DDR相应位设置1为输出模式,0为输入模式。

DR值: 0x00000000
二进制表示为:【00000000 00000000 00000000 00000000】
DR寄存器有32位,每8位一组,位置从左往右,代表GPIOD到GPIOA。
比如一个DR值为: 0x11223344,其中0x11代表GPIOD中的8个IO,从左往右为GPIOx_D7到GPIOx_D0,0x44代表GPIOA中的8个IO,从左往右为GPIOx_A7到GPIOx_A0。
再看GPIOA中的8个IO用0x44是怎么表示的,它换成二进制为0100 0100,从左往右依次代表GPIOx_A7 到 GPIOx_A0,即GPIOx_A6和GPIOx_A2为1,其它为0。当DDR相应位设置为1即输出模式时,往相应位写1,代表拉高该IO。

4. 设置GPIO的DDR及DR

GPIO4_D6输出设置,值为 0100 0000 即0x40,写到DDR寄存器的值为0x40000000,同样DR寄存器的值为0x40000000。
代码如下:

/* GPIO4_D6 DDR 设置输出 */
/* GPIO4_DX: 01000000 40 */
/* GPIO4_CX: 00000000 00 */
/* GPIO4_BX: 00000000 00 */
/* GPIO4_AX: 00000000 00 */
value = 0x40000000;
iowrite32(value, (void *)(0xFF790004));
value = ioread32((void *)(0xFF790004));
printf("GPIO4_xx DDR Setting value:[0xFF790004] 0x%08x\n",value);

/* GPIO4_D6 DR 输出高 */
value = 0x40000000;
iowrite32(value, (void *)(0xFF790000)); //DR High

0x40000000表示GPIO4_D6设置为输出及输出高,所以把这个值写到DDR寄存器地址0xFF790004和DR寄存器地址0xFF790000即可

5.完整代码验证

我们在Uboot中设置IO及其它输入输出。
代码如下:

diff --git a/common/board_f.c b/common/board_f.c
index 8bceb0c..ab54ec4 100644
--- a/common/board_f.c
+++ b/common/board_f.c
@@ -259,7 +259,7 @@ static int setup_mon_len(void)
 	return 0;
 }
 
+static int io_test(void)
+{
+	u32 value;
+
+	/* GPIO4_Ax IOMUX */
+	value = ioread32((void *)(0xFF77E020));
+	printf("GPIO4_Ax IOMUX Reset value:[0xFF77E020] 0x%08x\n",value);
+	
+	/* GPIO4_Ax PU/PD */
+	value = ioread32((void *)(0xFF77E060));
+	printf("GPIO4_Ax PU/PD Reset value:[0xFF77E060] 0x%08x\n",value);
+	
+	/* GPIO4_A1 PU/PD 设置为Pull-Down */
+	value = 0xffffaa9a;
+	iowrite32(value,(void *)(0xFF77E060));
+	value = ioread32((void *)(0xFF77E060));
+	printf("GPIO4_Ax PU/PD Setting value:[0xFF77E060] 0x%08x\n",value);
+
+	/* GPIO4_xx DDR/DR */
+	value = ioread32((void *)(0xFF790000));
+	printf("GPIO4_xx DR Reset value:[0xFF790000] 0x%08x\n",value);
+	value = ioread32((void *)(0xFF790004));
+	printf("GPIO4_xx DDR Reset value:[0xFF790004] 0x%08x\n",value);
+	
+	/* GPIO4_D6 DDR 设置输出 */
+	/* GPIO4_DX: 01000000 40 */
+	/* GPIO4_CX: 00000000 00 */
+	/* GPIO4_BX: 00000000 00 */
+	/* GPIO4_AX: 00000000 00 */
+	value = 0x40000000;
+	iowrite32(value, (void *)(0xFF790004));
+	value = ioread32((void *)(0xFF790004));
+	printf("GPIO4_xx DDR Setting value:[0xFF790004] 0x%08x\n",value);
+
+	/* GPIO4_D6 DR 循环输出高,低 */
+	while (1)
+	{
+		value = 0x40000000;
+		iowrite32(value, (void *)(0xFF790000)); //DR High
+		udelay(500*1000);
+		value = 0x00000000;
+		iowrite32(value, (void *)(0xFF790000)); //DR Low
+		udelay(500*1000);
+		value = 0x40000000;
+		iowrite32(value, (void *)(0xFF790000)); //DR High
+		udelay(500*1000);
+		value = 0x00000000;
+		iowrite32(value, (void *)(0xFF790000)); //DR Low
+		udelay(500*1000);
+	}
+
+	return 0;
+}
+
 __weak int arch_fpga_init(void)
 {
 	return 0;
@@ -968,7 +1022,8 @@ __weak int arch_cpu_init_dm(void)
 
 static const init_fnc_t init_sequence_f[] = {
 	setup_mon_len,
+	io_test,
 #ifdef CONFIG_OF_CONTROL
 	fdtdec_setup,
 #endif

输入如下结果:
[RK3399][Uboot]使用内存映射方式直接控制IO


总结

以上就是今天要讲的内容,本文使用操作GPIO地址映射的方式来直接控制IO,设置了GPIO4_A1为下拉,GPIO4_D6默认输出高。在uboot阶段对IO进行设置初始化。希望您看到此文有所收获,也希望如果您看到有错误的地方,能不吝赐教。文章来源地址https://www.toymoban.com/news/detail-411710.html

到了这里,关于[RK3399][Uboot]使用内存映射方式直接控制IO的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • [RK-Linux] RK3399使用RK开源SPL,修改U-Boot为FIT打包方式,裁剪trust分区

    RK3399平台根据前级Loader代码是否开源,目前有两套启动方式: TPL 相当于 ddr bin,SPL 相当于 miniloader。TPL+SPL 的组合实现了跟 RK 闭源 ddr.bin+miniloader 一致的功能,可相互替换。 FIT(flattened image tree)是U-Boot支持的一种新固件类型的引导方案,支持任意多个image打包和校验。FIT 使

    2024年01月16日
    浏览(28)
  • 基于 RK3399+fpga 的 VME 总线控制器设计(一)总体设计

    2.1 需求分析及技术指标 2.1.1 需求分析 VME 总线控制器需要实现数据传输、中断处理、测量显示等功能。同时还需 要具有操作系统、底层驱动程序以及功能接口等,以方便用户进行上层应用软件开 发及使用。 本课题需要实现 VME 控制器的国产化开发,因此需要选择一款国产处

    2024年02月14日
    浏览(33)
  • 基于 RK3399+fpga 的 VME 总线控制器设计(二)硬件和FPGA逻辑设计

    3.2 FPGA 最小系统设计 FPGA 最小系统是指可以使 FPGA 正常工作的最基本的系统,主要包括电源电 路、配置电路、时钟和复位电路。本次设计使用的 FPGA 为紫光同创的 PG2L100H, 接下来具体介绍 FPGA 最小系统各个部分的电路设计。 ( 1 )电源电路设计 FPGA 所需要的电源电压有 3.3V

    2024年02月12日
    浏览(32)
  • RK3399平台开发系列讲解(内核调试篇)Valgrind使用案例

    🚀 返回专栏总目录 沉淀、分享、成长,让自己和他人都能有所收获!😄 📢 Valgrind 是一个开源的内存调试和性能分析工具,用于帮助开发者找出程序中的内存错误,如内存泄漏、使用未初始化的内存、非法内存访问等问题。它在 Linux 平台上广泛使用,并且支持多种处理器

    2024年02月12日
    浏览(26)
  • RK3399平台开发系列讲解(内核调试篇)spidev_test工具使用

    🚀 返回专栏总目录 沉淀、分享、成长,让自己和他人都能有所收获!😄 📢 在 Linux 系统上,“ spidev_test ” 是一个用于测试和配置 SPI ( Serial Peripheral Interface )设备的命令行工具。 SPI 是一种串行通信协议,通常用于连接微控制器、传感器和其他外部设备。“ spidev_test ”

    2024年02月09日
    浏览(28)
  • 6.2物联网RK3399项目开发实录-驱动开发之GPIO使用(wulianjishu666)

    物联网嵌入式开发源码例程: 链接:https://pan.baidu.com/s/1B3oqq5QBhN-VmTFt9CI-7A?pwd=2ihg  ******************************************************************************************* GPIO, 全称 General-Purpose Input/Output(通用输入输出),是一种软件运行期间能够动态配置和控制的通用引脚。 RK3399 有 5 组 GP

    2024年04月28日
    浏览(25)
  • 6.9物联网RK3399项目开发实录-驱动开发之PWM的使用(wulianjishu666)

    嵌入式实战开发例程,珍贵资料,开发必备: 链接:https://pan.baidu.com/s/1149x7q_Yg6Zb3HN6gBBAVA?pwd=hs8b ====================================================================== AIO-3399J 开发板上有 4 路 PWM 输出,分别为 PWM0 ~ PWM3,4 路 PWM 分别使用在 EDP 背光、MIPI 背光、VDDLOG 供电、红外 IR。 本章主要描

    2024年04月28日
    浏览(24)
  • 6.5物联网RK3399项目开发实录-驱动开发之LCD显示屏使用(wulianjishu666)

    90款行业常用传感器单片机程序及资料【stm32,stc89c52,arduino适用】 链接:https://pan.baidu.com/s/1M3u8lcznKuXfN8NRoLYtTA?pwd=c53f  ======================================================== AIO-3399J开发板外置了两个LCD屏接口,一个是EDP,一个是LVDS,接口对应板子上的位置如下图: DTS配置 引脚配置 AIO-3

    2024年04月09日
    浏览(27)
  • 6.7物联网RK3399项目开发实录-驱动开发之Camera摄像头的使用(wulianjishu666)

    90款行业常用传感器单片机程序及资料【stm32,stc89c52,arduino适用】 链接:https://pan.baidu.com/s/1M3u8lcznKuXfN8NRoLYtTA?pwd=c53f  ======================================================== AIO-3399J 开发板分别带有两个 MIPI,MIPI 支持最高 4K 拍照,并支持 1080P 30fps 以上视频录制。此外,开发板还支持 USB 摄

    2024年04月13日
    浏览(32)
  • 36、RK3399Pro 环境搭建和Yolov5 c++调用opencv进行RKNN模型部署和使用

    基本思想:记录rk3399 pro配置环境和c++ npu开发记录,主要想搞一份c++代码和其它图像算法结合一下,好进行部署,淘宝链接见附录  需要的python3.7对应的aarch64的whl包:包含opencv-whl 、h5py-whl包: 链接: https://pan.baidu.com/s/1cvCAmHBa_4KgEjrcFIYnig 提取码: 5ui4 链接: https://pan.baidu.com/s/1hrc

    2024年02月07日
    浏览(27)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包