I'm trying to control my WS2801 LED Stripe with my Raspberry Pi 4 over the SPI interface.
The Pi is running un Ubuntu 20.04 with the kernel version: Linux ubuntu 5.3.0-1030-raspi2 #32-Ubuntu SMP Sun Jul 12 21:20:28 UTC 2020 aarch64 aarch64 aarch64 GNU/Linux
The setup and connection to the LED Strip should be fine. I've validated it with a test script on my Pi3 and it worked properly. With the test script running on the PI there is no error, but nothing happens on the LED stripe.
So far, I have the understanding that in order to communicate over the SPI we need the spidev and the spi-bcm2835 module to be loaded.
Output of lsmod | grep spi:
spidev 28672 0
IMO, there should be spi_bcm2835 as well. In the /dev/ folder there is spidev0.0 and spidev0.1, as it should be. Calling sudo modprobe spi_bcm2835 gives no error but does not solve the issue.
My /boot/firmware/config.txt:
[pi4]
kernel=uboot_rpi_4.bin
max_framebuffers=2
[pi3]
kernel=uboot_rpi_3.bin
[all]
arm_64bit=1
device_tree_address=0x03000000
start_x=1
gpu_mem=512
dtparam=spi=on
dtparam=sound=on
dtparam=i2c_arm=on
dtparam=i2s=on
dtoverlay=spi-bcm2835
My /etc/modules:
i2c-dev
spi-bcm2835
spi-dev
snd-bcm2835
There is no blacklist entry with respect to the spi inside the /etc/modeprob.d/ files.
The only related entry in dmesg is [ 1.559971] spi-bcm2835 fe204000.spi: could not get clk: -517. But as far as I know -517 means that the module is just loaded later because it's not ready at this timestep.
Does anybody know what the issue might be here? Thanks!
This is my test_script:
/******************************************************************************/
/* */
/* FILE: ledstrip.cpp */
/* */
/* Displays the contents of a file on a LED strip */
/* ============================================== */
/* */
/* V0.01 18-DEC-2015 Te */
/* */
/******************************************************************************/
#include <stdio.h>
#include <ctype.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdint.h>
#include <string.h>
#include <time.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <linux/spi/spidev.h>
static const char *device = "/dev/spidev0.0" ;
static uint32_t speed = 500000 ;
static uint8_t mode = SPI_MODE_0 ;
static uint8_t bits = 8 ;
static unsigned char tx[75] ;
static unsigned char rx[75] ;
static struct spi_ioc_transfer parameters[1];
static int offset = 0 ;
static int spi ;
/*************/
int OpenSPI()
/*************/
{
spi = open( device, O_RDWR ) ;
if( spi < 0 )
{
fprintf( stderr, "can't open device\n" ) ;
return 1 ;
}
int ret = ioctl( spi, SPI_IOC_WR_MODE, &mode ) ;
if( ret == -1 )
{
close( spi ) ;
fprintf( stderr, "can't set mode\n" ) ;
return 2 ;
}
ret = ioctl( spi, SPI_IOC_WR_BITS_PER_WORD, &bits ) ;
if( ret == -1 )
{
close( spi ) ;
fprintf( stderr, "can't set bits\n" ) ;
return 3 ;
}
ret = ioctl( spi, SPI_IOC_WR_MAX_SPEED_HZ, &speed ) ;
if( ret == -1 )
{
close( spi ) ;
fprintf( stderr, "can't set speed\n" ) ;
return 4 ;
}
memset( ¶meters, 0, sizeof(spi) ) ;
parameters[0].tx_buf = (unsigned long)tx ;
parameters[0].rx_buf = (unsigned long)rx ;
parameters[0].len = 75 ;
parameters[0].delay_usecs = 0 ;
parameters[0].speed_hz = speed ;
parameters[0].bits_per_word = bits ;
parameters[0].cs_change = 0 ;
return 0 ;
}
/***************/
void CloseSPI()
/***************/
{
close( spi ) ;
}
/*****************/
void ResetState()
/*****************/
{
memset( tx, 0, sizeof(tx) ) ;
}
/****************/
void ShowState()
/****************/
{
if( ioctl(spi,SPI_IOC_MESSAGE(1),¶meters) == -1 )
fprintf( stderr, "can't transfer data\n" ) ;
}
/*******************************/
void Token( const char *token )
/*******************************/
{
if( isdigit(*token) )
{
int value = atoi( token ) - 1 ;
if( (value >= 0) && (value <= 24) )
tx[value*3+offset] = 255 ;
}
else
{
switch( tolower(*token) )
{
case 'r' : offset = 0 ;
break ;
case 'g' : offset = 1 ;
break ;
case 'b' : offset = 2 ;
break ;
}
}
}
/***************************/
void Line( const char *ps )
/***************************/
{
ResetState() ;
char token[25] ;
size_t i = 0 ;
while( *ps != '\0' )
{
if( isspace(*ps) )
{
if( i > 0 )
{
token[i] = '\0' ;
Token( token ) ;
}
i = 0 ;
}
else
{
if( i < sizeof(token) - 1 )
token[i++] = *ps ;
}
++ps ;
}
ShowState() ;
}
/***************************/
void ReadFile( FILE *file )
/***************************/
{
char line[1024] ;
struct timespec in ;
struct timespec out ;
while( fgets(line,sizeof(line),file) != NULL )
{
Line( line ) ;
in.tv_sec = 0 ;
in.tv_nsec = 125000000 ;
nanosleep( &in, &out ) ;
}
}
/*********************************/
void File( const char *filename )
/*********************************/
{
FILE *file = fopen( filename, "r" ) ;
if( file != NULL )
{
ReadFile( file ) ;
fclose( file ) ;
}
}
/**********************************/
int main( int argc, char *argv[] )
/**********************************/
{
if( OpenSPI() != 0 )
return 1 ;
if( argc == 1 )
ReadFile( stdin ) ;
else
{
for( int i = 1; i < argc; i++ )
File( argv[i] ) ;
}
CloseSPI() ;
return 0 ;
}