Peripheral Driver Operation Guide
Peripheral Driver Operation Guide
Operation Guide
Issue 01
Date 2018-05-15
Copyright © HiSilicon Technologies Co., Ltd. 2018. All rights reserved.
No part of this document may be reproduced or transmitted in any form or by any means without prior
written consent of HiSilicon Technologies Co., Ltd.
, , and other HiSilicon icons are trademarks of HiSilicon Technologies Co., Ltd.
All other trademarks and trade names mentioned in this document are the property of their respective
holders.
Notice
The purchased products, services and features are stipulated by the contract made between HiSilicon and
the customer. All or part of the products, services and features described in this document may not be
within the purchase scope or the usage scope. Unless otherwise specified in the contract, all statements,
information, and recommendations in this document are provided "AS IS" without warranties, guarantees
or representations of any kind, either express or implied.
The information in this document is subject to change without notice. Every effort has been made in the
preparation of this document to ensure accuracy of the contents, but all statements, information, and
recommendations in this document do not constitute a warranty of any kind, express or implied.
Website: http://www.hisilicon.com
Email: [email protected]
Purpose
This document describes how to manage the peripherals connecting to the modules that have
the gigabit media access control (GMAC) and universal serial bus (USB) 2.0 Host driver
installed. It covers the following topics, namely, preparations, operation procedures,
precautions to be taken during operation, and operation instances.
Related Version
The following table lists the product version related to this document.
Intended Audience
This document is intended for:
Technical support personnel
Software development engineers
Change History
Changes between document issues are cumulative. Therefore, the latest document issue
contains all changes made in previous issues.
Issue 01 (2018-05-15)
This issue is the first official release.
The description of the Hi3520D V400 is added.
Contents
2 Operation Guide to the USB 2.0 /USB 3.0 Host Module ....................................................... 5
2.1 Preparations ...................................................................................................................................................... 5
2.2 Procedure ......................................................................................................................................................... 5
2.3 Operation Instances .......................................................................................................................................... 6
2.3.1 Operation Instance Related to the USB Flash Drive ............................................................................... 6
2.3.2 Using the Keyboard ................................................................................................................................ 8
2.3.3 Using the Mouse ..................................................................................................................................... 8
2.4 Precautions ....................................................................................................................................................... 8
6 Appendix ...................................................................................................................................... 30
6.1 Partitioning a Storage Device ......................................................................................................................... 30
6.1.1 Checking the Current Partition Status of a Storage Device................................................................... 30
6.1.2 Creating Partitions for a Storage Device ............................................................................................... 30
6.1.3 Saving the Partition Information ........................................................................................................... 32
6.2 Formatting a Partition..................................................................................................................................... 32
6.3 Mounting a Directory ..................................................................................................................................... 32
6.4 Reading/Writing to a File ............................................................................................................................... 32
Figures
The following addresses are only examples. You need to configure the addresses as required.
Note the following when using the network interface under the kernel:
You can configure the IP address and subnet mask by running the following command:
ifconfig eth0 xxx.xxx.xxx.xxx netmask xxx.xxx.xxx.xxx up
You can set the default gateway by running the following command:
route add default gw xxx.xxx.xxx.xxx
1.2 IPv6
The IPv6 function is disabled in the release package by default. If the IPv6 function is
required, you need to modify the kernel options and recompile the kernel as follows:
cd kernel/linux-3.18.y
cp arch/arm/configs/hi35xx_full_defconfig .config
make ARCH=arm CROSS_COMPILE=arm-hisivXXX-linux- menuconfig
Go to the following directories and configure the options, as shown in Figure 1-1.
[*] Networking support --->
Networking options --->
<*> The IPv6 protocol --->
The threshold for activating the process of transmitting pause frames must be less than the threshold for
deactivating the process of transmitting pause frames.
As shown in the preceding displayed information, both RX flow control and TX flow control
are enabled.
You can enable or disable TX/RX flow control by running the following commands:
# ./ethtool -A eth0 rx off (Disable RX flow control)
# ./ethtool -A eth0 rx on (Enable RX flow control)
# ./ethtool -A eth0 tx off (Disable TX flow control)
# ./ethtool -A eth0 tx on (Enable TX flow control)
The USB 2.0 and USB 3.0 of the Hi3531D V100 support the host mode.
The USB 2.0 of the Hi3521D V100 and Hi3520D V400 support the host mode.
2.1 Preparations
Before using the USB 2.0 host/USB 3.0 host module, ensure that the following items are
available:
U-boot and Linux kernel released in the SDK
File systems
You can use the local file system YAFFS2, JFFS2, or Cramfs (Jffs2 is recommended)
released in the SDK or mounted to the NFS.
2.2 Procedure
The operation procedure is as follows:
Step 1 Start the board, and load the NFS or the file system YAFFS2, JFFS2, Cramfs.
By default, all drivers related to the USB 2.0 module are compiled in the kernel. Therefore,
you do not need to load the drivers.
Step 2 Insert a USB device such as the USB flash drive, mouse, or keyboard, and then perform
operations on the USB device. For details, see section 2.3 "Operation Instance Related to the
USB Flash Drive."
The drivers related to USB are as follows:
Drivers related to the file system and storage devices
− vfat
− scsi_mod
− sd_mod
− nls_ascii
− nls_iso8859-1
Drivers related to the keyboard
− evdev
− usbhid
Drivers related to the mouse
− mousedev
− usbhid
− evdev
Drivers related to the USB 2.0 module
− ohci-hcd
− ehci-hcd
− usb-storage
− hiusb-hi35xx
Drivers related to the USB 3.0 module
− ohci-hcd
− ehci-hcd
− xhci-hcd
− usb-storage
− hiusb3.0
----End
The USB 3.0 module is not supported by Hi3521D V100 and Hi3520D V400.
4
sd 2:0:0:0: [sda] 15131636 512-byte logical blocks: (7.74 GB/7.21 GiB)
sd 2:0:0:0: [sda] Write Protect is off
sd 2:0:0:0: [sda] Write cache: disabled, read cache: enabled, does not
support DPO or FUA
sda: sda1
sd 2:0:0:0: [sda] Attached SCSI removable disk
If the USB 3.0 host module works properly, the following information is displayed over the
serial port:
usb 4-1: new SuperSpeed USB device number 2 using xhci-hcd
scsi1 : usb-storage 4-1:1.0
usbdev42 -> /dev/usbdev4.2
scsi 1:0:0:0: Direct-Access SanDisk Extreme 0001 PQ: 0 ANSI: 6
sd 1:0:0:0: [sda] 31277232 512-byte logical blocks: (16.0 GB/14.9 GiB)
sd 1:0:0:0: Attached scsi generic sg0 type 0
sd 1:0:0:0: [sda] Write Protect is off
sd 1:0:0:0: [sda] Mode Sense: 33 00 00 08
sd 1:0:0:0: [sda] Write cache: enabled, read cache: enabled, does not
support DPO or FUA
sda: sda1
sd 1:0:0:0: [sda] Attached SCSI disk
udisk4110 -> /dev/sda
udisk4110p1 -> /dev/sda1
Where, sda1 is the first partition of the USB flash drive or the portable drive. If there are
multiple partitions, information such as sda1, sda2, sda3, …, and sdaN is displayed.
In sdXY, X indicates the disk ID, and Y indicates the partition ID. You need to change them as required.
The sdX device node is partitioned by running the partition command such as $ fdisk
/dev/sda.
The sdXY partition is formatted by running the mkdosfs command such as ~ $ mkdosfs
–F 32 /dev/sda1.
The sdXY partition is mounted by running the mount command such as ~ $ mount -t
vfat /dev/sda1 /mnt.
Step 1 Check whether the USB flash drive is partitioned.
Run ls /dev to view system device files. If sdXY is not displayed, the USB flash drive is
not partitioned. In this case, run the ~ $ fdisk /dev/sda command to partition it. For
details, see section 6.1 "Partitioning a Storage Device.", and then go to Step 2.
If sdXY is displayed, the USB flash drive is detected and partitioned. In this case, go to
Step 2.
2.4 Precautions
Note the following when performing the operations related to the USB 2.0 module:
You need to run the mount command, operate a file, and then run the umount command
in sequence each time. This avoids exceptions in the file system.
The drivers of the keyboard and mouse must work with the upper layer. For example,
mouse events are displayed on the graphical user interface (GUI) of the upper layer. You
only need to operate the keyboard by accessing the event node in /dev/input. However,
standard libraries are required for mouse operations.
Mouse application libgpm libraries are provided in Linux. If you need to use the mouse,
these libraries must be compiled. You are recommended to use the standard kernel
interface gpm-1.20.5 that has passed the test.
In addition, a set of test programs (such as mev) is provided in the gpm tool. You can
perform encoding by using the test programs, making the development easier.
3.1 Preparations
Before using the I2C, ensure that the following items are available:
Standard serial advanced technology attachment (SATA) hard disk
U-boot and Linux kernel released in the SDK
File systems
You can use the local file system Yaffs2, UBIFS, JFFS2, or SquashFS released in the
SDK or mounted to the NFS.
3.2 Procedure
Before testing an SATA hard disk, perform the following steps:
Step 1 Start the board, and load the local file system Yaffs2, UBIFS, JFFS2, or SquashFS or mount
the local file system to the NFS.
Step 2 Load the drivers. By default, all drivers related to the SATA module are compiled in the
kernel, you do not need to run the command for loading drivers. For details, see section 3.3
"Operation Instances."
Drivers related to the file system and storage devices
− nls_base
− nls_cp437
− fat
− vfat
− msdos
− nls_iso8859-1
− nls_ascii
− scsi_mod
− sd_mod
Drivers related to hard disks
− libata
− ahci
----End
In the following commands, X indicates the disk ID, and Y indicates the partition ID. You need to
change them as required.
The sdX device node is partitioned by running the partitioning command such as $ fdisk
/dev/sda or $ parted /dev/sda.
The sdXY partition is formatted by running the mkdosfs command such as ~ $ mkdosfs
–F 32 /dev/sda1.
The sdXY partition is mounted by running the mounting command such as $ mount -t
vfat /dev/sda1 /mnt.
Perform the following steps:
Step 1 Check whether the SATA hard disk is partitioned.
Run ls /dev to view the system device files. If partition information sdXY is not displayed,
the SATA hard disk has not been partitioned yet. In this case, partition the SATA hard
disk by following section 6.1 "Partitioning a Storage Device."
If sdXY is displayed, the hard disk is detected and partitioned. In this case, go to step 2.
Step 2 Check whether the SATA hard disk is formatted.
If the SATA hard disk is not formatted, format it by following section 6.2 "Formatting a
Partition."
If it is formatted, go to step 3.
Step 3 Mount the directory by following section 6.3 "Mounting a Directory."
Step 4 Read/Write to the SATA hard disk by following section 6.4 "Reading/Writing to a File."
----End
3.4 Precautions
The Hi35xx SATA drivers support hot plug. After the hot plug, you need to unmount the
nodes mounted to the hard disk. Otherwise, the device nodes of the SATA hard disk change
after the SATA hard disk is reinserted.
4.1 Preparations
Before using the I2C, ensure that the following items are available:
Linux kernel released in the SDK
File systems
You can use the local file system YAFFS2, JFFS2, or SquashFS released in the SDK or
mounted to the NFS.
4.2 Procedure
To use the I2C, perform the following steps:
Step 1 Start the board, and load the local file system YAFFS2, JFFS2, or SquashFS or mount the
local file system to the NFS.
Step 2 Load the kernel. By default, all drivers related to the I2C module are compiled in the kernel.
Therefore, you do not need to load the drivers.
Step 3 Run I2C read and write commands on the console or compile I2C read and write programs in
kernel mode or user mode to read/write to the peripherals mounted on the I2C controller. For
details, see section 4.3 "Operation Instances."
----End
For example, to read the register (address of 0x8) of the sil9024 device mounted on I2C
controller 2, run the following command:
~ $ i2c_read 2 0x72 0x8 0x8 0x1 0x1
i2c_num: I2C controller ID (corresponding to I2C controller in the Hi35xx H.265 Codec Processor
Data Sheet)
device_addr: peripheral address (The Hi35xx supports the 7-bit standard address and 10-bit
extended address.)
reg_addr: start address for reading peripheral registers
end_reg_addr: end address for reading peripheral registers
reg_width: bit width of peripheral registers (The Hi35xx supports 8-bit and 16-bit width.)
data_width: data width of peripherals (The Hi35xx supports 8-bit and 16-bit data width.)
reg_step: incremental step when peripheral registers are read consecutively. The default value is 1,
indicating that two or more registers are read consecutively. This parameter is not used when only
one register is read.
To write to I2C peripherals on the console, run i2c_write:
~ $ i2c_write <i2c_num> <device_addr> <reg_addr> <value> <reg_width>
<data_width>
For example, to write 0xa5 to the register (address of 0x8) of the sil9024 device mounted
on I2C controller 2, run the following command:
~ $ i2c_write 2 0x72 0x8 0xa5 0x1 0x1
i2c_num: I2C controller ID (corresponding to I2C controller in the Hi35xx H.265 Codec Processor
Data Sheet)
device_addr: peripheral address (The I2C controller of the Hi35xx supports the 7-bit standard
address and 10-bit extended address.)
reg_addr: address for writing to peripheral registers
value: data written to peripheral registers
reg_width: bit width of peripherals (The I2C controller of the Hi35xx supports 8-bit and 16-bit
width.)
data_width: data bit width of peripherals (The I2C controller of the Hi35xx supports 8-bit and 16-bit
data width.)
Assume that the new peripheral is mounted on I2C controller 2, the parameter value of i2c_get_adapter
can be set to 2.
Step 2 Associate the I2C controller with the new I2C peripheral. hi_client is obtained, which is a data
structure that describes the client of I2C peripherals.
hi_client = i2c_new_device(i2c_adap, &hi_info);
Step 3 In a non-interrupt context, call the standard read and write functions provided by the I2C core
layer to read/write to peripherals.
ret = i2c_master_send(client, buf, count);
ret = i2c_master_recv(client, buf, count);
In an interrupt context, call the read and write functions provided by the I2C driver layer to
read/write the peripherals.
ret = hi_i2c_master_send(client, buf, count);
ret = hi_i2c_master_recv(client, buf, count);
The client parameter is the hi_client structure obtained in step 2, which is a data structure that
describes the client of I2C peripherals.
The buf parameter is the register or data needs to be read or written.
The count parameter is the length of buf.
The following code instance is a sample program, which only serves as a reference for customers when
they develop kernel-mode I2C peripheral drivers. The code has no actual functions.
For details about kernel-mode I2C peripheral drivers, see tlv320aic31 in
mpp/extdrv/tlv320aic31/tlv320aic31.c of the SDK.
//Each I2C_BOARD_INFO structure represents a supported I2C peripheral. The device name
is hi_test and the device address is 0x72.
I2C_BOARD_INFO("hi_test", 0x72),
};
if (data_byte_num == 2)
client->flags |= I2C_M_16BIT_DATA;
//In a non-interrupt context, call the I2C standard write function provided by the kernel to
perform the write operation.
ret = i2c_master_send(client, buf, count);
//In an interrupt context, call the write function provided by the driver layer to perform the
write operation.
ret = hi_i2c_master_send(client, buf, count);
return ret;
}
//In a non-interrupt context, call the I2C standard read function provided by the kernel to
perform the read operation.
ret = i2c_master_recv(client, buf, count);
//In an interrupt context, call the read function provided by the driver layer to perform the read
operation.
ret = hi_i2c_master_recv(client, buf, count);
return ret;
}
static int hi_dev_init(void)
{
//Call functions at I2C core layer to obtain i2c_adap, which is a structure of the I2C controller.
Assume that the new peripheral is mounted on I2C controller 2.
i2c_adap = i2c_get_adapter(2);
//Associate the I2C controller with the new I2C peripheral by mounting the I2C peripheral on
I2C controller 2. The address is 0x72. In this way, hi_client is formed.
hi_client = i2c_new_device(i2c_adap, &hi_info);
i2c_put_adapter(i2c_adap);
return 0;
}
static void hi_dev_exit(void)
{
i2c_unregister_device(hi_client);
}
----End
Step 2 Run the following ioctl commands to configure the peripheral address, bit width of peripheral
registers, and data bit width of peripherals.
ret = ioctl(fd, I2C_SLAVE_FORCE, device_addr);
ioctl(fd, I2C_16BIT_REG, 0);
ioctl(fd, I2C_16BIT_DATA, 0);
For the register bit width and data bit width, when the third parameter of ioctl is set to 0, the bit width is
8 bits. When the third parameter of ioctl is set to 1, the bit width is 16 bits.
Step 3 Call the read and write functions to read/write the data.
read(fd, recvbuf, reg_width);
write(fd, buf, (reg_width + data_width));
The following code instance is a sample program, which only serves as a reference for customers when
they develop user-mode I2C peripheral drivers. The code has no actual functions.
For details about user-mode I2C peripheral drivers, see i2c_ops in osdrv/tools/board/reg-tools-
1.0.0/source/tools/i2c_ops.c of the SDK.
unsigned int reg_width = 1;
unsigned int data_width = 1;
unsigned int reg_step = 1;
int ret;
unsigned int i2c_num, device_addr, reg_addr, reg_addr_end;
char data;
char recvbuf[4];
int cur_addr;
fd = open("/dev/i2c-0", O_RDWR);
if (fd<0)
{
printf("Open i2c dev error!\n");
return -1;
}
if (reg_width == 2)
ret = ioctl(fd, I2C_16BIT_REG, 1);
else
ret = ioctl(fd, I2C_16BIT_REG, 0);
if (ret < 0) {
printf("CMD_SET_REG_WIDTH error!\n");
close(fd);
return -1;
}
if (data_width == 2)
ret = ioctl(fd, I2C_16BIT_DATA, 1);
else
ret = ioctl(fd, I2C_16BIT_DATA, 0);
if (ret < 0) {
printf("CMD_SET_DATA_WIDTH error!\n");
close(fd);
return -1;
}
} else
recvbuf[0] = cur_addr & 0xff;
if (data_width == 2) {
data = recvbuf[0] | (recvbuf[1] << 8);
} else
data = recvbuf[0];
close(fd);
return 0;
}
fd = open("/dev/i2c-0", O_RDWR);
if(fd < 0)
{
printf("Open i2c dev error!\n");
return -1;
}
if (reg_width == 2)
ret = ioctl(fd, I2C_16BIT_REG, 1);
else
ret = ioctl(fd, I2C_16BIT_REG, 0);
if (data_width == 2)
if (reg_width == 2) {
buf[index] = reg_addr & 0xff;
index++;
buf[index] = (reg_addr >> 8) & 0xff;
index++;
} else {
buf[index] = reg_addr & 0xff;
index++;
}
if (data_width == 2) {
buf[index] = reg_value & 0xff;
index++;
buf[index] = (reg_value >> 8) & 0xff;
index++;
} else {
buf[index] = reg_value & 0xff;
index++;
}
close(fd);
return 0;
}
----End
5.1 Preparations
Before using the serial peripheral interface (SPI), ensure that the following items are available:
Linux kernel released in the SDK
File systems
You can use the local file system YAFFS2, JFFS2, or SquashFS released in the SDK or
mounted to the NFS.
5.2 Procedure
To use the SPI, perform the following steps:
Step 1 Start the board, and load the local file system YAFFS2, JFFS2, or SquashFS or mount the
local file system to the NFS.
Step 2 Load the kernel. By default, all drivers related to the SPI module are compiled in the kernel.
Therefore, you do not need to load the drivers.
Step 3 Run SPI read and write commands on the console or compile SPI read and write programs in
kernel mode or user mode to read/write to the peripherals mounted on one of the chip selects
(CSs) of the SPI controller. For details, see section 5.3 "Operation Instances."
----End
[num_reg] can be omitted and its default value is 1 (indicating reading one register).
[dev_width], [reg_width], and [data_width] can be omitted and their default values are 1
(indicating one byte).
For example, to read the register (address of 0x0) of the device (address of 0x2) mounted on
CS 0 of the SPI controller 0, run the following command:
~ $ ssp_read 0x0 0x0 0x2 0x0 0x10 0x1 0x1 0x1
spi_num: SPI controller ID (corresponding to SPI controller 0 and SPI controller 1 in the Hi35xx
H.265 Codec Processor Data Sheet)
csn: CS ID
dev_addr: peripheral address
reg_addr: address of the first peripheral register to be read among multiple peripheral registers
whose addresses are consecutive
num_reg: number of peripheral registers to be read
dev_width: address bit width of peripherals (8/16 bits)
reg_width: address bit width of peripheral registers (8/16 bits)
data_width: data bit width of peripherals (8/16 bits)
To write to SPI peripherals on the console, run spi_write:
~ $ ssp_write <spi_num> <csn> <dev_addr> <reg_addr> <data> [dev_width]
[reg_width] [data_width]
[dev_width], [reg_width], and [data_width] can be omitted and their default values are
1 (indicating one byte).
For example, to write 0x65 to the register (address of 0x0) of the device (address of 0x2)
mounted on CS 0 of the SPI controller 0, run the following command:
~ $ ssp_write 0x0 0x0 0x2 0x0 0x65 0x1 0x1 0x1
spi_num: SPI controller ID (corresponding to SPI controller 0 and SPI controller 1 in the Hi35xx
H.265 Codec Processor Data Sheet)
csn: CS ID
dev_addr: peripheral address
reg_addr: peripheral register address
data: data written to peripheral registers
dev_width: address bit width of peripherals (8/16 bits)
reg_width: address bit width of peripheral registers (8/16 bits)
data_width: data bit width of peripherals (8/16 bits)
The SPI read and write commands can be used only to read and write to sensors.
bus_num is the ID of the SPI controller connected to the SPI peripherals to be read or written to.
hi_master is a pointer to the spi_master structure that describes the SPI controller.
Step 2 Call functions at the SPI core layer by name of each SPI CS at the core layer to obtain a
structure that describes an SPI peripheral mounted to one CS of an SPI controller.
sprintf(spi_name, "%s.%u", dev_name(&hi_master->dev),csn);
d = bus_find_device_by_name(&spi_bus_type, NULL, spi_name);
hi_spi = to_spi_device(d);
spi_bus_type is a pointer to the bus_type structure that describes the SPI bus and is defined at the
core layer.
hi_spi is a pointer to the spi_device structure that describes SPI peripherals.
Step 3 Configure members in the spi_transfer structure, call functions at the SPI core layer, and add
spi_transfer to the queue of spi_message.
spi_message_init(&m);
spi_message_add_tail(&t, &m);
Parameter t is a pointer to the spi_transfer structure that describes a transferred message frame.
Parameter m is a pointer to the spi_message structure that describes a transferred message queue.
Step 4 Call the standard read and write functions provided by the SPI core layer to read/write to
peripherals.
status = spi_async(spi, &m);
status = spi_sync(spi, &m);
Parameter spi is a pointer to the spi_device structure that describes SPI peripherals.
The spi_async function is used to perform asynchronous SPI read and write operations.
The spi_sync function is used to perform synchronous SPI read and write operations.
The following code instance is a sample program for asynchronously reading and writing to the SPI
peripheral imx185. The code only serves as a reference for customers when they develop kernel-
mode SPI peripheral drivers and has no actual functions.
For details about kernel-mode SPI peripheral drivers, see sensor_spi in
mpp/extdrv/sensor_spi/sensor_spi.c of the SDK.
//Module parameters. The transferred SPI controller ID is the SPI bus ID and the SPI CS ID.
static unsigned bus_num = 0;
static unsigned csn = 0;
module_param(bus_num, uint, S_IRUGO);
MODULE_PARM_DESC(bus_num, "spi bus number");
module_param(csn, uint, S_IRUGO);
MODULE_PARM_DESC(csn, "chip select number");
//After the transfer of the message queue is complete, the state member of spi_message
is set to null at the core layer.
if (m.state != NULL) {
spin_unlock_irqrestore(&master->queue_lock, flags);
return -EFAULT;
}
spin_unlock_irqrestore(&master->queue_lock, flags);
t.tx_buf = buf;
t.rx_buf = buf;
t.len = 3;
t.cs_change = 1;
t.bits_per_word = 8;
t.speed_hz = 2000000;
When the function is returned after calling, the SPI read and write operations may not be complete
because the operations are asynchronous. Therefore, the address space pointed by the transferred
parameters must be a local static variable or a global variable to prevent the address space transferred to
spi_async from being released when the function is returned.
status = spi_async(spi, &m);
return status;
}
//After the transfer of the message queue is complete, the state member of spi_message
is set to null at the core layer.
if (m.state != NULL) {
spin_unlock_irqrestore(&master->queue_lock, flags);
return -EFAULT;
}
spin_unlock_irqrestore(&master->queue_lock, flags);
t.tx_buf = buf;
t.rx_buf = buf;
t.len = 3;
t.cs_change = 1;
t.bits_per_word = 8;
t.speed_hz = 2000000;
When the function is returned after calling, the SPI read and write operations may not be complete
because the operations are asynchronous. Therefore, the address space pointed by the transferred
parameters must be a local static variable or a global variable to prevent the address space transferred to
spi_async from being released when the function is returned.
status = spi_async(spi, &m);
*data = buf[2];
return status;
}
//External reference declaration for the spi_bus_type structure that describes the SPI bus and
is defined at the SPI core layer.
extern struct bus_type spi bus_type;
//The structure that describes the SPI controller is obtained by using the SPI controller ID.
hi_master = spi_busnum_to_master(bus_num);
if (hi_master) {
spi_name = kzalloc(strlen(dev_name(&hi_master->dev)) + 10 ,
GFP_KERNEL);
if (!spi_name) {
status = -ENOMEM;
goto end0;
}
//The pointer to the device member of spi_device is obtained by name of each CS at the SPI
core layer.
d = bus_find_device_by_name(&spi_bus_type, NULL, spi_name);
if (d == NULL) {
status = -ENXIO;
goto end1;
}
//The structure that describes SPI peripherals is obtained by using the pointer to the device
member of spi_device.
hi_spi = to_spi_device(d);
if(hi_spi == NULL) {
status = -ENXIO;
goto end2;
}
} else {
status = -ENXIO;
goto end0;
}
status = 0;
end2:
put_device(d);
end1:
kfree(spi_name);
end0:
return status;
}
----End
SPI_MODE_3 indicates the mode in which the SPI clock and phase are both 1.
SPI_LSB_FIRST indicates that the format of each data segment is big endian during the SPI
transfer.
For details about the clock, phase, endian mode of the SPI, see the Hi35xx H.265 Codec
Processor Data Sheet.
Step 3 Use ioctl to read and write data.
ret = ioctl(fd, SPI_IOC_MESSAGE(1), mesg);
mesg indicates the start address of the spi_ioc structure array that transfers a message frame.
SPI_IOC_MESSAGE(n) indicates commands used to read and write n message frames in full-
duplex mode.
The following code instance is a sample program for synchronously reading and writing to IMX185
(an SPI peripheral). The code only serves as a reference for customers when they develop the
operation program for user-mode SPI peripherals and has no actual functions.
For details about user-mode SPI peripheral drivers, see ssp_rw in osdrv/tools/board/reg-tools-
1.0.0/source/tools/ssp_rw.c of the SDK.
int sensor_write_register(unsigned int addr, unsigned char data)
{
int fd = -1;
int ret;
unsigned int value;
struct spi_ioc_transfer mesg[1];
unsigned char tx_buf[4];
unsigned char rx_buf[4];
char file_name[] = "/dev/spidev0.0";
fd = open(file_name, 0);
if (fd < 0) {
return -1;
}
fd = open(file_name, 0);
if (fd < 0) {
return -1;
}
----End
6 Appendix
Press Enter and enter the m command. Continue with the operations based on the help
information.
The device node depends on the type of the actual storage device. For details, see the
operation instances in preceding chapters.
The preceding information indicates that the device is not partitioned. In this case, you need to
partition the device by following section 6.1.2 "Creating Partitions for a Storage Device.", and
save the partition information by following section 6.1.3 "Saving the Partition Information."
Run the l command to view the details of all the partitions of the fdisk.
Changed system type of partition 1 to b (Win95 FAT32)
The name of a partition depends on the type of the actual storage device. For details, see
the operation instances in preceding chapters.
If no error information is displayed on the console, a partition is formatted successfully:
~ $
The name of a partition depends on the type of the actual storage device. For details, see the
operation instances in the preceding chapters.
To write to a file, copy the test.txt file in the current directory to the mnt directory of a
storage device by running the following command:
~ $ cp ./test.txt /mnt