MegaCoreX icon indicating copy to clipboard operation
MegaCoreX copied to clipboard

spi on 4809

Open paulskirk53 opened this issue 3 years ago • 10 comments

Hi, I am using SPI to communicate between two AVR 4809s. Just to flag that the arduino commands associated with SPI do not seem to work, I documented my findings on a simple SPI transaction here

Although I now seem to have SPI working by using baremetal coding in conjunction with the Arduino framework, it seems to be fragile and the positioning of the SPI initialisation in the master and slave code sequence in the setup() routines seems critical, and in particular it seems that the 4809 acting as slave must setup before the master. This may be a prerequisite, but I din't read it anywhere (probably didn't read enough :) ) Thanks.

paulskirk53 avatar Feb 03 '22 21:02 paulskirk53

Any slave functionality you manage to make work is an achievement.

It should come as no surprise that is is difficult to make it interoperate with the SPI.h library and requires bare metal coding to do so - The SPI.h library does not support slave operation. No Arduino SPI.h library has ever supported slave operation as far as I could tell (I did a bunch of searches using open source code search engines to determine what the expectation was for SPI slave mode functionality. My conclusion was: There is none. SPI.h has nothing to do with slave operation, and never has on any modern AVR or classic AVR library, and I could only find evidence of a single third party hardware package for a different architecture that had a clumsily implemented slave mode API of their own design. Hence I would expect that it would be a fight to make SPI.h work alongside slave mode functionality. I's initialization functions are likely to interfere with initialization of slave mode. I would also think that you'd need to unset the SSD bit in order to make slave mode work, since SPI.begin() disables the SS pin....

There is no existing reference of what the API might look like for a slave SPI library and I'm not sure how one might be designed to expose enough of the functionality to be useful while legitimately being any easier than just doing it yourself.. I had been thinking about this in the context of DxCore (which has it a little easier, since there's a second SPI port, so unless you need the device to act as both a master and a slave, you can split the bus into a bus of things that are master relative to the device and things that are slave relative to the device, use one interface for each of them, and then just have to implement SPI slave on an otherwise unencumbered SPI port.) and my conclusion was that extending the SPI library for slave functionality was impractical and inappropriate.

This isn't my repo, but I would "no plans to change" this one if it were - since you're trying to do something wholly unsupported by the library and for which there is no reason to expect would be supported.

SpenceKonde avatar Feb 03 '22 22:02 SpenceKonde

Oh well, just shows my lack of knowledge about Arduino, SPI, life, the universe and everything :)

paulskirk53 avatar Feb 03 '22 23:02 paulskirk53

Though the fact that you've cobbled together a working solution seems to contradict that ;-)

SpenceKonde avatar Feb 03 '22 23:02 SpenceKonde

Just a quick comment over here - if at all possible, I would try to make one device always be the master and se stock SPI library, and the other be a slave and not touch the SPI library.

I highly recommend buffered mode for the SPI slave if you go this route. It gives you so much more margin

SpenceKonde avatar Mar 17 '22 18:03 SpenceKonde

Thanks for this. I have my 4809s set up as you've suggested, one is always the master and uses the spi lib. The other is the slave. The slave uses an ISR with commands like those shown below. I hadn't thought about it, but in fact it doesn't use the spi lib.

I have done a lot of testing since my original post and it works reliably. Thanks for help. `` // SPI interrupt routine ISR(SPI0_INT_vect) { SPIReceipt = SPI0.DATA;

if (SPIReceipt == 'A') // a dummy transaction which loads the SPI reg with the low byte { // in readiness for the 'L' transaction SPI0.DATA = lowByteReturn;

``

paulskirk53 avatar Mar 17 '22 20:03 paulskirk53

You don't need the dummy first byte, cjeck the datasneet, tere's a bit you can set to get rid of tjat with a name that sounds lke it wold do someting totally differernt

SpenceKonde avatar Mar 17 '22 22:03 SpenceKonde

@paulskirk53 I'm trying to use a 4809 as a spi slave and ran into the same issue you did. Wondering if you have a running code you would be willing to share for your 4809 in slave setup. Thanks in advance!

DirtyEngineer avatar Sep 02 '22 01:09 DirtyEngineer

The slave project code is on github here: https://github.com/paulskirk53/Azimuth_Encoder and the master project is here: https://github.com/paulskirk53/Stepper

They are both public repos' so you should be fine to access. Let me know if you need anything further and perhaps we can pm

The code which sets up the 4809 as slave is this: (based on code on the Microchip site)

static void SPI0_init(void) { PORTA.DIR &= ~PIN4_bm; /* Set MOSI pin direction to input / PORTA.DIR |= PIN5_bm; / Set MISO pin direction to output / PORTA.DIR &= ~PIN6_bm; / Set SCK pin direction to input / PORTA.DIR &= ~PIN7_bm; / Set SS pin direction to input */

SPI0.CTRLA = SPI_DORD_bm /* LSB is transmitted first / | SPI_ENABLE_bm / Enable module / & (~SPI_MASTER_bm); / SPI module in Slave mode */

SPI0.INTCTRL = SPI_IE_bm; /* SPI Interrupt enable */ }

paulskirk53 avatar Sep 02 '22 08:09 paulskirk53

Thank you for your response! This was incredibly helpful.

Reading through the data sheet did you ever end up looking into the BUFWR register in CTRLB (Section 24.5.2 of datasheet)? Seems that if you set it to 1 do don't have to throw away the first data transfer as mentioned. When writing to the data register when the SPI is enabled and SS is high, the first write will go directly to the Shift register.

Something I might try once I get a working transfer as a base line.

DirtyEngineer avatar Sep 02 '22 14:09 DirtyEngineer

Thanks for reminding me of that, no I didn't look, but now that you've flagged the particular section of the datasheet, I have no excuse! :) Glad you found it helpful. Paul

On Fri, 2 Sep 2022, 15:36 Jon Raymond, @.***> wrote:

Thank you for your response! This was incredibly helpful.

Reading through the data sheet did you ever end up looking into the BUFWR register in CTRLB (Section 24.5.2 of datasheet)? Seems that if you set it to 1 do don't have to throw away the first data transfer as mentioned https://github.com/MCUdude/MegaCoreX/issues/138#issuecomment-1071688976. When writing to the data register when the SPI is enabled and SS is high, the first write will go directly to the Shift register.

Something I might try once I get a working transfer as a base line.

— Reply to this email directly, view it on GitHub https://github.com/MCUdude/MegaCoreX/issues/138#issuecomment-1235580850, or unsubscribe https://github.com/notifications/unsubscribe-auth/AIKFDCDXSXQSXSP3K2GOQZ3V4IGF5ANCNFSM5NQDAFVA . You are receiving this because you were mentioned.Message ID: @.***>

paulskirk53 avatar Sep 02 '22 15:09 paulskirk53