Jump to content
  • 0

Zybo and PmodCAN


mbo

Question

Hello members,

I have the Zybo-Z7 Board and I want to connect it with other Zybo-Z7 Board via CAN.

The board has an integrated CAN Controller and I need following PmodCAN-Connector which has also can controller integrated.

http://store.digilentinc.com/pmod-can-can-2-0b-controller-with-integrated-transceiver/

 

Which CAN Controller shall I use and how do I make it work?

I have implemented a basic design for Zybo in Vivado and added the IP core for PmodCAN. Is something more I need?

 

Cheers,

mb

 

zybo_can.JPG

Link to comment
Share on other sites

Recommended Posts

Hi @Notarobot, @JColvin, @jpeyron,

Can is working! Also with breakout board and PmodCAN.

To my shame, I have to confess that I have used wrong d-sub cable all time.
With tips from Notarobot I tried to implement can with breakout board which worked at first moment. After that success I tried other d-sub cable for PmodCAN and now both ways are working.

Thank you guys for all your help. You're the best!

Thanks and cheers,
Mirco

Link to comment
Share on other sites

@Notarobot,

I'm sure that you know this but I thought that I'd mention for the benefit of any curious readers that while there is still a place for RS-485 it can get quite messy. One could certainly add the hardware to a Zynq board for implementing RS-485 networks but if CAN does the job and your application needs fit within it's protocol then using it has a lot of advantages. I've appreciated your comments. Thanks.

Link to comment
Share on other sites

Thank you all for help and further information,

@jpeyron do you mean design wrapper?

To answer your question about input for can I'll try to describe the structure. I use two Zybo-Z7 boards and each board has one Pmod CAN Transceiver connected to Pmod port JE.
The Pmod CAN Transceiver of both boards are connected together via d-sub 9-pin cable. One board has Tx.c example source of Pmod CAN implemented and other board has Rx.c source implemented.

@Notarobot I understand that the way I've chosen may not be the easiest and I am thankful for your advices. The breakout-board you presented has an onboard can transceiver and is I think not different to Pmod CAN from Digilent where I also have the option simply to connect wires. Both ways should work. Thank you

My goal is that two boards are connected to each other via two CAN lines and in case of a failure of one line the connection between these boards is switched automatically to the other CAN line. But this one is far away and first I need CAN to get work correctly by sending messages from one board to other board.

Thanks,
Mirco

design_wrapper.txt

Link to comment
Share on other sites

In addition, I have another question...
When I use the source files Tx.c and Rx.c from PmodCAN source directory is there any way I can find out how to set PmodCAN to specific status?

In Tx.c and Rx.c following function is used several times to check current status of CAN but at beginning of Rx.c the status is not correct and I want to set it by myself.

status = CAN_ReadStatus(&myDevice);

Does anyone know which registers I have to set at specific value to get specific status?

Thanks,
Mirco

Link to comment
Share on other sites

Hi @mbo,

What sort of status were you hoping to read? Based on datasheet for the CAN device in the Pmod CAN, there a few registers that show status (4-2, 4-11, 4-35) but they all tend to be single bits of information. There is also a Read Status instruction which is what that function you listed is, but it returns specific bits in certain registers (the bits are detailed on page 60, the registers referenced are on page 52 and page 32).

Thanks,
JColvin

Link to comment
Share on other sites

Hi @JColvin

I monitored the loopback demo and in the receiving part of that demo the ReadStatus-function is returning value 9 as status. With that status the switch-case statement is switching between receiving message from buffer 0 or 1. But if status is not 9 an error is returned by switch-case statement.

Next step was to use Rx.c example code which starts at mentioned ReadStatus-function and switch-case statement afterwards. To get it work the ReadStatus-function needs to return 9 as status.

I will take a look at the pages you mentioned.

Thanks, Mirco

Link to comment
Share on other sites

Hi @Notarobot,
 

On 9.3.2018 at 1:58 PM, Notarobot said:

You can find JF port configuration searching FPGA forum, check Xilinx provided examples of the driver and you are good to go. You can start with the Xilinx source code but change loopback mode to normal in the configuration call.

I have searched for JF port configuration in Digilent and Xilinx forum but found nothing. Where can I find it?

Thanks,
Mirco

Link to comment
Share on other sites

Dear @mbo

If you trace Zybo Pmod JF schematic diagram you will find that

- pin JF2 (MIO-10 = Rx in) should be connected to CAN Rx on the PHY breakout board SN65HVD230 or similar,

- pin JF3 (MIO-11 = Tx out) should be connected to CAN Tx on the PHY breakout board.

- pin JF5 and JF6 - GND and 3.3V power.

Please, note that the above mentioned breakout board is does not include CAN controller, CAN controller is implemented in ARM on Zynq. I am not sure that you can use Pmod-CAN is such configuration. I don't have time to investigate this.

My recommendation is to get USB-CAN dongle and use PC for monitoring the CANetwork. It will help you to debug and configure your nodes and messages.

Link to comment
Share on other sites

@zygot

Initially, I tried CAN as a replacement for RS485 which is not supported on Zynq, and found that it's not difficult to implement. I think I showed the way, relevant C-code anyone can find in Xilinx library embeddedsw\XilinxProcessorIPLib\drivers\canps\ .

My response to this post was motivated by troubles understanding the way @mbo tried to implement CAN on Zybo. I think it's very awkward approach and I am not sure that it can be successfully accomplished. I hope to spare him from unnecessary suffering.

 

Link to comment
Share on other sites

Hi @JColvin, @jpeyron, @artvvb,

How can I check the Acknowledge Bit to make sure transmission of message was successful?

I know there is this check but it wont work when PmodCAN on receiver board is disconnected.

 

CAN_SendMessage(&pmod, TxMessage, CAN_Tx0);
CAN_ModifyReg(&pmod, CAN_CANINTF_REG_ADDR, CAN_CANINTF_TX0IF_MASK, 0);

do {
  status = CAN_ReadStatus(&pmod);
} while ((status & CAN_STATUS_TX0IF_MASK) != 0);


Thanks,
Mirco

Link to comment
Share on other sites

Hi @mbo,

Are you using the most up to date Pmod CAN ip core? We recently connected the interrupt to the IP Core. For checking status, does the status check exits the loop, or if it loops forever (as expected)? I would also suggest looking at section 3.6.3 of the MCP25625 datasheet. I reached out to a co-worker about your thread and they suggested that If you are polling, rather than using the full interrupt mode that you have two approaches.

First if the loop never terminates, you can add a timeout clause, ie if (timeoutcount++>=timeoutperiod) break;

Second, if the loop exits prematurely, you can add additional status register reads as required, We are not sure what this would consist of, but you'd want to make sure that the flag you are looking for in the TX0 interrupt flag reg is the correct one for all situations. 

The other option if you would like to eliminate polling would be to incorporating the ISR process.
 

thank you,

Jon

 

 

 

 

Link to comment
Share on other sites

Hi @jpeyron,

I found out that I am not using the latest release of Pmod CAN ip core. First, thank you for that information.

Lets say we have following scenario. Board A wants to send a message to Board B. On Board A Pmod CAN is connected but on Board B not.
So Board A tries to send a message but it will never be received by Board B. 

The shown code snipped for checking status exists immediately the loop but message has never been received by Board B or transmitted successfully.


The check of an additional status register you mentioned is also the approach of my choice. So am I correct that I need to extend the status check in mentioned loop above? For example like...

do {
  status = CAN_ReadStatus(&pmod);
} while ((status & CAN_STATUS_TX0IF_MASK) != 0 && (status & OTHER_REG_MASK) != 0);


What do you mean with full interrupt mode? You mean ISR process?

Thank you for your advices and I will try to get further information from other registers.

Thanks,
Mirco

Link to comment
Share on other sites

Hi @mbo,

Sorry if my post was confusing the full interrupt mode was referring to the ISR process.

Your do while loop will no work correctly because it can only check if a different bit of the status register is also 1
if you need to test if a single bit in a register other than status is 1. Some pseudo code for the do while:
do {
  status = CAN_ReadStatus(&pmod);
  other_reg_value = CAN_ReadReg(&pmod, OTHER_REG_ADDR);
} while ((status & CAN_STATUS_TX0IF_MASK) != 0 && (other_reg_value & OTHERREG_1BIT_MASK) != 0);

One of my co-worker also suggested that often its safer to do a multi-byte SPI transaction than to do multiple single-reg reads, assuming that you don't need to go as fast as possible. Usually this ensures that nothing has changed between when the different bytes are read.

thank you,

Jon

 

 

Link to comment
Share on other sites

Hi @jpeyron,

thank you for that advice. Is there a example how to use function CAN_ReadReg, because there are some parameter I do not understand how to use?

 

void CAN_ReadReg(PmodCAN *InstancePtr, u8 reg, u8 *data, u32 nData) {
   u8 buf[nData + 2];
   u32 i;
   buf[0] = CAN_READ_REG_CMD;
   buf[1] = reg;
   XSpi_Transfer(&InstancePtr->CANSpi, buf, buf, nData + 2);
   for (i = 0; i < nData; i++)
      data[i] = buf[nData + 2];
}


What is the best way to do a multi-byte SPI transaction?

Thanks,
Mirco

Link to comment
Share on other sites

Hi @mbo,

Here is what xspi_transfer function takes for input:

int XSpi_Transfer(XSpi *InstancePtr, u8 *SendBufPtr, u8 *RecvBufPtr, unsigned int ByteCount)

The CAN_ReadReg function does read multi-bytes.  We were just making sure that you did not alter the CAN_ReadReg to only read one byte at a time. Are you using this function to get your data?

thank you,

Jon

 

 

 

Link to comment
Share on other sites

Hi Gents,

allow me to ask you a question about same subject. I have also discussed it with @jpeyron and @mbo sent me some files.

I am trying to stablish a CAN bus network with a Ultrazed (ultrascale+) board with a axi_quad_spi interface and a Digilent PMOD CAN breakout board.

