adafruit / Adafruit_CircuitPython_BusDevice

Two helper classes that handle transaction related state for I2C and SPI including locks.
MIT License
105 stars 76 forks source link

"spi = board.SPI()" is there a way to set this to SPI1 #89

Closed Reowald closed 2 years ago

Reowald commented 2 years ago

This is more of a question than an issue.

I am trying to setup up an ILI9340 for a 2.2" TFT Display however I am using SPI0 for something else (CAN).

I would like to set up the following pins:

MOSI - GPIO20 - Pin 38 MISO - GPIO19 - Pin35 SCLK - GPIO21 - Pin40

CS - GPIO18/17/16 - Pin12/11/38

RST - GPIO2 - Pin3 DC - GPIO3 - Pin 5

Is this possible I have tried adding these pins into the setup but without any success, the primary reason seems to be coming from board.SPI() as this defaults to SPI0

Any help would be tremendous. Thanks in advance.

n.b. this is the documentation I have been using: https://cdn-learn.adafruit.com/downloads/pdf/2-2-tft-display.pdf

caternuson commented 2 years ago

Think of the board.SPI() reference as a convenience. It provides a ready to go instance for a default set of pins. It only exists for boards where there's an obvious "default" or "main" SPI set of pins - so it should be reasonably self evident what board.SPI() is referring to. And it is really nothing more than a shortcut for creating the bus using busio, which is always an option.

If you need to setup the SPI bus on different pins, fall back to setting it up "manually" using busio. https://docs.circuitpython.org/en/latest/shared-bindings/busio/index.html#busio.SPI

ex:

import board
import busio

# change these as needed for specific board being used
# can use `dir(board)` to quickly see pin names
MOSI = board.GPIO20
MISO = board.GPIO19
SCLK = board.GPIO21

spi = busio.SPI(SCLK, MOSI, MISO)
Reowald commented 2 years ago

Thanks for your rapid response.

dir(board) yielded some interesting information from the cm4

