SPI (SSP) example software

Colibri iMX6 512MB IT v1.1B
Colibri Evaluation Board v 3.2B
torizon-core-docker-evaluation-colibri-imx6-Tezi_5.6.0-devel-202202+build.21.container.tar

Hi guys,

I have been surfing around for how to get my SPI bus up and running as quickly as possible.
I understand the quickest way to do this is to use TorizonCore’s device tree overlays,
(i.e. do NOT try to build your own (custom) TorizonCore image, with a device tree, but use a pre-built image and override the device tree with the overlay.)

It seems there is still lot of work to do here, but here is a short checklist of what resources I have found, and what I have done so far (added incase others find this useful, I added some errors I bumped into along the way… my actual question is further down)

INSTALL TorizonCore Builder on your PC
Note that you cannot close the session, or you may have to start this procedure from scratch (environment variable will be lost)

Create and enter a working directory where your customization will be stored:

$ mkdir ~/tcbworkdir
$ cd ~/tcbworkdir

Use the setup script named tcb-env-setup.sh, available on the Toradex Github]tcb-env-setup/tcb-env-setup.sh at master · toradex/tcb-env-setup · GitHub
to setup TorizonCore Builder:

$ wget https://raw.githubusercontent.com/toradex/tcb-env-setup/master/tcb-env-setup.sh
$ source ./tcb-env-setup.sh

Error: -sh: source: tcb-env-setup.sh: file not found
Error: could not pull TorizonCore Builder from Docker Hub!
Are you doing this on the target? Should be on your PC!

WATCH the video:

It shows you how to:
-create a template

$ torizoncore-builder build --create-template

-edit the template carefully in vi

I found another thread which suggests the following changes to his .dts file:

diff --git a/arch/arm/boot/dts/imx7-colibri-eval-v3.dtsi b/arch/arm/boot/dts/imx7-colibri-eval-v3.dtsi
index 1db5aa5..28a8bc7 100644
--- a/arch/arm/boot/dts/imx7-colibri-eval-v3.dtsi
+++ b/arch/arm/boot/dts/imx7-colibri-eval-v3.dtsi
@@ -101,14 +101,14 @@
interrupt-parent = <&gpio5>;
interrupts = <2 IRQ_TYPE_EDGE_FALLING>;
spi-max-frequency = <10000000>;
-               status = "okay";
+               status = "disabled";
};
spidev0: spidev@0 {
compatible = "toradex,evalspi";
reg = <0>;
spi-max-frequency = <23000000>;
-               status = "disabled";
+               status = "okay";
};
};

RUN torizoncore-builder

$ torizoncore-builder build

Here is where I made it so far… Now I have parsing errors.

=>Parsing errors found:
tcbuild.yaml: ‘source-dir’ is a required property, while parsing /customization/kernel/modules/1

CODE
I found the SPI API described here:
SPI Lib API (toradex.com)
but it does not seem to mention the iMX6 so I don’t know if its the right link for me.

Sorry if this post was a little long…
My questions are:

  • Which .dts example should I start with for Colibri-Eval-Board and iMX6, and where to find it?
  • How to fix parsing errors above (source-dir) am I supposed to define this as an environment variable
  • Once I have the device tree overlay working, how to test?
    • by command line
    • by spidev.c
    • Is there other example code for the Colibi-Eval-Board which I should know about, like using the CAN bus? I have not found any examples yet, not even to flash an LED.
  • The note about not shutting down your session is worrysome. What can I do to ensure I can repeat these steps properly in the future?
  • what do I include in my .h file. I have tried various versions of
    #include <spi/spi.h>
    but it not found by the linker.

Greetings @leighjboyd,

Which .dts example should I start with for Colibri-Eval-Board and iMX6, and where to find it?

All of our device tree source files can be found in our Linux Kernel: linux-toradex.git - Linux kernel for Apalis, Colibri and Verdin modules

Make sure you’re looking at the right branch that corresponds to the kernel on the device.

