Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

How to implement EEPROM device driver in SylixOS

2025-04-01 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Internet Technology >

Share

Shulou(Shulou.com)06/02 Report--

SylixOS how to achieve EEPROM device driver, many novices are not very clear about this, in order to help you solve this problem, the following editor will explain in detail for you, people with this need can come to learn, I hope you can gain something.

1. Development environment

Operating system: SylixOS

Programming environment: RealEvo-IDE3.1.5

Hardware platform: SAMA5D2 Xplained development board

Introduction to 2.EEPROM

EEPROM, or E2PROM, the full name of electronic erasable rewritable read-only memory (English: Electrically-Erasable Programmable Read-Only Memory), is a semiconductor memory device that can be copied many times electronically. In contrast, the EPROM,EEPROM does not need to be exposed to ultraviolet light or removed, and a specific voltage can be used to erase the information on the chip so that new data can be written.

2.1 Storage structure and device address

The model of EEPROM chip used in this paper is AT24MAC402, which provides 2Kbit serial electrically erasable programmable memory cell, namely 256bytes, and can read and write through I2C compatible serial interface (TWI). In addition, AT24MAC402 can be used to store a globally unique MAC or EUI address (EUI-48). Its internal storage organization is shown in figure 2-1.

Figure 2-1 AT24MAC402 internal storage structure

As you can see from figure 2-1, AT24MAC402 provides an extended storage portion of 128-bit Serial Number and 48-bit (9Ah-9Fh) to store serial numbers and globally unique MAC or EUI addresses. As I2C slave devices, the internal storage addresses of these two parts of the EEPROM (standard and extended) can be accessed through two different device addresses. The addressing of these two parts in AT24MAC402's chip manual is shown in figure 2-2.

Figure 2-2 device address

The Bit [3:1] is determined by the hardware pin level, and the read and write operations can be performed for the standard EEPROM without write protection, while the extension only supports read operations. The circuit diagram of the SAMA5D2 development board EEPROM is shown in figure 2-3.

Figure 2-3 EEPROM circuit diagram wiring

Combined with figure 2-2, we can see that the device address of the standard part of EEPROM is' 1010100, or 0x54, and the device address of the extension is' 1011100, or 0x5C.

2.2 Operation mode

2.2.1 read operation

Both the standard EEPROM section and the extension section support read operations, and EEPROM supports the following three types of read operations:

Current address read: in the current address read operation mode, there is no need to send read byte address, only the data stored in the current address is read out each time, and the on-chip address is always self-added until it returns to zero address after reading the whole EEPROM.

Random address reading: the master device sends a valid slave device internal address, and after sending a response signal from the slave device, the data at that internal address will be sent to the master device through I2C.

Sequential read: the multi-byte continuous read operation can be either the current address read or the random address read. Each time the processor receives a byte of data, it returns an ACK,EEPROM. After receiving this ACK, the address is automatically added by 1, and then the next byte of data is output until the processor returns NO ACK. The reading process ends.

2.2.2 write operation

The standard EEPROM section provides write operations when write protection is disabled, and supports the following two write operations:

Byte write: when writing by bytes, usually after sending the device address to EEPROM and receiving the reply signal, the send write byte address starts to write data after receiving ACK again, and finally sends the stop bit to end the write operation.

Page writing: when writing a page, EEPROM can write a whole page of data continuously (16 bytes per page). The process of sending an address is exactly the same as when writing bytes. The difference is whether the processor sends a stop state after writing a byte of data, but continues to write data after the reply signal. After each byte is received, EEPROM returns an ACK until the complete page is written. If the number of writes when the page is written exceeds the boundary of the physical page, the excess data will be rewritten to the data written before the header address is overwritten.

3. Technical realization

In this paper, the device driver of EEPROM is realized by kernel module.

The writing of the EEPROM driver is also a member function of the device file operation control block structure file_operations. In the EEPROM device driver, the functions of _ _ e2promOpen, _ _ e2promClose, _ _ e2promRead, _ _ e2promWrite, _ _ e2promIoctl are mainly realized, and the _ _ e2promIoctl function is used to set the internal address of the EEPROM to be accessed.

The application can read and write the EEPROM device by accessing the standard file iMaple O function. Before reading and writing the EEPROM device, it can call the lseek function to set the address of the eeprom internal register to be read / write, and then call the standard file iMaple O to read / write the internal address.

The reading and writing function of EEPROM is essentially realized by calling the sending interface of I2C equipment. Here, a character-driven framework is used to implement the read and write operation of EEPROM. Because the device addresses of the standard EEPROM and the extension are different, but the operation of the two parts is the same, this paper only gives the driver implementation of the standard EEPROM device.

