Linux Common driver modifications

Source: Internet
Author: User

=============================== Description ===============================
This article takes A5 as an example, to give 8 kinds of our company commonly used interface of the extremely streamlined driver, only should refer to, when using, please self-correcting logic and drive frame
The contents are as follows:
1. Gpio
2. External interrupt
3. LEDs
4. UART
5, I²c
6. SPI
7, PCK
8, Gadget

=============================== Gpio ===============================
The GPIO does not require additional configuration in the device tree, and the default mode of operation for all pins at A5 startup is Gpio. The application-layer interface for GPIO is/sys/class/gpio.

1.gpio structure of the application layer interface
/sys/class/gpio
┣export# Application Pin Interface
┣unexport# canceling the request pin interface
┣pioa15# Single pin device
┃┣direction# Output/Input control
┃┣value# level
┃┗ ...
┗ ...

2. How to use
1) Set input
Set the B22 pin as input and read the values, for example:
Cd/sys/class/gpio
echo > export# gpioa No. 0 # bank,54 = b*32 + 22
CD pioB22
echo in > direction# string "in"
Cat value# characters ' 0 ' or ' 1 '
If it is used in an application, then cat can be replaced with the Read function, and Echo can replace the Write function.
2) Set the output
Set the C1 pin to output and set the level:
Cd/sys/class/gpio
echo > Export
CD pioC1
echo Out > direction
Echo 1 > value
echo 0 > value

=========================== external Interrupt & key ===========================
External interrupts are implemented in two ways, pure Drive mode and key mode

1. Pure Drive Mode
If you want to add a key driver named Btn_test, print "User button pressed!\n" When the button that connects pioE0 is pressed
1) Device tree modification, add the following nodes
/ {
AHB {
APB {
[Email protected] {
Board {
/* Declare the PIN PIN you want to use */
Pinctrl_btn_test_gpio:btn_test_gpio {
Atmel,pins =
<at91_pioe 0 At91_periph_gpio at91_pinctrl_pull_up>;
};
};
};
};
};
btn_test {
/* Drive Match */
compatible = "Btn_test";
Status = "Okay";
/* Declare the PIN PIN you need to use */
Pinctrl-names = "Default";
pinctrl-0 = <&pinctrl_btn_test_gpio>;
};
};

2) configuration of the driver, only the implementation of the probe function is given here
#define GPIO_TO_PIN (port, PIN) ((port) * + PIN)
#define Btn_pin (Gpio_to_pin (4, 0))

Interrupt function ======================================================

static irqreturn_t btntest_interrupt (int irq, void *dev_id)
{
/* Print information */
PRINTK (kern_info "User button pressed!\n");
/* return value: Interrupt normal exit */
Return Irq_retval (irq_handled);
}

Probe & Remove ==========================================================

static int btntest_probe (struct platform_device *pdev)
{
struct Pinctrl *pinctrl;
int ret = 0;
/* Initialize PIN PIN, here you need to rely on the Pinctrl-names property of the device tree, the pinctrl-0 property */
Pinctrl = Devm_pinctrl_get_select_default (&pdev->dev);
....
/* Request an interrupt number and configure the interrupt trigger condition */
ret = REQUEST_IRQ (GPIO_TO_IRQ (Btn_pin), Btntest_interrupt,
irq_type_edge_falling, "User key", NULL);

return ret;
}

=============================== LEDs ===============================
The LEDs drive is a variant of the Gpio driver

1. Application Layer Interface
/sys/class/leds
┣led_1# Single LED device
┃┣brightness# brightness control, can be ' 0 ' or ' 1 '
┃┗ ...
┗ ...

1) Light LED light
Echo 1 >/sys/class/leds/led_1/brightness

2. Drive implementation
LEDs are very simple to drive, it is a variant of the GPIO, only need to modify the device tree can be achieved,
Add the following nodes:
/ {
LEDs {
compatible = "Gpio-leds";

/* LEDs Device Object */
led_1 {
label = "Led_1";/* The name of the application-tier interface */
Gpios = <&pioa gpio_active_high>;/* ACTIVE entry is high, then 1 indicates a higher level */
};

......
};
};

=============================== UART ===============================
UART is the most common interface in Linux, the driver is very perfect, generally in the application layer operation can

Cases:
Open serial port, set baud rate 115200, no check bit no stop bit
int Openuart (char *path)
{
int serial = 0;
struct Termios options;
Bzero (&options, sizeof (options));

Routine operation of opening the serial port
serial = open (path, O_RDWR | O_nonblock);
Tcflush (serial, Tcioflush);
Options.c_cflag &= ~csize;
Options.c_cflag |= (clocal | Cread);

Configuration options---can be modified casually
Cfsetispeed (&options, B115200);//Reception rate
Cfsetospeed (&options, B115200);//Transmit Rate
Options.c_cflag |= cs8;//8 data bits
Options.c_cflag &= ~parenb;//No calibration
Options.c_cflag &= ~cstopb;//1 Stop bit

Eliminate all special software and hardware flow control
Options.c_lflag &= ~ (Icanon | ECHO | Echoe | Isig | Crtscts);
Options.c_oflag &= ~ (opost);

Setting the time-out range
Options.c_cc[vtime] = 150;
Options.c_cc[vmin] = 0;

Write configuration
Tcsetattr (Serial, Tcsanow, &options);
Tcflush (serial, Tcioflush);

return serial;
}

Read and write directly using read and write

================================ I²c ================================
Off the net ... Ready to be perfected


================================ SPI ================================
The Linux source has a very good SPI interface driver--spidev, which is the SPI standard interface specified by our company

