Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

Info

This is an add-on product that installs on top of the Linux BSP for the NXP i.MX RT10XX EVK board. It must be purchased separately from the Linux BSP product.

1. Overview

This document describes how to support for the LPSPI controller of the i.MX RT10XX processor in the Linux BSP.

2. Requirements

2.1. Detailed Requirements

The following are the requirements for this project:

  1. Provide a Linux demo project combining all the requirements in this project.

  2. Provide support for the i.MX RT1050 LPSPI controller in Linux.

  3. Provide support for the raw access to the SPI device from user space.

2.2. Detailed Non-Requirements

The following are the non-requirements for this project that may otherwise not be obvious:

  • None

3. Design

3.1. Detailed Design

3.1.1.
Anchor
Design-Demo-Project
Design-Demo-Project
Design: Demo Project

This project will enable the required functionality in the Linux configuration ("embedded project") called rootfs, which resides in a projects/rootfs directory, relative to the top of the Linux i.MX RT1050 or i.MX RT1060 installation.

3.1.2.
Anchor
Design-Linux-LPSPI-Device-Driver
Design-Linux-LPSPI-Device-Driver
Design: Linux LPSPI Device Driver

In the i.MXRT1050/1060 SoC, the LPSPI controller is compatible with the same controller of some other SoCs from the i.MX family, so the existing spi-fsl-lpspi.c driver in the Linux sources, which was initially added to support SPI in the i.MX7ULP SoC, will be used to support the LPSPI controller of the i.MXRT1050/1060 SoC.

...

Due to the fact that the GPIO_SD_B0_00, GPIO_SD_B0_01, GPIO_SD_B0_02 and GPIO_SD_B0_03 PADs are used for the SD card controller, the changes for LPSPI1 will be provided under the #if defined(SPI_FLASH_ON_LPSPI1) condition. If the SPI_FLASH_ON_LPSPI1 is defined in DTS, the SD-card controller will be disabled.

3.1.3.
Anchor
Design-Raw-SPI-Device-Access
Design-Raw-SPI-Device-Access
Design: Raw SPI Device Access

Linux provides a special spidev device driver to allow raw accesses to SPI devices from the user space: https://www.kernel.org/doc/Documentation/spi/spidev.

...

Code Block
/*                                                                                                                                                                                                                                                                                 
 * Sample application that makes use of the SPIDEV interface                                                                                                                                                                                                                       
 * to access an SPI slave device. Specifically, this sample                                                                                                                                                                                                                        
 * reads a Device ID of a JEDEC-compliant SPI Flash device.                                                                                                                                                                                                                        
 */                                                                                                                                                                                                                                                                                
                                                                                                                                                                                                                                                                                   
#include <stdio.h>                                                                                                                                                                                                                                                                 
#include <sys/types.h>                                                                                                                                                                                                                                                             
#include <sys/stat.h>                                                                                                                                                                                                                                                              
#include <fcntl.h>                                                                                                                                                                                                                                                                 
#include <unistd.h>                                                                                                                                                                                                                                                                
#include <sys/ioctl.h>                                                                                                                                                                                                                                                             
#include <linux/types.h>                                                                                                                                                                                                                                                           
#include <linux/spi/spidev.h>                                                                                                                                                                                                                                                      
#include <stdint.h>                                                                                                                                                                                                                                                                
#include <stdio.h>                                                                                                                                                                                                                                                                 
#include <string.h>                                                                                                                                                                                                                                                                
#include <errno.h>                                                                                                                                                                                                                                                                 
                                                                                                                                                                                                                                                                                   