We also have all our pre-made device tree overlays here: device-tree-overlays.git - Sources for Device Tree Overlays

How to fix parsing errors above (source-dir) am I supposed to define this as an environment variable

It’d be easier to help with said parsing errors, if you shared what your tcbuild.yaml looks like.

Once I have the device tree overlay working, how to test?

If after applying the change there is an entry on the device that looks like /dev/spidevA.B. Then you’ve successfully enabled an SPI. All that changing the device tree does is enable a spidev device file to be made in /dev.

For actually working with spidev programmatically please refer to the kernel documentation for spidev: https://www.kernel.org/doc/Documentation/spi/spidev

The note about not shutting down your session is worrysome. What can I do to ensure I can repeat these steps properly in the future?

Take notes, write a script, or use the build command. The intended way is to use the build command. Then all you have to do is manage your tcbuild.yaml. Then in the future you just run the setup script again and run the build command on your tcbuild.yaml.

what do I include in my .h file. I have tried various versions of
#include <spi/spi.h>
but it not found by the linker.

Where are you compiling? Also according to the kernel spidev documentation the header for spidev is #include <linux/spi/spidev.h>. Though spidev is just a simple wrapper driver. If you require more advanced SPI utilities/drivers you’ll need to take a look to see what fits your needs.

Best Regards,
Jeremias

Here is my tcbuild.yaml file, removed comments for brevity:
No more parsing errors (I removed all the excess changes made in the video, like adding additional overlays, kernel arguments, hello-mod, docker-compose and bundle parts. I hope I didn’t need them)

input:
  easy-installer:
          local: torizon-core-docker-evaluation-colibri-imx6-Tezi_5.6.0-devel-202202+build.21.container.tar
customization:
   filesystem:
      - changes/
   device-tree:
     include-dirs:
       - device-trees/include/
     custom: device-trees/dts-arm32/imx6ull-colibri-eval-v3.dts
output:
  easy-installer:
    local: output_directory

now I just get:
No such file or directory: 'device-trees/dts-arm32/imx6ull-colibri-eval-v3.dts'

I see i need to follow the link for the source files, as you say. But “make sure you are looking at the right branch” part was a little tricky… cant find these files.

I replaced my #include <spi/spi.h> with #include <linux/spi/spidev.h> and no more squiggly lines!

So is it true that all the spi.h API with functions like SPIInit() and SPIReadWritePolling() are only for WindowsCE? Grrr… Okay, breathe…

Wait what are you trying to do with this tcbuild.yaml?

You’re going to install a device tree for the Colibri i.MX6ULL on an image for the Colibri i.MX6? Also as for the No such file or directory, you need to actually provide the files that you set in the tcuild.yaml.

Furthermore if this is all for SPI, there should be a single SPI interface enabled by default on the Colibri i.MX6 for Torizon. Or do you need more/a different SPI?

Also yes those API functions are for WindowsCE. WindowsCE and Torizon/Linux are completely different OSes and thus have different API for near everything.

Best Regards,
Jeremias

I thought I wanted to make a device overlay to use the SPI bus.
Yes, I just need the one default SPI interface.

I was reading here:
SPI (Linux) (toradex.com)
that you needed to disable the CAN bus or something…

For NAND-based SoMs, in order to use spidev instead one needs to disable (e.g. status = “disabled”) the mcp2515 device tree node and enable (e.g. status = “okay”) the spidev… (see also screenshots earlier)

But maybe it doesn’t apply for me?

Also,
I was just recently told by our third party developer to look here:
https://github.com/toradex/device-trees/tree/toradex_5.4-2.1.x-imx/dts-arm32

for these three files
device-trees/imx6qdl.dtsi at toradex_5.4-2.1.x-imx · toradex/device-trees (github.com)
device-trees/imx6dl-colibri-eval-v3.dts at toradex_5.4-2.1.x-imx · toradex/device-trees (github.com)
device-trees/imx6qdl-colibri.dtsi at toradex_5.4-2.1.x-imx · toradex/device-trees (github.com)