The standard EEPROM device file operation structure is shown in listing 3-1 of the program.

Listing 3-1 e2prom device file operation set

/ * e2prom device file operation set * * / struct file_operations GfileOperate = {.fo _ open = _ _ e2promOpen .fo _ close = _ _ e2promClose, .fo _ read = _ _ e2promRead, .fo _ write = _ _ e2promWrite, .fo _ ioctl = _ _ e2promIoctl}

You can finally call the corresponding member function in the file_operations structure by calling the standard Imax O function.

3.1 read operation

_ _ e2promRead reads EEPROM internal data, and its implementation is shown in listing 3-2 of the program.

Listing 3-2 _ _ e2promRead implementation

/ * function name: _ _ e2promRead * * function description: read eeprom device * * input: pvArg version type selection parameter * * pcBuffer buffer * * stMaxByte buffer size * * output: ERROR * * * / static ssize_t _ _ e2promRead (PVOID pvArg PCHAR pcBuffer, size_t stMaxByte) {UINT32 uiRet If (! pcBuffer) {return PX_ERROR;} uiRet = _ _ at24xxRead (Gi2cDev, Goffset, (UINT8 *) pcBuffer, stMaxByte); Goffset = (Goffset + stMaxByte)% EEPROM_MEM_SIZE; / * Internal address counter save value * / return (uiRet = = ERROR_NONE)? StMaxByte:PX_ERROR;}

_ _ e2promRead will call the at24xxRead function to perform the read operation, as shown in listing 3-3 of the program at24xxRead implementation.

Listing 3-3 at24xxRead implementation