int main(int argc, char **argv)                                                                                                                                                                                                                                                    
{                                                                                                                                                                                                                                                                                  
        char *name;                                                                                                                                                                                                                                                                
        int fd;                                                                                                                                                                                                                                                                    
        struct spi_ioc_transfer xfer[2];                                                                                                                                                                                                                                           
        unsigned char buf[32], *bp;                                                                                                                                                                                                                                                
        int len, status;                                                                                                                                                                                                                                                           
                                                                                                                                                                                                                                                                                   
        name = argv[1];                                                                                                                                                                                                                                                            
        fd = open(name, O_RDWR);                                                                                                                                                                                                                                                   
        if (fd < 0) {                                                                                                                                                                                                                                                              
                perror("open");                                                                                                                                                                                                                                                    
                return 1;                                                                                                                                                                                                                                                          
        }                                                                                                                                                                                                                                                                          
                                                                                                                                                                                                                                                                                   
        memset(xfer, 0, sizeof xfer);                                                                                                                                                                                                                                              
        memset(buf, 0, sizeof buf);                                                                                                                                                                                                                                                
        len = sizeof buf;                                                                                                                                                                                                                                                          
                                                                                                                                                                                                                                                                                   
        /*                                                                                                                                                                                                                                                                         
         * Send a GetID command                                                                                                                                                                                                                                                    
         */                                                                                                                                                                                                                                                                        
        buf[0] = 0x9f;                                                                                                                                                                                                                                                             
        len = 6;                                                                                                                                                                                                                                                                   
        xfer[0].tx_buf = (unsigned long)buf;                                                                                                                                                                                                                                       
        xfer[0].len = 1;                                                                                                                                                                                                                                                           
                                                                                                                                                                                                                                                                                   
        xfer[1].rx_buf = (unsigned long) buf;                                                                                                                                                                                                                                      
        xfer[1].len = 6;                                                                                                                                                                                                                                                           
                                                                                                                                                                                                                                                                                   
        status = ioctl(fd, SPI_IOC_MESSAGE(2), xfer);                                                                                                                                                                                                                              
        if (status < 0) {                                                                                                                                                                                                                                                          
                perror("SPI_IOC_MESSAGE");                                                                                                                                                                                                                                         
                return -1;                                                                                                                                                                                                                                                         
        }                                                                                                                                                                                                                                                                          
                                                                                                                                                                                                                                                                                   
        printf("response(%d): ", status);                                                                                                                                                                                                                                          
        for (bp = buf; len; len--)                                                                                                                                                                                                                                                 
                printf("%02x ", *bp++);                                                                                                                                                                                                                                            
        printf("\n");                                                                                                                                                                                                                                                              
                                                                                                                                                                                                                                                                                   
        return 0;                                                                                                                                                                                                                                                                  
}                                                                                                                                                                                                                                                                                  

3.2. Effect on Related Products

This project makes the following updates in the related products:

  • None

3.3. Changes to User Documentation

This project updates the following user documents:

  • None

3.4. Alternative Design

The following alternative design approaches were considered by this project but then discarded for some reason:

  • None

4. Test Plan

4.1. Secure Download Area

The downloadable materials developed by this project are available from a secure Web page on the Emcraft Systems web site. Specifically, proceed to the following URL to download the software materials:

  • for For the i.MX RT1050 BSP (release 3.0.4):

https://www.emcraft.com/imxrtaddon/imxrt1050/lpspi/

...

Login: CONTACT EMCRAFT

Password: CONTACT EMCRAFT

  • for For the i.MX RT1050 BSP (release 3.1.0):

https://www.emcraft.com/imxrtaddon/imxrt1050-3.1.0/lpspi/

...

Login: CONTACT EMCRAFT

Password: CONTACT EMCRAFT

  • for For the i.MX RT1060 BSP (release 3.1.0):

https://www.emcraft.com/imxrtaddon/imxrt1060-3.1.0/lpspi/

...

Login: CONTACT EMCRAFT

Password: CONTACT EMCRAFT

4.2.
Anchor
Downloadable-Files
Downloadable-Files
Downloadable Files

The following files are available from the secure download area:

  • linux-lpspi.patch - patch to the Linux kernel sources;

  • projects-lpspi.patch - patch to the rootfs project;

  • rootfs.uImage - prebuilt bootable Linux image;