Reason I am not using PMODCAN is that I had a bad time repackaging it to UltraScale+.

 when I run the loopback.c test, apparently it goes well - it manages to send and fetches the message pre-define. When I remove the breakout board, it goes on "waiting to send"; so I believe it is working.

However, when I run either the RX or TX, having and Arduino (with CAN bus shield) at the other end, I do not manage to stablish the link.

For instance, for the TX, it stucks on the "waiting to send"....(Arduino is then configured as receive_check) - nothing gets through.

(I am using a twisted pair cable for CANH and CANL)

I would appreciate if you could shed some light on this.

Best regards,

 

 

 

Link to comment
Share on other sites

@Notarobot

Thank you for lucid commentary.  Can can! (Yes, that was a pun) Can is widely used in automotive and industrial applications, has been around for quite some time and has a robust protocol. Hopefully, you've got more people interested in experimenting with Canning and learning about a useful interface.

Link to comment
Share on other sites

@zygot

Thank for the advice, I did check the schematic when implemented CAN on Zynq and configuring CAN on MIO 10,11 for using Zybo port JF. You are correct, a PHY = CAN_breakout_board is needed for implementing differential signaling. This is the only purpose of PHY in this particular case.

Anyway it was done a while ago and CAN delivered expected results. CAN is fast, low latency communication allowing to put many devices on the same pair of wires. I can add or remove any one without disrupting the network.

Link to comment
Share on other sites

Hi @zygot

Yes, it requires MIO to be configured, for example, like this

image.thumb.png.4786e6dec891940a7755db6490445a33.png

On Zybo these MIO are wired to Pmod JF. You are also correct that PHY = breakout board is needed to implement differential signaling.

I've done this on Zybo and on other Zynq board and happy with results. CAN is more complicated but worth the effort. It is fast, reliable, only two wires, and you can put 64 devices on these two wires and since there is no master node you can add/remove any device easily.

Link to comment
Share on other sites

@Notarobot,

Yes the Zynq has CAN controllers but unless they are connected to the MIO and available on an board connector or through the EMIO that functionality is unavailable. Check the schematic for your board.

My understanding of the Zynq CAN is that regardless of whether or not the interface goes though the PS IO or the PL IO you still need a PHY to connect it to external networks. Can (no pun intended) anyone confirm this?

Link to comment
Share on other sites

Hello @mbo

I am not sure that you are aware that ARM processors on Zynq have two CAN 2.A (2.0B) controllers embedded on the chip. Unless some specific requirements, logic of adding an external controller Pmod-CAN is difficult understand. Pmod-CAN is well suited for boards without Zynq (ARM) capabilities.

The only piece of hardware needed to make ARM CAN to work over a pair of twisted wires is a breakout board, for example, like this connected to the Zybo Pmod port JF. This breakout board is required to implement physical CAN interface.

You can find JF port configuration searching FPGA forum, check Xilinx provided examples of the driver and you are good to go. You can start with the Xilinx source code but change loopback mode to normal in the configuration call.

I would also recommend to have include PC in the network for debugging purposes. For the intreface I would recommend USB-CAN adapter from this open source project. It works with open source software so that you can start with very low monetary investment into your project.

Good luck!

Link to comment
Share on other sites

Hi @jpeyron,

thank you for the hint of updated board files. 

I am using Pmod port JE on my Zybo-Z7 and the port assignment in my constraint file is following:

##Pmod Header JE             
set_property -dict { PACKAGE_PIN V12   IOSTANDARD LVCMOS33 } [get_ports { pmod_out_pin1_io }]; #IO_L4P_T0_34 Sch=je[1]						 
set_property -dict { PACKAGE_PIN W16   IOSTANDARD LVCMOS33 } [get_ports { pmod_out_pin2_io  }]; #IO_L18N_T2_34 Sch=je[2]                     
set_property -dict { PACKAGE_PIN J15   IOSTANDARD LVCMOS33 } [get_ports { pmod_out_pin3_io  }]; #IO_25_35 Sch=je[3]                          
set_property -dict { PACKAGE_PIN H15   IOSTANDARD LVCMOS33 } [get_ports { pmod_out_pin4_io  }]; #IO_L19P_T3_35 Sch=je[4]                     
set_property -dict { PACKAGE_PIN V13   IOSTANDARD LVCMOS33 } [get_ports { pmod_out_pin7_io  }]; #IO_L3N_T0_DQS_34 Sch=je[7]                  
set_property -dict { PACKAGE_PIN U17   IOSTANDARD LVCMOS33 } [get_ports { pmod_out_pin8_io  }]; #IO_L9N_T1_DQS_34 Sch=je[8]                  
set_property -dict { PACKAGE_PIN T17   IOSTANDARD LVCMOS33 } [get_ports { pmod_out_pin9_io  }]; #IO_L20P_T3_34 Sch=je[9]                     
set_property -dict { PACKAGE_PIN Y17   IOSTANDARD LVCMOS33 } [get_ports { pmod_out_pin10_io  }]; #IO_L7N_T1_34 Sch=je[10] 

Thanks,

Mirco

Link to comment
Share on other sites

Archived

This topic is now archived and is closed to further replies.

×
×
  • Create New...