/ * function name: _ _ at24xxRead * * function description: AT24xx register read function * * input: pI2cDev i2c device * * RegAddress register address * * buf data reception buffer * * data length to be read by len * * output: return 0 indicates successful execution of the function. * / static int _ _ at24xxRead (PLW_I2C_DEVICE pI2cDev UINT8 ucRegAddress, UINT8 * ucBuf, UINT uiLen) {INT iError LW_I2C_MESSAGE i2cMsgs [2] = {{.I2CMSG _ usAddr = pI2cDev- > I2CDEV_usAddr, .I2CMSG _ usFlag = 0, / * 0 indicates write operation * / .I2CMSG _ usLen = sizeof (ucRegAddress), .I2CMSG _ pucBuffer = & ucRegAddress / * write the register address to read first * /}, {.I2CMSG _ usAddr = pI2cDev- > I2CDEV_usAddr, .I2CMSG _ usFlag = LW_I2C_M_RD / * indicates read operation * / .I2CMSG _ usLen = uiLen, .I2CMSG _ pucBuffer = ucBuf, / * read operation * /}} IError = API_I2cDeviceTransfer (pI2cDev, i2cMsgs, 2); if (iError

< 0) { return (PX_ERROR); } return (ERROR_NONE); } 实质上,应用层调用read函数,最终是调用的API_I2cDeviceTransfer函数实现接收与发送操作。 3.2 写操作 __e2promWrite向EEPROM写入数据,其实现如程序清单 3-4所示。 程序清单 3-4 e2promWrite实现 /********************************************************************************************************* ** 函数名称: __e2promWrite ** 功能描述: 写eeprom设备 ** 输 入 : pvArg 版本类型选择参数 ** pcBuffer 缓冲区 ** stMaxByte 缓冲区大小 ** 输 出 : ERROR *********************************************************************************************************/ static ssize_t __e2promWrite(PVOID pvArg, PCHAR pcBuffer, size_t stMaxByte) { UINT32 uiRet; if(!pcBuffer) { return PX_ERROR; } uiRet = __at24xxWrite (Gi2cDev, Goffset, (UINT8 *)pcBuffer, stMaxByte); Goffset = (Goffset + stMaxByte) % EEPROM_MEM_SIZE; /* 内部地址计数器保存值 */ return (uiRet == ERROR_NONE) ? stMaxByte:PX_ERROR; } __e2promWrite将会调用at24xxWrite函数实现EEPROM的写操作,at24xxWrite实现如程序清单 3-5所示。 程序清单 3-5 at24xxWrite实现 /********************************************************************************************************* ** 函数名称: __at24xxWrite ** 功能描述: AT24xx 寄存器写函数 ** 输 入 : pI2cDev i2c设备 ** RegAddress 寄存器地址 ** buf 需要写入寄存器的数据 ** len 写入数据长度 ** 输 出 : 返回 0 表示函数执行成功 *********************************************************************************************************/ static int __at24xxWrite (PLW_I2C_DEVICE pI2cDev, UINT8 ucRegAddress, UINT8 *ucBuf, UINT uiLen) { INT iError; if(!pI2cDev) { return PX_ERROR; } /* * 发送缓存大小:至少为(数据+地址)字节数 */ UINT8 *pui2cBuf = (UINT8 *)malloc(uiLen+1); LW_I2C_MESSAGE i2cMsgs[1] = { { .I2CMSG_usAddr = pI2cDev->

I2CDEV_usAddr, .I2CMSG _ usFlag = 0, / * 0 means write operation * / .I2CMSG _ usLen = uiLen + sizeof (ucRegAddress), / * (data + address) bytes * / .I2CMSG _ pucBuffer = pui2cBuf,},} / * * address information is stored at the beginning of the send cache, followed by data * / pui2cBuf [0] = ucRegAddress; memcpy (& pui2cBuf [1], & ucBuf [0], uiLen); iError = API_I2cDeviceTransfer (pI2cDev, i2cMsgs, 1); if (iError)

< 0) { free(pui2cBuf); printk(KERN_ERR "__at24xxWrite(): failed to i2c transfer!\n"); return (PX_ERROR); } free(pui2cBuf); return (ERROR_NONE); } 实质上,应用层调用write函数,最终是调用的API_I2cDeviceTransfer函数实现接收与发送操作。 3.3 设置读写地址 通过实现__e2promIoctl函数,完成设置待读/写的EEPROM的内部寄存器地址,其实现如程序清单 3-6所示。 程序清单 3-6 __e2promIoctl实现 /********************************************************************************************************* ** 函数名称: __e2promIoctl ** 功能描述: 控制eeprom设备 ** 输 入 : pdevhdrHdr 设备头 ** iCmd 命令 ** lArg 命令参数 ** 输 出 : ERROR *********************************************************************************************************/ static INT __e2promIoctl(PLW_DEV_HDR pdevhdrHdr, INT iCmd, LONG lArg) { INT iError; struct stat *pstat; switch(iCmd) { case FIOSEEK: /* 获取e2prom内部地址偏移 */ Goffset = *(off_t *)lArg; break; case FIOFSTATGET: /* 获得文件属性 */ pstat = (struct stat *)lArg; pstat->

St_dev = (dev_t) pdevhdrHdr; pstat- > st_ino = (ino_t) 0; / * equivalent to a unique node * / pstat- > st_mode = 0644 | S_IFCHR / * default properties * / pstat- > st_nlink = 1; pstat- > st_uid = 0; pstat- > st_gid = 0; pstat- > st_rdev = 1; pstat- > st_size = 0; pstat- > st_blksize = 0; pstat- > st_blocks = 0 Pstat- > st_atime = API_RootFsTime (LW_NULL); / * root fs base time is used by default * / pstat- > st_mtime = API_RootFsTime (LW_NULL); pstat- > st_ctime = API_RootFsTime (LW_NULL); break; default: errno = ENOSYS; iError = PX_ERROR; break } return ERROR_NONE;}

By calling lseek in the application layer, the underlying _ _ e2promIoctl function can be called. In the _ _ e2promIoctl function, by assigning a value to the global variable Goffset, when the read/write function is called, the corresponding _ _ e2promRead/ _ _ e2promWrite at the bottom can obtain the offset value of Goffset, and then read / write to the internal register of EEPROM.

3.4 initialization and uninstallation of driver module

The driver module initialization implementation is shown in listing 3-7.

Program listing 3-7 module initialization

/ * function name: module_init * * function description: driver loading module * * input: NONE * * output: ERROR_CODE * * * / int module_init (void) {printk ("hello_module init!\ n") INT iDrvNum = API_IosDrvInstallEx (& GfileOperate); / * install driver * / API_IosDevAdd (& GdevhdrHdr, "/ dev/eeprom", iDrvNum) / * install the device * / Gi2cDev = API_I2cDeviceCreate ("/ bus/i2c/1", "/ dev/eeprom", DEVICE_ADDR, 0); return ERROR_NONE;}

The module unloading implementation is shown in listing 3-8.

Program listing 3-8 module uninstall

/ * function name: module_exit * * function description: driver uninstall module * * input: NONE * * output: NONE * * / void module_exit (void) {printk ("hello_module exit!\ n") API_IosDevDelete (& GdevhdrHdr); / * delete device * / API_I2cDeviceDelete (Gi2cDev); / * delete specified i2C device * / return;} is it helpful for you to read the above content? If you want to know more about the relevant knowledge or read more related articles, please follow the industry information channel, thank you for your support.

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Internet Technology

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report