4.3. Test Set-Up

4.3.1. Hardware Setup

The following hardware setup is required for the i.MX RT 1050/1060 board:

...

SPI Memory Signal/Function

J20 Pin#

MCU Signal

MCU PAD

CS#/Chip Select

5

LPSPI1_PCS0

GPIO_SD_B0_01

SCLK/Clock Input

3

LPSPI1_SCK

GPIO_SD_B0_00

SI/Serial Data Input

7

LPSPI1_SDO

GPIO_SD_B0_02

SO/Serial Data Output

8

LPSPI1_SDI

GPIO_SD_B0_03

4.3.2. Software Setup

The following software setup is required:

  1. Download the files listed in Section: "Downloadable Files" to the top of the Linux i.MX RT installation.

  2. Install the BSP, as per the respective "Installing and activating cross development environment" document in the "Software" section on the Emcraft site.

  3. From the top of the Linux installation, activate the Linux cross-compile environment by running:

    Code Block
    $ . ACTIVATE.sh
  4. From the top of the BSP installation, go to the Linux kernel tree and install the kernel patch, eg:

    Code Block
    $ cd linux/
    $ patch -p1 < ../../linux-lpspi.patch
  5. From the top of the Linux installation, go to the projects sub-directory, and patch the rootfs project:

    Code Block
    $ cd projects/
    $ patch -p1 < ../../projects-lpspi.patch
  6. Build the rootfs project:

    Code Block
    $ cd projects/rootfs
    $ make

4.4. Detailed Test Plan

4.4.1.
Anchor
TestPlan-Demo-Project
TestPlan-Demo-Project
Test Plan: Demo Project

Perform the following step-wise test procedure:

  1. Go to the projects/rootfs directory, build the loadable Linux image (rootfs.uImage) and copy it to the TFTP directory on the host:

    Code Block
    $ cd projects/rootfs
    $ make
  2. Boot the loadable Linux image (rootfs.uImage) to the target via TFTP and validate that it boots to the Linux shell:

    Code Block
    => run netboot
    Using ethernet@40424000 device
    TFTP from server 192.168.1.96; our IP address is 192.168.1.86
    Filename 'imxrt1050/rootfs.uImage'.
    Load address: 0x80007fc0
    Loading: #################################################################
             #################################################################
             #################################################################
             #################################################################
    ...
    
    / # uname 
    Linux
    / #

4.4.2.
Anchor
TestPlan-Linux-LPSPI-Driver
TestPlan-Linux-LPSPI-Driver
Test Plan: Linux LPSPI Driver

Perform the following step-wise test procedure:

  1. From the Linux shell, run dmesg and verify that there are no error messages related to SPI or LPSPI:

    Code Block
    / # dmesg
    ...
    / # dmesg | grep spi
    / #
  2. Verify that the spi0 master is registered in the sysfs:

    Code Block
    / # ls /sys/class/spi_master/
    spi0
    / # 

4.4.3.
Anchor
TestPlan-Raw-SPI-Device-Access
TestPlan-Raw-SPI-Device-Access
Test Plan: Raw SPI Device Access

  1. Replace the SD card in the SD card slot by the SPI Flash memory M25P32 using "SD TF to TF Flexible Card Extension cable Extender Adapter".

  2. Make sure the spidev device exists:

    Code Block
    / # ls -l /dev/spidev0.0 
    crw-------    1 root     root      153,   0 Jan  1 00:00 /dev/spidev0.0
    / # 
    
  3. Make sure the spidev_flash application reads the correct Flash ID over SPI (first 3 bytes must be 0x20 0x20 0x16 for the M25P32 Flash connected the IMXRT1050-EVK board):

    Code Block
    / # spidev_flash /dev/spidev0.0
    response(7): 20 20 16 10 00 00
    / #