So you’re saying maybe this was all just a good ‘learning experience’?
(I will need to do this eventually I guess, since we aren’t using the Colibr Eval Board forever…)

When I look in the /dev folder I see…
image

but no SpidevA.B like I was expecting to find - as explained in:
SPI (Linux) (toradex.com)
it says :

The standard SPI interfaces are enabled by default. Most modules offer additional (non-standard) SPI interfaces, to enable these device trees or board files aka platform data customization is required.

The Colibri Evaluation Board provides an MCP2515 SPI CAN controller. For Colibri modules the kernel driver for this CAN controller is active by default and no userspace SPI access is possible, i.e. the /dev/spidevA.B device files are not available. See the carrier board section for further information.

Also note that I am running my code in a dev container, if that makes any difference…

I was about to do something like this:

my-colibri-overlay.dts

/plugin/:
/* Colibri SSP */
&ecspi4 {
	cs-gpios = <&gpio5 2 GPIO_ACTIVE_HIGH>;
	pinctrl-names = "default";
	pinctrl-0 = <&pinctrl_ecspi4>;
	status = "okay";

	spidev0: spidev@0 {
		compatible = "toradex,evalspi";
		reg = <0>;
		spi-max-frequency = <23000000>;
+       status = "okay";
	};
};

I also have this sample code from our 3rd party developer, but it was intended for our own hardware, and an angstrom linux image (not TorizonCore) so I wasn’t sure if I could still use it…

.
.
/* CAN controller */

&can1 {
	status = "okay";
};

&can2 {
	status = "disabled";
};

/* Colibri SSP */
&ecspi4 {
	
	status = "okay";

	mcp251x0: mcp251x@0 {
	compatible = "microchip,mcp2515";
	reg = <0>;
	clocks = <&clk16m>;
	interrupt-parent = <&gpio3>;
	interrupts = <27 0x2>;
	spi-max-frequency = <10000000>;
	status = "disabled";
	};

	spidev0: spidev@0 {
	compatible = "toradex,evalspi";
	reg = <0>;
	spi-max-frequency = <23000000>;
	status = "okay";
	};

};
.
.

thanks

I just managed to rebuild the image, using the following overlay:

/dts-v1/;
/plugin/;

/* Colibri SSP */
&ecspi4 {
	mcp251x0: mcp251x@0 {
		compatible = "microchip,mcp2515";
		reg = <0>;
		clocks = <&clk16m>;
		interrupt-parent = <&gpio3>;
		interrupts = <27 0x2>;
		spi-max-frequency = <10000000>;
		status = "disabled";
	};
	/* To keep the CAN controller enabled by default,
	 * disable conflicting spidev. This spidev device
	 * enables with the devicetree overlay.
	 */
	spidev0: spidev@0 {
		compatible = "toradex,evalspi";
		reg = <0>;
		spi-max-frequency = <23000000>;
		status = "okay";
	};
};

Then reloaded the easy installer and re-installed my image and I see the same spidev3.0 as above, not spidevA.B and then I realized, A and B are probably just placeholders, and spidev3.0 was what I needed all along. Duh… (suggested edit spidevA.B where A is the where A=bus number and B=slave number)

Onward!

Yes, this is what I’ve been trying to tell you. There is already a single spidev device enabled by default. The spidev kernel documentation I linked to you earlier in this thread also uses the same letter placeholders.

Best Regards,
Jeremias

Okay good.

Now for the next step then, (as the title of this question is now relevant) do we have an example somewhere? Is the idea just to take spidev_test.c and modify it for my own purposes? I read that spidev_test should already be present in linux, but I don’t seem to be able to run it from a command line.

I read that spidev_test should already be present in linux

spidev_test.c is test utility that is present in the Linux Kernel source code: linux/spidev_test.c at master · torvalds/linux · GitHub

It’s not necessarily always built into every Linux distribution however. This program can be used as a reference on how to interact with and use spidev devices.

Best Regards,
Jeremias