Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Issue #338: Add support for SPI on Pi5 using /dev/spidev. #390

Open
wants to merge 3 commits into
base: develop
Choose a base branch
from

Conversation

mpilone
Copy link

@mpilone mpilone commented Oct 5, 2024

I implemented SPI support on the Pi5 using /dev/spidev. This change introduces a dependency on JNA. I implemented it in the existing LinuxFS plugin because it uses /dev/spidev, but I'm not sure if that's the intent of the existing plugin. I tested it with an OLED display using write operations, but I didn't test any read operations as I don't have an SPI device to work with. Use the code as you like.

@mistermaeks
Copy link

Hi, that means in the 2.7.1-SNAPSHOT you implemented it for the Pigpio-spi? I have a device were i could test it.

@mpilone
Copy link
Author

mpilone commented Nov 21, 2024

You can pull the code from my fork and give it a test. I jumped off to a different project for a bit but writing to an SPI display was working for me with this implementation.

@mistermaeks
Copy link

Hi, as i am quite new to git, can you please advice me how to do this?
I installed the git cli already and also the desktop version. If i try to get the repo with
gh pr checkout 390
it says the following message
none of the git remotes configured for this repository point to a known GitHub host. To tell gh about a new GitHub host, please use "gh auth login"
I already logged in with gh auth login and i also added the url to the remote origin.
The command
git remote -v
gives the following message

origin  https://github.com/Pi4J/pi4j-v2/pull/390 (fetch)
origin  https://github.com/Pi4J/pi4j-v2/pull/390 (push)

Do you have any idea what i am doing wrong?
Thx for your help.

@mpilone
Copy link
Author

mpilone commented Nov 22, 2024

You can simply clone my branch directly and then follow the normal pi4j build instructions. My branch is behind pi4j but if you're just interested in testing SPI that shouldn't matter.

git clone https://github.com/mpilone/pi4j-v2.git

@mistermaeks
Copy link

Hi,
i managed to clone the git repository of pi4j, but unfortunately i didn't manage to build a jar file. Would you be so kind to build it for me so that i can add it to my local maven repository and change my pom to the needed one?
Thanks a lot for your effort.

@mistermaeks
Copy link

Hi, is there a reason for binding it directly to SPI 0?
private final static String SPI_DEVICE_BASE = "/dev/spidev0.";
and than you use the bus, instead the chipselect
String spiDev = SPI_DEVICE_BASE + config().bus().getBus() ;

i changed it accordinlgy
private final static String SPI_DEVICE_BASE = "/dev/spidev";
and
String spiDev = SPI_DEVICE_BASE + config().bus().getBus() + "." + config().getChipSelect().getChipSelect();
But i am not able to call the create method.
Spi spi = pi4j.create(config)
My config is

return Spi.newConfigBuilder(pi4j)
				.id("SPI" + bus)
				.chipSelect(chipSelect)
				.mode(SpiMode.MODE_1)
				.name("ADS1118")
				.bus(bus)
				.baud(frequency)
				.provider(LinuxFsSpiProvider.ID)
				.build();

and my pi4j context is

var impl = LinuxFsSpiProvider.newInstance();
		Context pi4j = Pi4J.newContextBuilder()
				.noAutoDetect()
	            .add(LinuxFsSpiProvider.newInstance())
	            .build();

Do you have any idea why it is not working to call the create?
I do not have any exception at all.

@mpilone
Copy link
Author

mpilone commented Nov 25, 2024

You're probably correct that the code mixes up bus and channel in the device name. I was only using bus 0, channel 0 so it didn't matter.

I can't say what might be wrong with your code. I tested it with the code below using a simple LED display:

var spiConfig = Spi.newConfigBuilder(context)
            .address(channel)
            .baud(9600)
            .build();
System.out.printf("SPI provider: " + context.spi());
this.spi = context.spi().create(spiConfig);
this.spi.open();
System.out.println("SPI instance: " + spi);

That would use channel 0, mode 0, and baud 9600. It's possible other modes or channels aren't working correctly. I only had a RaspberryPi5 and a single LED display to test with so I definitely didn't test many variations. You can see that the code in LinuxFsSpi is pretty simple and just a few ioctl calls. The class docs link to the kernel docs I was using if you want to check if there's something wrong with the mode or channel implementation. Sorry I can't be of more help but I don't really have the setup to try different variations. I wanted to provide a base implementation for folks to build on so there was at least some SPI support for Pi5.

@mistermaeks
Copy link

Hi again,
could it be that this code is only running on a Rpi5? I am using a cm4 module. Unfortunately do i not know where to check whether the code is only Rpi5 compatible. Is it in the provided .so file which is called over JNA?

@mpilone
Copy link
Author

mpilone commented Nov 25, 2024

There's nothing Pi5 specific in this SPI code. It just uses kernel ioctl calls to talk to the /dev/spidev device. There's no native code other than the JNA core that maps the Java calls to native C calls. I suspect you'd get an exception from JNA if it didn't support your platform/architecture.

Do you have SPI working on the device outside of your Java app? Like some kind of simple python or C test code? It's possible there's an issue at the OS/SPI level that isn't directly related to Java/Pi4J. For example, something like this or this.

I don't have a CM4 to test with but if you're not getting any errors from the Pi4j SPI code, then it is probably opening the device successfully but probably not successfully talking to any SPI device.

@mistermaeks
Copy link

Hi, yes i tested it with a python script and spidev, so it is all running fine. With the Java app i already managed to get it partly working as i need the mode 1 for the SPI6 bus i tried your code. I get no error message at all that is strange. The program exits when i call the create method of the pi4j context. I also tried to switch this part and initialize the plugin directly

var impl = LinuxFsSpiProvider.newInstance();
Spi spi = new LinuxFsSpi(impl, config);

without success.

@mpilone
Copy link
Author

mpilone commented Nov 25, 2024

Oh, ok. I didn't realize your application was exiting vs just not getting any SPI data. I'm guessing that the native SPI code is causing the JVM to crash. Usually the JVM will generate an hs_err_pid.log file when this happens but it may be JVM specific.

Because you're already compiling pi4j yourself, you can try adding some System.out or configure SLF4J logging and add some logger.trace("..."); calls. I'd start with the "open" method to see if there's a specific native call that causes the VM to crash. You can obviously do this with stepping through the debugger but sometimes it is hard to get a debugger connected to your JVM on the device.

If you find the specific call that causes the JVM to crash, you can look at the value's being passed to the native call. It's possible (likely) that there's a native data type or structure field layout mismatch.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants