当前位置: 首页 > article >正文

使用DM368的GPIO控制NANDFLASH的WP

目录

  • 0.问题描述
  • 1.DM368的GPIO操作
    • 1.1 gpio_request申请和冲突分析
      • 1.1.1 申请
      • 1.1.2 释放
      • 1.1.3 gpio_request冲突处理
    • 1.2 IOMUX的配置
      • 1.2.1 修改iomux寄存器
      • 1.2.2 通过davinci_cfg_reg函数配置
    • 1.3 IO的操作
  • 2.在Nand写入擦除操作中增加对WP的操作
    • 2.1 初始化、读写保护操作的定义
    • 2.2 WP引脚的操作
    • 2.3 测试是否生效

0.问题描述

最近需要使用DM368的GPIO控制NandFlash的WP引脚实现写保护功能,只在需要写入和擦除时才放开写保护。

1.DM368的GPIO操作

DM368的GPIO操作主要分为下面三步实现:

  1. gpio_request申请GPIO引脚
  2. 修改IOMUX寄存器,设置端口复用为GPIO模式
  3. 操作GPIO引脚

1.1 gpio_request申请和冲突分析

1.1.1 申请

在内核中申请GPIO,就是给GPIO进行加锁处理,防止被其他程序进行占用。

gpio_request的范例代码如下:

ret = gpio_request(gpioport[i],GPIO_REQ_NAME);
if(ret < 0)
{printk(KERN_EMERG "GPIO #%d req Fail,ret = %d\n",i,ret);return ret;
}

第一个参数是GPIO号,是一个整型数据。

第二个是锁的名称,方便后续debug和分析。

1.1.2 释放

释放GPIO使用gpio_free函数,函数参数是GPIO号。

gpio_free(gpionum);

1.1.3 gpio_request冲突处理

gpio_request申请gpio的时候,可能会申请失败。如果失败的返回值是-16,即Device or resource busy,说明这个GPIO被占用了。

这种时候可以使用debugfs进行分析。

首先,需要保证Kernel编译配置中打开了DEBUGFS选项(一般在Kernel hacking→Debug Filesystem),如下:

在目标板上查看/sys/kernel/debug/,如果是空白的则说明debugfs没有挂载上,使用下面命令挂载

mount -t debugfs debug /sys/kernel/debug/

挂载成功后可以看到debugfs文件系统的文件如下:

在这里插入图片描述

gpio文件中就是当前的gpio占用情况和电平输出情况:

在这里插入图片描述

如果自己使用的gpio被占用了,可以在kernel中找到占用的模块取消之,或使用别的端口。

1.2 IOMUX的配置

端口复用iomux的配置有两种方式。

  1. 直接使用寄存器进行修改(通用)
  2. 使用dm368内核中的davinci_cfg_reg函数配置(平台限定)

1.2.1 修改iomux寄存器

直接修改寄存器需要查阅DataSheet,定位到要修改的寄存器地址和要修改的位,修改即可。

首先查阅相关的DataSheet,这部分的内容在官方文档TMS320DM36x Digital Media System-on-Chip(DMSoC) ARM Subsystem User’s Guide中。

以修改GPIO35为例,可以看到,GPIO35位于PINMUX4的BIT16&BIT17:

在这里插入图片描述

配置为00时,作为GPIO使用:

在这里插入图片描述

从Datasheet中得知,我们要修改的是System Module Registers(简称SMR)的PINMUX4,地址是SMR基地址+0x10:

在这里插入图片描述

基地址可查阅Table 7:

在这里插入图片描述

则可得到实际地址为0x01C40000 + 0x10 = 0x01C40010。

之后只要将物理地址ioremap映射为虚拟地址,再对寄存器的相关值(BIT16-17)进行修改即可,这里不再展开说明。

volatile static unsigned long virt_addr = (unsigned long)ioremap(0x01C40010,0x20);
data = (unsigned long *)virt_addr;
data = xxxx; //要修改的值