['CE0', 'CE1', 'D0', 'D1', 'D10', 'D11', 'D12', 'D13', 'D14', 'D15', 'D16', 'D17', 'D18', 'D19', 'D2', 'D20', 'D21', 'D22', 'D23', 'D24', 'D25', 'D26', 'D27', 'D3', 'D4', 'D5', 'D6', 'D7', 'D8', 'D9', 'I2C', 'MISO', 'MISO_1', 'MOSI', 'MOSI_1', 'RX', 'RXD', 'SCK', 'SCK_1', 'SCL', 'SCLK', 'SCLK_1', 'SDA', 'SPI', 'TX', 'TXD', '__blinka__', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__repo__', '__spec__', '__version__', 'ap_board', 'board_id', 'detector', 'pin', 'sys']

I cheerfully dialed in

MOSI = board.MOSI_1
MISO = board.MISO_1
SCLK = board.SCLK_1

But I got an error!

OSError: /dev/spidev6.0 does not exist

So I sparked up google and found you'd been helping other lost souls :) https://giters.com/adafruit/Adafruit_CircuitPython_RGB_Display/issues/86

So followed the link and made sure everything was installed correctly but when I ran the test it said 'OSError: /dev/spidev0.0 does not exist' which is OK because it is dedicated to the MCP2515 CAN chip.

I try running the test differently with the code below:

import board
import digitalio
import busio

MOSI = board.MOSI_1
MISO = board.MISO_1
SLK = board.SCK_1
spi = busio.SPI(SLK, MOSI, MISO)
print("SPI ok!")

And I continue to get the following error 'OSError: /dev/spidev6.0 does not exist'

So I have not found the right pins to set as there are only 2 SPI channels in my cm4, not 6. So I will look into the dir(board) output and see if I can find the right pin names for the SPI1 GPIO.

Thanks for your help, I thought I would respond and capture my thoughts as it helps me and if you have any further advice would be much great but you have already been really helpful twice!

caternuson commented 2 years ago

Looks like you are using a Raspberry Pi CM4 (BCM2711), which means you're also using Blinka to allow using CircuitPython libraries. It seems like maybe SPI is not currently enabled at all on your setup, since you're getting both 'OSError: /dev/spidev0.0 does not exist and OSError: /dev/spidev6.0 does not exist.

Here's where the pins to SPI port mapping occur for the CM4: https://github.com/adafruit/Adafruit_Blinka/blob/5373fc664a99122ce3e8b8e05cebbbf3f18f9df1/src/adafruit_blinka/microcontroller/bcm2711/pin.py#L82-L90

How was the initial install of Blinka done? Were you following this guide? https://learn.adafruit.com/circuitpython-on-raspberrypi-linux/installing-circuitpython-on-raspberry-pi

Reowald commented 2 years ago

PXL_20220524_102845342

I went backward a little just to better understand what is happening and tried to run the ILI9340 using SPI0 and the default pins. I also disabled the CAN 'dtoverlayMCP2515...'

And fantastic the screen worked which was a relief. However, retracing my steps and using the following IO I still was not able to access SPI1.

<html xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:x="urn:schemas-microsoft-com:office:excel" xmlns="http://www.w3.org/TR/REC-html40">

GPIO17 | SPI1_CE1_N | 50 | CM4_SPI1_CS1 | Also can be GPIO | pHat Pin 11 -- | -- | -- | -- | -- | -- GPIO18 | SPI1_CE0_N | 49 | CM4_SPI1_CS0 | NC | pHat Pin 12 GPIO19 | SPI1_MISO | 26 | CM4_SPI1_MISO |   | pHat Pin 35 GPIO20 | SPI1_MOSI | 27 | CM4_SPI1_MOSI |   | pHat Pin 38 GPIO21 | SPI1_SCLK | 25 | CM4_SPI1_SCLK |   | pHat Pin 40 GPIO2 | SDA1 | 58 | CM4_SDA1 | RST | pHat Pin 3 (1.8K pull-up) GPIO3 | SCL1 | 56 | CM4_SCL1 | DC | pHat Pin 5 (1.8K pull-up)

I still get this pesky error!

OSError: /dev/spidev6.0 does not exist

Below is an exert from the code I modified based on the previous information you provided, incidentally the main code I stole from https://learn.adafruit.com/2-2-tft-display/assembly?view=all the 'Displaying System Information' project.

cs_pin = digitalio.DigitalInOut(board.D17)
dc_pin = digitalio.DigitalInOut(board.D3)
reset_pin = digitalio.DigitalInOut(board.D2)

MOSI = board.MOSI_1
MISO = board.MISO_1
SLK = board.SCK_1

spi = busio.SPI(SLK, MOSI, MISO)

Somehow I am not able to access SPI1 through the busio module. Although I do seem to have allocated the correct pins as per: https://pinout.xyz/pinout/spi

n.b. using: 'ls/dev/spi' I am getting the following output

/dev/spidev1.0 /dev/spidev1.1

This is setup from /boot/config.txt using: dtoverlay=spi1-2cs,cs0_pin=11,cs1_pin=12

Incidentally, I get no errors with the below code using spidev.SpiDev(1, 1)

import spidev
import RPi.GPIO as GPIO
import time

GPIO.setmode(GPIO.BCM)
GPIO.setwarnings(False)
OLED_RST_PIN = 3
OLED_DC_PIN  = 2
OLED_CS_PIN  = 17
GPIO.setup(OLED_RST_PIN, GPIO.OUT)
GPIO.setup(OLED_DC_PIN, GPIO.OUT)
GPIO.setup(OLED_CS_PIN, GPIO.OUT)
#GPIO init
SPI = spidev.SpiDev(1, 1)
SPI.max_speed_hz = 9000000
SPI.mode = 0b0000

Sometimes it really feels like what's wrong with me :)

Update 1 - as you suggested feels like an issue with configuration.

Update 2: I think I am tracking it down...

With following: dtoverlay=spi1-2cs, cs0_pin=11,cs1_pin=12

pi@raspberrypi:~ $ dmesg | grep spi
[    4.420280] pinctrl-bcm2835 fe200000.gpio: pin gpio11 already requested by fe                                                                     204000.spi; cannot claim for fe215080.spi
[    4.420304] pinctrl-bcm2835 fe200000.gpio: pin-11 (fe215080.spi) status -22
[    4.420343] spi-bcm2835aux fe215080.spi: Error applying setting, reverse thin                                                                     gs back
[    4.420412] spi-bcm2835aux: probe of fe215080.spi failed with error -22
pi@raspberrypi:~ $ ls /dev/*spi*
/dev/spidev0.0  /dev/spidev0.1

After removing pin 11 from cs0: dtoverlay=spi1-2cs,cs1_pin=12

pi@raspberrypi:~ $ ls /dev/*spi*
/dev/spidev0.0  /dev/spidev0.1  /dev/spidev1.0  /dev/spidev1.1

Update 3 - Ok still error still persists. OSError: /dev/spidev6.0 does not exist

Update 4 - I am still confused as to why MOSI_1, MISO_1 SCK_1 that should be SPI1 are pointing to /dev/spidev6.0

>>> board.MOSI_1
20
>>> board.MISO_1
19
>>> board.SCK_1
21
>>> spi = busio.SPI(board.SCK_1, board.MOSI_1, board.MISO_1)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/local/lib/python3.7/dist-packages/busio.py", line 289, in __init__
    self._spi = _SPI(portId)
  File "/usr/local/lib/python3.7/dist-packages/adafruit_blinka/microcontroller/generic_linux/spi.py", line 25, in __init__
    self._spi = spi.SPI(device=(portid, 0))
  File "/usr/local/lib/python3.7/dist-packages/Adafruit_PureIO/spi.py", line 167, in __init__
    raise IOError("{} does not exist".format(device))
OSError: /dev/spidev6.0 does not exist
>>> spi = busio.SPI()

Shouldn't this code be pointing towards /dev/spidev6.0

There are only SPI0 and SPI1 so possibly this is the issue?

Maybe this code:

spiPorts = (
    (0, SCLK, MOSI, MISO),
    (6, SCLK_1, MOSI_1, MISO_1),
    (2, SCLK_2, MOSI_2, MISO_2),
    (3, D3, D2, D1),
    (4, D7, D6, D5),
    (5, D15, D14, D13),
)

Should read:

spiPorts = (
    (0, SCLK, MOSI, MISO),
    (1, SCLK_1, MOSI_1, MISO_1),
    (2, SCLK_2, MOSI_2, MISO_2),
    (3, D3, D2, D1),
    (4, D7, D6, D5),
    (5, D15, D14, D13),
)
caternuson commented 2 years ago

@makermelissa Any ideas? I'm not familiar with the CM4 specifics. Should the Blinka install script be taking care of setting up and enabling /dev/spidev6.0?

Reowald commented 2 years ago

Just for your reference, I am using a cm4 with a "Compute Module 4 IO Board" to connect to the IO, however,I believe in setup this should be no different from a pi4 - it has a [pi4] Model Filter for the config.txt

brentonthedon commented 2 years ago

You're suggestion here "spiPorts = ( (0, SCLK, MOSI, MISO), (1, SCLK_1, MOSI_1, MISO_1), (2, SCLK_2, MOSI_2, MISO_2), (3, D3, D2, D1), (4, D7, D6, D5), (5, D15, D14, D13), )"

got implemented in a new update for PureIO a few days ago. I was running into the same issue while trying to use SPI1 for a separate sensor while still using SPI0 for a CAN device.

Reowald commented 2 years ago

@brentonthedon thanks for this - so it was an issue but maybe I raised it in the wrong place? Thanks for the response. I will test in the coming weeks!

brentonthedon commented 2 years ago

I think the reason that mapping was done that way where 1 became 6 is to deal with the fact that you can't use spi1 in mode = 1