1. Modify the device tree
The SPI statement in Sama5d3.dtsi is as follows:
SPI1: [email protected] {
#address-cells = <1>;
#size-cells = <0>;
compatible = "ATMEL,AT91RM9200-SPI";
Reg = <0xf8008000 0x100>;
interrupts = <25 Irq_type_level_high 3>;
DMAs = <&dma1 2 at91_dma_cfg_per_id ();
<&DMA1 2 at91_dma_cfg_per_id (>;)
Dma-names = "TX", "RX";
Pinctrl-names = "Default";
pinctrl-0 = <&pinctrl_spi1>;
Clocks = <&spi1_clk>;
Clock-names = "SPI_CLK";
Status = "Disabled";
};

Then our own DTS file after inheriting Sama5d3.dtsi this file, we might as well make some minor adjustments:
SPI1: [email protected] {
DMAs = <0>, <0>;/* disable DMA */
pinctrl-0 = <&pinctrl_spi1 &pinctrl_spi1_cs3>;/* Increase the re-use of CS feet */

[Email protected] {
compatible = "ROHM,DH2228FV";/* Important compatible property, which is keyed out from the SPIDEV.C */
Spi-max-frequency = <4000000>;/* rated speed, varies by device */
reg = <3>;/* CS3 pin */
spi-cpha;/* Cpha and Cpol properties, optional, but this choice is very important, be sure to match the device! Failure to do so will result in a timing exception */
spi-cpol;/* about Cpha and Cpol configuration, please Niang "SPI four modes" */
};

Status = "Okay";
};

2. Kernel adjustment
Menuconfig the User mode SPI device driver support must be selected, this option is directly associated with SPIDEV.C
selected, the device tree changed, burn write system, in/dev inside will appear a Spidev device

3. Use
We operate on this interface at the application level, and since we have enough information in the device tree, this example can be simpler, but it still gives the complete process
Examples are as follows:

1) Turn on SPI
int Openspi (char *path)
{
int spidev = 0;
unsigned char mode = spi_mode_3;//Set operating modes

Turn on the SPI and configure
Spidev = open (path, O_RDWR);
IOCTL (Spidev, Spi_ioc_rd_mode, &mode);//Allow reading
IOCTL (Spidev, Spi_ioc_wr_mode, &mode);//Allow Write
IOCTL (Spidev, Spi_ioc_wr_max_speed_hz, 4000000);//Set rated rate

return Spidev;
}

2) Read and write data
The SPI typically faces a situation where an address is sent before it is read;

Example:
int Spi_readreg (unsigned char reg_addr, char *buff, int reg_size)
{
Read and write split into two-section buff
struct Spi_ioc_transfer spi_buffer[2];
int ret = 0;

Bzero (Spi_buffer, sizeof (Spi_buffer));

The first buffer structure has a length of 1, write-only, address
Spi_buffer[0].bits_per_word = 8;
Spi_buffer[0].len = 1;
Spi_buffer[0].tx_buf = &reg_addr;
Spi_buffer[0].cs_change = 0;

The second buffer structure is the length of the readout data, read-only, and the buff is passed in to store the return value.
Spi_buffer[1].bits_per_word = 8;
Spi_buffer[1].len = size;
Spi_buffer[1].rx_buf = buff;
Spi_buffer[1].cs_change = 0;

Execute the transfer command, and the result will be stored in the buff.
RET = IOCTL (Spidev, Spi_ioc_message (2), spi_buffer);
return ret;
}

Can actually read and write at the same time, that is, a structure can handle a lot of things, see how the program wrote

================================ PCK ================================
Sama5d3 inside PCK refers to the clock output, can be used in a variety of occasions, to provide the device clock signal

1) Device Tree
In fact, in general and external interruption is the same, but the configuration of the re-use of the PIN is different, note at91_periph_b:

Pinctrl_pck_gpio:pck_gpio {
Atmel,pins = <at91_piod At91_periph_b at91_pinctrl_pull_up>;
};

2) Drive
Enable PCK, if you want the most concise, then directly in the probe inside the frequency of the fixed to die (probably also won't hand to change frequency?) Very dangerous, oh ~)

On the pin output clock, example:
int Probe (struct platform_device *dev)
{
int clk_src = 0;
int clk_rate = 0;
struct CLK *mclk = NULL;

...//omit the process of getting pins

First, get an internal clock called Main, which is integrated within the SAMA5D3 chip
CLK_SRC = Clk_get (NULL, "main");
Clk_rate = Clk_get_rate (CLK_SRC);

Configuring the Pck0 Pin-connected clock controller
Clk_get (NULL, "pck0");//Get Pck0 Clock
Clk_set_parent (MCLK, CLK_SRC);//Use main as the input source for pck0, if hardware is supported, otherwise it will fail
Clk_set_rate (MCLK, mclk_rate);//try to modulate the rate of pck0 to the nearest value to Mclk_rate

Return clk_prepare_enable (MCLK);//Turn on the clock
}

============================== Gadget ==============================

Gadget is a USB operating mode, you can make the device into a USB stick, or serial

Mainly some configuration work, do not need to write code

1. Kernel Menuconfig

1) go to Device Drivers USB support, select
USB Modem (CDC ACM) support
USB Mass Storage Support
USB Serial Converter Support
[*] USB Generic Serial Driver
USB Gadget Support
Mass Storage Gadget
Serial Gadget (with CDC ACM and CDC OBEX support)
CDC Composite Device (ACM and mass storage) (This is the point, to choose m)
Multifunction Composite Gadget

2) Move all Drivers/usb down to the Development Board and Modprobe

3) The last modprobe G_acm_ms.ko a little different:
Insmod G_acm_ms.ko file=/mnt/static.img luns=1 ro=0 stall=0 removable=1 iserialnumber=3000111 iProduct=zhdgnss Imanufacturer=zhd_survey

Linux Common driver modifications

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.