1.2.2 通过davinci_cfg_reg函数配置

参考资料如下:

https://blog.csdn.net/xiufu004/article/details/7704823

简单来说,davinci_cfg_reg函数就是把dm365.c里的dm365_pins数组中对应位置的管脚复用信息转换成对PINMUX寄存器的操作。

以修改GPIO35为普通IO口为例子:

在dm365_pins数组中找到对应的引脚:

在这里插入图片描述

结合上一节分析,GPIO35在PINMUX4,BIT16-17,2位(mask = 0000 0011b = 3),设置为0时为GPIO。

即本行配置为

MUX_CFG(DM365,	SPI4_SDO,	4,   16,    3,    0,	 false)

之后再在初始化中调用davinci_cfg_reg(DM365_SPI4_SDO)即可。其中DM365_SPI4_SDO是上行配置在dm365_pins数组中的下标。

1.3 IO的操作

主要API:

设置为输出:

gpio_direction_output(GPIONUM,level);  //将GPIONUM的电平设置为level(0/1)

设置为输入:

 gpio_direction_input(GPIONUM);  //设置GPIONUM为输入

读取电平值

int level = gpio_get_value(GPIONUM);//读取GPIONUM的电平,返回给level

这些操作可以和ioctl/read/write等接口配合供上层调用测试。

2.在Nand写入擦除操作中增加对WP的操作

2.1 初始化、读写保护操作的定义

在nand_base.c中增加如下代码:

//NAND WP PART
#define WP_GPIO_PIN 35   //写保护的GPIO为GPIO 35
static int NAND_WP = 0;#define WP_ENABLE()  do {if(NAND_WP!=0) gpio_direction_output(NAND_WP,0); } while(0)   //写保护启用,拉低WP引脚
#define WP_DISABLE()  do {if(NAND_WP!=0) gpio_direction_output(NAND_WP,1); } while(0)  //写保护禁用,拉高WP引脚static void init_wp_pin()
{int ret;ret = gpio_request(WP_GPIO_PIN,"NAND WP"); //申请NAND的写保护引脚if(ret < 0){printk(KERN_EMERG "GPIO WP req Fail,ret = %d\n",ret);return ret;}davinci_cfg_reg(DM365_SPI4_SDO);  //设置IOMUX为DM365.c中dm365_pins的值,修改引脚的话需要改结构体或者自行配置IOMUX寄存器NAND_WP = WP_GPIO_PIN;   //申请到GPIO才走这里WP_ENABLE();   //默认开启写保护printk(KERN_EMERG "GPIO WP Init Success!!!!\n");
}

这段代码中实现了GPIO的申请操作,只有成功申请了GPIO35,才会给NAND_WP变量赋值。NAND_WP不为0时,说明初始化成功,可以进行GPIO控制WP的操作。

初始化代码需要在nand模块被装载时执行,放在module_init执行的函数中即可:

在这里插入图片描述

2.2 WP引脚的操作

查看对NAND FLASH操作的函数,发现操作开始之前会先执行nand_get_device,操作之后执行nand_release_device。

因此对该引脚的操作主要是在nand_release_device函数中增加写保护,在nand_get_device中判断操作为FL_WRITING或FL_ERASING时去掉写保护。

写保护解除:(看下方代码的START和END之间的部分)

