1: Configure PIN for SPI function
At the end of the board-mx6q_sabresd.h, the copy is redefined
(To add SPI2 as an example)
[CPP]View Plaincopy
- <span style="FONT-SIZE:18PX;" > MX6Q_PAD_EIM_CS0__ECSPI2_SCLK,
- Mx6q_pad_eim_cs1__ecspi2_mosi,
- Mx6q_pad_eim_oe__ecspi2_miso,
- MX6Q_PAD_CSI0_DAT11__ECSPI2_SS0,
- </span>
After that, the board-level file BOARD-MX6Q_SABRESD.C will have related functions for the unified initialization of the PIN.
Complete the operation of the Register configuration.
[CPP]View Plaincopy
- <span style="FONT-SIZE:18PX;" > mxc_iomux_v3_setup_multiple_pads (mx6q_sabresd_pads,
- Array_size (mx6q_sabresd_pads));
- Mxc_iomux_v3_setup_multiple_pads (mx6q_sabresd_cstm_tq_pads,\
- Array_size (mx6q_sabresd_cstm_tq_pads));</span>
2: Add the following code in the board-level file BOARD-MX6Q_SABRESD.C
Will match the driver source in the Driver/spi/spidev.c file
2.1 Completing the SPI Master Registration
SPI2 Blade pin-Select macro definition:
[CPP]View Plaincopy
- <span style="FONT-SIZE:14PX;" > #define SABRESD_ECSPI2_CS0 IMX_GPIO_NR (5) </span>
Adding related structures
[CPP]View Plaincopy
- <span style="FONT-SIZE:14PX;" >static int mx6q_marsboard_spi1_cs[] = {
- Sabresd_ecspi2_cs0,
- };
- </span>
[CPP]View Plaincopy
- <span style="FONT-SIZE:14PX;" >static const struct Spi_imx_master mx6q_sabresd_spi2_data __initconst = {
- . Chipselect = Mx6q_marsboard_spi2_cs,
- . Num_chipselect = Array_size (Mx6q_marsboard_spi1_cs),
- };
- </span>
2.2 Matching SPI2 driver files on the SPI bus
The MX6Q platform has 2 SPI resources and 0/1, of which the Bus_num is the bus selection of the mounted drive.
[CPP]View Plaincopy
- <span style="FONT-SIZE:18PX;" ><span style="FONT-SIZE:14PX;" >static struct mtd_partition imx6_sabrelite_spi_nor_partitions[] = {
- {
- . Name = "Bootloader",
- . Offset = 0,
- . Size = 0x00100000,
- },
- {
- . Name = "Kernel",
- . offset = Mtdpart_ofs_append,
- . Size = Mtdpart_siz_full,
- },
- };
- Static struct Flash_platform_data imx6_sabrelite__spi_flash_data = {
- . Name = "Spidev",//matching principle.
- . Parts = Imx6_sabrelite_spi_nor_partitions,
- . Nr_parts = Array_size (imx6_sabrelite_spi_nor_partitions),
- . Type = "sst25vf016b",
- };
- Static struct Spi_board_info imx6_sabrelite_spi_nor_device[] __initdata = {
- {
- . Modalias = "Spidev",
- . max_speed_hz = 20000000, /* max SPI Clock (SCK) speed in Hz */
- . Bus_num = 1, //device Mount number on the SPI bus
- . Chip_select = 0,
- . Platform_data = &imx6_sabrelite__spi_flash_data,
- },
- };
- Spi_register_board_info (Imx6_sabrelite_spi_nor_device,
- Array_size (Imx6_sabrelite_spi_nor_device));
- Imx6q_add_ecspi (0, &mx6q_sabrelite_spi2_data);
- </span>
- </span>
3: Kernel configuration
View Kconfig in the spidev.c file directory and makefile Learn how to add kernel drivers
Select the Blue section option to add the spidev.c file to the kernel.
4: View the Development Board/sys/bus/spi/drivers/spidev directory
Generating device files in/dev/dev/spidev1.0
5: Test the interface using the SPI test program in the Freescale official BSP Package
[CPP]View Plaincopy
- <span style="FONT-SIZE:12PX;" >/*
- * SPI Testing utility (using Spidev driver)
- *
- * Copyright (c) MontaVista Software, Inc.
- * Copyright (c) Anton Vorontsov <[email protected]>
- *
- * This program was free software; You can redistribute it and/or modify
- * It under the terms of the GNU general public License as published by
- * The free software Foundation; Either version 2 of the License.
- *
- * Cross-compile with Cross-gcc-i/path/to/cross-kernel/include
- */
- #include <stdint.h>
- #include <unistd.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <getopt.h>
- #include <fcntl.h>
- #include <sys/ioctl.h>
- #include <linux/types.h>
- #include <linux/spi/spidev.h>
- #define ARRAY_SIZE (a) (sizeof (a)/sizeof ((a) [0]))
- static void Pabort (const char *s)
- {
- Perror (s);
- Abort ();
- }
- Static Const Char *device = "/dev/spidev1.0";
- static uint8_t mode;
- static uint8_t bits = 8;
- static uint32_t speed = 500000;
- static uint16_t delay;
- static void transfer (int fd)
- {
- int ret;
- uint8_t tx[] = {
- 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
- 0x40, 0x00, 0x00, 0x00, 0x00, 0x95,
- 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
- 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
- 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
- 0xDE, 0xAD, 0xBE, 0xEF, 0xBA, 0xAD,
- 0xF0, 0x0D,
- };
- uint8_t Rx[array_size (tx)] = {0,};
- struct Spi_ioc_transfer tr = {
- . Tx_buf = (unsigned long) TX,
- . Rx_buf = (unsigned long) Rx,
- . Len = Array_size (TX),
- . Delay_usecs = delay,
- . Speed_hz = Speed,
- . Bits_per_word = Bits,
- };
- RET = IOCTL (FD, Spi_ioc_message (1), &TR);
- if (Ret < 1)
- Pabort ("can ' t send SPI message");
- For (ret = 0; ret < array_size (TX); ret++) {
- if (! ( Ret% 6))
- Puts ("");
- printf ("%.2x", Rx[ret]);
- }
- Puts ("");
- }
- int main (int argc, char *argv[])
- {
- int ret = 0;
- int fd;
- //parse_opts (argc, argv);/* For what, unknow*/
- FD = open (device, O_RDWR);
- if (FD < 0)
- Pabort ("can ' t open device");
- /*
- * SPI mode
- */
- RET = IOCTL (FD, Spi_ioc_wr_mode, &mode);
- if (ret = =-1)
- Pabort ("can ' t set SPI mode");
- RET = IOCTL (FD, Spi_ioc_rd_mode, &mode);
- if (ret = =-1)
- Pabort ("can ' t get SPI mode");
- /*
- * Bits per Word
- */
- RET = IOCTL (FD, Spi_ioc_wr_bits_per_word, &bits);
- if (ret = =-1)
- Pabort ("can ' t set bits per word");
- RET = IOCTL (FD, Spi_ioc_rd_bits_per_word, &bits);
- if (ret = =-1)
- Pabort ("can ' t get bits per word");
- /*
- * Max speed Hz
- */
- RET = IOCTL (FD, Spi_ioc_wr_max_speed_hz, &speed);
- if (ret = =-1)
- Pabort ("can ' t set max speed Hz");
- RET = IOCTL (FD, Spi_ioc_rd_max_speed_hz, &speed);
- if (ret = =-1)
- Pabort ("can ' t get max speed Hz");
- printf ("SPI mode:%d\n", mode);
- printf ("bits per word:%d\n", bits);
- printf ("Max speed:%d Hz (%d KHz) \ n", speed, speed/1000);
- Transfer (FD);
- Close (FD);
- return ret;
- }
- </span>
Execution of the application, you can see the timing mode (SPI 4 timing mode No. 0), clock frequency and other parameters.
Adding SPI Resources on the Freescale Mx6q platform