Closed oloynet closed 9 years ago
What mraa calls a spi context or object really is a SPI Bus + HW CS. So asking for '0' will give you a spidev5.1 we could make '1' give you spidev5.2 with a different CS. I'm reluctant to do any soft CS stuff because on some devices (like galileo gen2 or edison + arduino) doing so could cause the ADC to crash or on some devices (vocore) cause the MMC to be corrupted. With that in mind, no one is stopping you from making a CS manually like you've done :)
I don't think in SPI anything says you have to keep your CS low during the whole transfer period, however as with everything SPI there may some devices that may not like you doing so. We can change this behaviour via the spi_transfer.cs_change flag & spi_transfer.delay_usecs, I admit I don't think anyone has looked at this and what the correct default behaviour should be. Currently we stick to what the default for the driver is, maybe that's not idea. We can definately let users customise those fields with a new API, however I'd like to get an idea of what a sensible delay in usecs would be for yourself (@tingleby, @KurtE any opinions on this?). It looks like on edison we take <10us between transfers so maybe that's a sensible 'default'?
I have had a similar problem, here are my 10 cents:
Depending on Hardware (Intel Edison for example is fine) you can set the number of bits that spi transfers in mraa. I used this to transfer 16bits to the max7219 device (look at the example on github in mraa/examples) So with the right hardware you may not need to use a custom CS
One thing I wanted to do some day is to to the SPI ioctl to disable CS (so that no other devices are disturbed) to have more than 9 bits on Raspberry Pi. As you are currently working on this, could you try the ioctl? This could make the whole thing a lot saver.
As you said, it works in 16 bits mode without a custom CS. I've made some change in my code to support the new format. One thing to know, data are sended in LSB mode. I've try to change this with _mraa_spilsbmode but I've the error : spidev spi5.1: setup: unsupported mode bits 8 ??????
Here the new code for who are interesting
/*
* Max31865 chip on SPI bus with MRAA
* http://datasheets.maximintegrated.com/en/ds/MAX31865.pdf
*
* gcc -lmraa -o max31865-16bits max31865-16bits.c
*/
#include "mraa.h"
#include <unistd.h>
#include <stdint.h>
int main(int argc, char **argv)
{
mraa_init();
printf("MRAA Version: %s\n\n", mraa_get_version() );
// -------------------------------------
printf("Init SPI (mode 3 - 1MHz)\n\n");
mraa_spi_context spi;
spi = mraa_spi_init(1); // 0 = spidev5.1 / 1 = spidev5.2
mraa_spi_mode(spi, MRAA_SPI_MODE3);
mraa_spi_frequency(spi, 1000000);
//mraa_spi_lsbmode(spi, 0); // don't work : spidev spi5.1: setup: unsupported mode bits 8 ???
mraa_spi_bit_per_word(spi, 16);
usleep(1000);
// -------------------------------------
printf("Configure Max31865\n\n");
uint8_t tx_init[] = {0xc3, 0x80}; // see Table 2. Configuration Register Definition - page 12
uint8_t *rx_init;
rx_init = mraa_spi_write_buf(spi, tx_init, 2);
printf(" > Write 0x%02x%02x -- Read 0x%02x%02x \n", tx_init[0], tx_init[1], rx_init[0], rx_init[1]);
usleep(1000);
printf("\n");
// -------------------------------------
printf("Start reading Max31865 from address 0x00 and all the 8 registers\n\n");
unsigned int i;
uint8_t reg[8];
uint8_t tx_read[] = {0x00,0x00};
uint8_t *rx_read;
for (i = 0; i < 8; i++) {
tx_read[1] = i;
rx_read = mraa_spi_write_buf(spi, tx_read, 2);
reg[i] = rx_read[0];
//printf(" > Write 0x%02x%02x -- Read 0x%02x%02x\n", tx_read[0], tx_read[1], rx_read[0], rx_read[1]);
}
printf("\n");
printf(" > Reg. Configuration = %02x\n", reg[0]);
printf(" > Reg. RTD MSBs = %02x\n", reg[1]);
printf(" > Reg. RTD LSBs = %02x\n", reg[2]);
printf(" > Reg. High Fault Threshold MSB = %02x\n", reg[3]);
printf(" > Reg. High Fault Threshold LSB = %02x\n", reg[4]);
printf(" > Reg. Low Fault Threshold MSB = %02x\n", reg[5]);
printf(" > Reg. Low Fault Threshold LSB = %02x\n", reg[6]);
printf(" > Reg. Fault Status = %02x\n", reg[7]);
printf("\n");
// -------------------------------------
printf("Decode Max31865 values\n\n");
double Rref = 4000; // for PT1000
unsigned int RTDdata;
unsigned int ADCcode;
double R;
double temp;
RTDdata = reg[1] << 8 | reg[2]; // MSB + LSB
if (RTDdata & 1) {
printf(" > Sensor connection fault");
} else {
ADCcode = RTDdata >> 1;
R = (double)ADCcode * Rref / 32768;
temp = ((double)ADCcode / 32) - 256;
printf(" > RTDdata = %04x\n", RTDdata);
printf(" > ADCcode = %d\n", ADCcode);
printf(" > R = %f\n", R);
printf(" > temp = %f\n", temp);
}
}
Now the CS is set low state during all the 16 bits transfer (ex. for the configuration)
@arfoll : I understand it's difficult to change the CS by soft because it had repercussion on other parts like you mention, and also on spidev dependance. Do I close this issue and open one for customer parameters for SPI ?
Thanks for all answers.
@oloynet this is weird, wonder if it's like this on other platforms I'll investigate and get back to you - keeping this bug open is fine, bit long but that's life ehehe! @michael-ring by disabling cs_change I wonder if we can just disable the HW CS. Again I'll try this and get back, if it's really that easy then it makes sense to do this IMHO.
I guess it is that simple, search for no-cs in https://www.kernel.org/doc/Documentation/spi/spidev_test.c
We can make the whole thing (nearly) transparent to the end user if the cs is not needed for more that 32 bits. On the Raspberry it might be that we can use the old CS pin, even though it is reserved by SPI. But I did not do any serious testing on that. If you consider implementing a feature for Soft-CS then I can dig deeper on Raspberry. Which other platforms would benefit? Beaglebone is fine, Edison is fine, both can do 32bits ootb, what about the other intel boards?
I dont understand - "the cs is not needed for more that 32 bits"? Can you explain?
usually I see CS for 8,9,16 and 32 bits on spi devices. For those cases soft-spi could work as a drop in replacement for platforms like Raspberry that can only do 8 or 9 bit cs. The other usecase I see is to extend the number of available cs pins, but this would need more work because then there is a need to support 'virtual' spi devices that use the real spi device in no_cs mode and do the handling of the assigned gpio pin. This would make it possibe to have a lot more devices on the SPI bus.
The first case is fairly easy to implement, would mean that a device can get initialized with no_cs and there should be a new function that allows you to assign a gpio pin as replacement-CS. Then the whole logic for using cs can get hidden in the functions that send/receive byte,word and (perhaps) long data.
Just to give a small update - this looks like an edison spi kernel issue and not a mraa issue, it's happening only on that platform. We're working on our end on to find out what's wrong there.
@michael-ring on rpi that sounds like the spi kernel driver should fix the CS, alot of platforms (edison included) use a gpio in kernel to replace the HW CS in cases when it's not possible to get the HW to do the right thing. As for adding 'soft-cs' from userspace, let's talk about that in a different issue :)
Quick notes:
there appear to be issues with SPI with current beta. Sample program at top of this message tries to work around with output 0 character to get CS right... Appears to be new power management issue, I talk about in thread: https://communities.intel.com/thread/60326 I also mention a hack to the file I did to get the Adafruit display to work. (Intel_mid_ssp_spi.c)
Actually I think Edison uses normal IO pin in the kernel to do CS for SPIDEV device. (platform_spidev.c)
MRAA: Not currently supporting spi_ioc_transfer.cs_change field. Also not sure exactly how it is supposed to work. From Kernel, it looks like if asserted it does not change CS line? Some places imply that it should leave the CS asserted when the transfer completes.
@KurtE yes edison should use a normal IO pin for cs spidev but it seems it does not in the case of writing bytes which is weird - do you know if the behaviour is the same on arduino code? I haven't tried that. Anyways the edison kernel guys are on it, I'll post an update here.
cs_change does something else you're right, we have to change spi mode thought that doesn't seem to work, I tried with spidev_test like:
root@edison:~# ./spidev_test -D /dev/spidev5.1 -s 1000000 -N
can't set default spi mode: Invalid argument
Aborted
So it seems that changing the spi mode doesn't work on edison - if it works on other platforms then I'm happy to include something like this http://dpaste.com/1N276PZ or similar to disable the HW cs - we can just disable it on platforms where this is not possible.
Nice!
I would like to take this code and extend it a little, please keep me posted when you add more functionality to the disable cs code.
Since this thread got too long, #149 is for NOCS discussion. The edison issue of CS going high between every byte is now fixed.
Hello,
I also want to use a custom chipselect.I want the CS to be high initially just before the transfer and go low with the first falling edge of the SCK first bit transfered. How do I achieve this?I m working with edison and I also need 16 bit transfers My CS (yellow) and SCK (green) should be as in the following diagram.
After investigating why I can't read values from the MAX31865 (RTD-to-Digital Converter), I've develop a custom chip select. The original MRAA custom select, change of state for each bytes sended, so I've develop a custom one, just to demonstrate that could fix in MRAA lib.
The program that should works but....
The result is
From the logic analyser you can see the CS change for each bytes
configuration
get values
And now a workaround with a custom chip select
The result is
and some snapshots from the analyser.
configuration with custom CS
configuration with custom CS zoomed
get values with custom CS
get values with custom CS zoomed
I put the original signal for CS on the first row.
To conclude
I'm not a specialist of SPI, but I think when you write, the CS still to be down until the end of transmission. And not change after each bytes sended. Is it a bug from MRAA ?
Before I've writing in C, I've made unsuccessful with JS and PYTHON programs.
I don't understand why before the fist data is write, the clock goes down and up ?
Also an another remark, if you have severals chips on the same SPI bus, how to you fix the CS for each chips. Can the SPI functions in MRAA libs can integrate differents CS in future ? Like choosing the CS pin when transmit data... A hardware solution can be done with mixing CS from MRAA (pin 10) and the custom CS (your pin) with a OR-gate chip and connect the output to the SPI chip
Regards, Olivier