/*** nand_get_device - [GENERIC] Get chip for selected access* @chip:	the nand chip descriptor* @mtd:	MTD device structure* @new_state:	the state which is requested** Get the device and lock it for exclusive access*/
static int
nand_get_device(struct nand_chip *chip, struct mtd_info *mtd, int new_state)
{spinlock_t *lock = &chip->controller->lock;wait_queue_head_t *wq = &chip->controller->wq;DECLARE_WAITQUEUE(wait, current);retry:spin_lock(lock);/* Hardware controller shared among independent devices */if (!chip->controller->active)chip->controller->active = chip;
//------------------START-----------------------------if(NAND_WP == 0)  //检查是否初始化WP,未初始化则再次初始化{init_wp_pin();}if(new_state == FL_WRITING || new_state == FL_ERASING) //只在写入和擦除时关闭写保护WP_DISABLE();
//------------------END-----------------------------if (chip->controller->active == chip && chip->state == FL_READY) {chip->state = new_state;spin_unlock(lock);return 0;}if (new_state == FL_PM_SUSPENDED) {spin_unlock(lock);return (chip->state == FL_PM_SUSPENDED) ? 0 : -EAGAIN;}set_current_state(TASK_UNINTERRUPTIBLE);add_wait_queue(wq, &wait);spin_unlock(lock);schedule();remove_wait_queue(wq, &wait);goto retry;
}

写保护开启:

/*** nand_release_device - [GENERIC] release chip* @mtd:	MTD device structure** Deselect, release chip lock and wake up anyone waiting on the device*/
static void nand_release_device(struct mtd_info *mtd)
{struct nand_chip *chip = mtd->priv;/* De-select the NAND device */chip->select_chip(mtd, -1);/* Release the controller and the chip */spin_lock(&chip->controller->lock);chip->controller->active = NULL;chip->state = FL_READY;
//---------------START--------------------------if(NAND_WP == 0){init_wp_pin();}WP_ENABLE();  //写保护开启
//--------------END----------------------wake_up(&chip->controller->wq);spin_unlock(&chip->controller->lock);
}

2.3 测试是否生效

  1. 查看开机的串口输出,是否出现了WP申请成功的Log:

在这里插入图片描述

  1. 万用表测量WP脚,平时是否一直为低电平。

  2. 在目标板Linux Shell中进行文件读写删除操作,操作不报错,重启后文件仍然存在,说明修改成功。

http://www.lryc.cn/news/2413923.html

相关文章:

  • Java图形化界面编程超详细知识点(7)——进度条
  • 雅虎YUI 3.7.1发布
  • FastDFS,Redis,Solr,ActiveMQ核心技术整合二(1)
  • CTF training WriteUp
  • 【转】花开正当时,十四款120/128GB SSD横向评测
  • widgets
  • win7开机出现修复计算机,win7开机提示系统自动修复无法正常进入的原因分析及解决...
  • 空间转换与动画
  • cf聊天室,cf聊天室下载
  • VM虚拟机常见问题之二----声卡驱动问题
  • 数字系统的设计
  • C语言笔记1
  • Windows中d3dx9_28.dll丢失解决
  • 脾胃系病证--便秘,痢疾,泄泻,腹痛,呃逆。。。。。。。。
  • 联想android手机驱动,驱动天空 - 手机驱动 - 联想手机 lenovo
  • show java玩jar游戏_指小游Java模拟器v1.2/安卓手机上玩jar游戏
  • 数据中台技术选型和厂商分析
  • NO.117 国内8大免费CMS建站系统。
  • 【2024最新版】超详细Aircrack-ng安装保姆级教程,破译WiFi,收藏这一篇就够了
  • 【Python】成功解决FileNotFoundError: [Errno 2] No such file or directory: ‘xxx‘
  • k2698场效应管参数电流_LDO 基础特性 2 静态电流
  • ZYNQ学习笔记(一):基于ZYNQ7020、AN108的DDS实验(VIO可控频率字)
  • 002:如何画出收盘价的曲线图
  • DVI-A、DVI-D、DVI-I接口定义、DVI接口图和DVI接口标准介绍
  • 微软windows 8.1 Preview 预览版发布下载
  • Build qt5.15.0 qtbase on SUSE SLE-15
  • 网吧破解还原卡的方法总结!!
  • java 内存配置优化_JAVA调优设置 内存占用过大
  • IT开发技术群
  • Windows源码分析 - 1.初始化内核与执行体子系统