Electronics > Microcontrollers
Microchip MCP2517FD CAN-FD Tranceiver cannot write to chip registers?
Kawakneurder:
Hi all!
In an effort to play around with CAN-FD I decided to play around with the MCP2517FD chip.
However after wrestling around a couple of days I have come to a bit of an impasse.
In short, it seems that I cannot write values to the registers of the chip.
For ease of discussion, please find the registry/memory map of the chip on page 7 (fig 3-1) here: https://ww1.microchip.com/downloads/en/DeviceDoc/MCP2517FD-External-CAN-FD-Controller-with-SPI-Interface-20005688B.pdf
To use the CAN-FD chip, one needs to first reset it (which puts it in configuration mode), write appropriate values to a couple of registers (the details of which are not of importance in this case), and then put the chip in 'normal' operation mode.
If I however, read out the registry contents, do the registry manipulation and read back the registry contents afterwards, they have not changed. (evaluated address space is 0x000 to 0x2EC and 0xE00 to 0xE10, strangely registry space in this chip is split in half)
I can then put the chip in 'normal' mode, but the chip will never set the flag to indicate it is ready to receive data in its queue.
The particular microcontroller I use to talk to the chip is the NXP K64F, using mbed (yeah, I know, sometimes we have to use the cards we are dealt :-X)
What have I checked:
- Chip has a clock:
- signal on the crystal
- Clock output pin shows a nice square wave, with the correct frequency
- SPI seems to function as expected as well:
- Reading out the registers seems to yield valid 'default' initialization values of said registers, indicating reading works (which for SPI involves both sending out data as well as receiving)
- Also, changing SPI baudrates don't alter results (tried 100Kbps, 1Mbps and 10Mbps, no change)
- Mode changes are possible??
- Writing 'normal' opmode (0x00) to the appropriate register (cREGADDR_CiCON+3, addr 0x03) and then reading back the register, does seem to work, most of the time*.
- I have tried to get GPIO working, but could not get an output on the pins. This is not surprising if writing to registers seems borked.
Microchip has some sample code available. This contains a RAM and a registery test. Running these gives the following results:
- RAM (FIFO) manipulation seems to work
- RAM test (writing to data to and reading this data back from addr 0x400 to 0x46F) completes successfully
- Note that this address space is not the full space of memory, but is consistently good
- The registry test (writing data to and reading back from addr 0x1F0 to 0x22F) completes only partially (The first 8 bytes from addr 0x1f0 to 0x1f7 mismatch, the rest matches)
- The particular addresses evaluated are filter objects, of which the 31st bit is manipulated randomly (as this is unused by the chip)
- Note however, that these registry values do not overlap with the above configuration registries
* I noticed some weird behavior in my code as well. If I loop through the address space above (0x000 to 0x2EC) it would read the 'opmode' register as 0x00 (which would be incorrect, it should be 0x04):
(This is output printed to the terminal, where ADDR represents the memory address and VAL the associated contents)
--- Code: ---ADDR;VAL
0;0X60
0X1;0X7
0X2;0X98
! 0X3;0X00
0X3;0X4
0X4;0XF
...
--- End code ---
If I however add a specific read for the register BEFORE I loop through the address space, and check it again after, something funny happens:
(This is the particular change to the code)
--- Code: --- // Read opmode
uint8_t sp = DRV_CANFDSPI_ReadByte(index, cREGADDR_CiCON + 3, &d);
printf("Read opmode before check mem:%#X (%#X)\n",d,(cREGADDR_CiCON + 3));
// .... Loop through address space
// Read opmode again
uint8_t sp = DRV_CANFDSPI_ReadByte(index, cREGADDR_CiCON + 3, &d);
printf("Read opmode after check mem:%#X (%#X)\n",d,(cREGADDR_CiCON + 3));
--- End code ---
Will print:
--- Code: ---Read opmode before check mem:0XFF (0X3)
ADDR;VAL
0;0X60
0X1;0X7
0X2;0X98
! 0X3;0X4
0X3;0X4
0X4;0XF
0X5;0XF
0X6;0X3E
...
0XE00;0X60
0XE01;0X4
0XE04;0X3
0XE06;0X1
0XE07;0X3
Read opmode after check mem:0X4 (0X3)
--- End code ---
Note that it first shows an incorrect value of the memory address (0x30), but then during loop it DOES show the correct value (0x04).
For this to work it also NEEDS to have the print statement between. This makes me suspect it might have something to do with the internal mbed SPI libraries requiring some time to copy things over or doing weird stuff.
However, recompiling or changing some things around makes the result incorrect for both again. These non-deterministic issues... :-BROKE
It is quite late now, tomorrow I am hooking up the scope to the SPI bus to confirm whether the values I transmit and read back correspond with reality, or that perhaps it is something on a hardware level on the bus.
In the meantime, does this have something to do with the way Mbed SPI works? Or something with the stack?
Has anyone had similar issues before, or does anyone have any suggestions on what to check next?
It's a bit of a shot in the dark, but any help and pointers would be much appreciated. :)
IDEngineer:
First suggestion: Stop using other people's SPI libraries and control the SPI hardware yourself. You're already questioning if the library "needs time" for... something. Do it yourself and eliminate an entire layer of unknowns.
Kawakneurder:
--- Quote from: IDEngineer on November 06, 2024, 05:44:06 am ---First suggestion: Stop using other people's SPI libraries and control the SPI hardware yourself. You're already questioning if the library "needs time" for... something. Do it yourself and eliminate an entire layer of unknowns.
--- End quote ---
Personally I don't think it is the SPI bus and/or K64F, but more related with the chip.
I have also interfaced with some other SPI/SSI sensors and never had issues....
Anyway, I have done some further digging this morning. After dusting off the logic analyzer, I managed to capture some traces to compare what the uC thinks its sending/receiving, and what's actually being seen on the bus. All communication is done at 100Ksps:
Apologies that I didn't convert the decimal of the terminal into hex. I compared them manually, the result of which is in the right most columns.
In conclusion, it seems to match. Also note here that address 0x03 produces the correct content 0x04.
However, there is an excessive amount of print statements to retrieve the TX/RX bytes from the uC. So subsequently I removed these and only printed the results of registers (the addr/val combinations). Here a view of these:
Note here that address 0x03 produces the WRONG content, and returns 0x00. But that it does so on the bus as well.
There's some missing registry values, I think this is due to printf overflows or something else. Im not too worried about this.
At least this seems to confirm that most likely the read/write values do work.
And this makes me think, is this the MCP chip being weird with SPI read/writes? Or is it possibly a hardware issue? The latter would surprise me, as the hardware is extremely simple (just SPI connected straight through, a crystal which is confirmed working and some decoupling for the chip).
I think I might try to solder a new chip on a board, perhaps it got damaged somehow.
IDEngineer:
--- Quote from: Kawakneurder on November 06, 2024, 12:20:11 pm ---Personally I don't think it is the SPI bus and/or K64F, but more related with the chip. I have also interfaced with some other SPI/SSI sensors and never had issues....
--- End quote ---
SPI is mind-numbingly simple, which is a key strength over I2C. The only question is generally "which mode?" so the edges match between Master and Slave. You can bit-bang it in firmware to prove things work, if necessary.
If you're able to read/write some of the registers, it's very likely the hardware is OK. Seems unlikely that "some" internal registers would be damaged and not others. I have interfaced via SPI to other Microchip standalone CAN chips and they work just fine. No surprises. I doubt it's the chip.
Ideas:
1) Re-study the chip spec sheet. See if there are any timing requirements you've missed. There weren't any in the other CAN parts I've used but who knows. I'm thinking here of EEPROM which often requires a delay after a write. These chips don't generally have EEPROM but I'm using this as an example.
2) Confirm your SPI modes match. Again, if some registers work they all should work, but since nothing obvious has popped up it's time to check everything.
3) Look carefully at how the SPI peripheral in your MCU works (again, RTFM). Also, are you handling the chip select signal properly? Are you coordinating it with the SPI exchange? I think of chip select as an SPI reset signal... when it's deselected the SPI hardware completely resets and you get a fresh start when you take CS active again. If the timing between CS and your SPI clock/bits is off lots of weird things can happen.
Hope this helps!
Kawakneurder:
I've finally had some time to mess around again with the chip, and again hook the scope to the SPI bus.
Looking at the SPI traces on the scope it seemed there was some potentially strange stuff going on during startup.
Chip select is done with a GPIO, which was kept in active state on startup until configured.
After some deliberation I had decided to put a pullup resistor on the CS line to force it to be deselected when the pin is tri-state.
That seems to have fixed it!
Register values are now consistent, and I can read/write to registers (confirmed by using the build in I/O of the chip).
Can't get any messages out of the CAN bus yet, but that probably has to do with some configuration issues of the FIFO that I will need to have another look at.
Thanks @IDEngineer for having a think, and for the suggestions. :)
Navigation
[0] Message Index
[#] Next page
Go to full version