- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi, I know that this has been discussed in some old threats but I could not get some real help from those. I want to use the CAN Protocoll Controller in my NIOSII system designed with QSYS.
I took a look at the two bus specifications and came up with this wrapper:
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
entity OC_Can is
port (
avs_s0_address : in std_logic_vector(7 downto 0) := (others => '0'); -- s0.address
avs_s0_read : in std_logic := '0'; -- .read
avs_s0_readdata : out std_logic_vector(31 downto 0); -- .readdata
avs_s0_write : in std_logic := '0'; -- .write
avs_s0_writedata : in std_logic_vector(31 downto 0) := (others => '0'); -- .writedata
avs_s0_readdatavalid : out std_logic; -- .readdatavalid
avs_s0_waitrequest : out std_logic := '0';
clk : in std_logic := '0'; -- clock.clk
reset : in std_logic := '0'; -- reset.reset
avs_irq_n : out std_logic; -- irq0.irq
clk_i : IN STD_LOGIC;
rx_i : IN STD_LOGIC;
tx_o : OUT STD_LOGIC;
bus_off_on : OUT STD_LOGIC;
irq_on : OUT STD_LOGIC;
clkout_o : OUT STD_LOGIC
);
end entity OC_Can;
architecture rtl of OC_Can is
COMPONENT can_top
GENERIC ( Tp : INTEGER := 1 );
PORT
(
wb_clk_i : IN STD_LOGIC;
wb_rst_i : IN STD_LOGIC;
wb_dat_i : IN STD_LOGIC_VECTOR(7 DOWNTO 0);
wb_dat_o : OUT STD_LOGIC_VECTOR(7 DOWNTO 0);
wb_cyc_i : IN STD_LOGIC;
wb_stb_i : IN STD_LOGIC;
wb_we_i : IN STD_LOGIC;
wb_adr_i : IN STD_LOGIC_VECTOR(7 DOWNTO 0);
wb_ack_o : OUT STD_LOGIC;
clk_i : IN STD_LOGIC;
rx_i : IN STD_LOGIC;
tx_o : OUT STD_LOGIC;
bus_off_on : OUT STD_LOGIC;
irq_on : OUT STD_LOGIC;
clkout_o : OUT STD_LOGIC
);
END COMPONENT;
signal wb_readdata : STD_LOGIC_VECTOR(7 downto 0);
signal wb_writedata : STD_LOGIC_VECTOR(7 downto 0);
signal wb_stb : STD_LOGIC;
signal wb_ack : STD_LOGIC;
signal wb_cyc : STD_LOGIC;
signal avs_irq : STD_LOGIC;
signal av_readdatavalid : STD_LOGIC;
begin
can_inst : can_top
PORT MAP
(
wb_clk_i => clk,
wb_rst_i => reset,
wb_dat_i => wb_writedata, --write data
wb_dat_o => wb_readdata, --read data
wb_cyc_i => wb_cyc, --when asserted indicates that valid bus cycle is in progress
wb_stb_i => wb_stb, --when asserted indicates that the slave is selected, slave should not respond till stb_i is asserted
wb_we_i => avs_s0_write, --deasserted during read cycles, asserted during write cycles
wb_adr_i => avs_s0_address,
wb_ack_o => wb_ack, --when asserted indicates termination of normal bus cycle
clk_i => clk_i,
rx_i => rx_i,
tx_o => tx_o,
bus_off_on => bus_off_on,
irq_on => avs_irq,
clkout_o => clkout_o
);
wb_stb <= avs_s0_read OR avs_s0_write;
wb_cyc <= avs_s0_read OR avs_s0_write;
avs_s0_waitrequest <= not wb_ack;
avs_s0_readdatavalid <= wb_ack;
--extend 8bits coming from can core to full 32 bits for avalon
avs_s0_readdata <= "000000000000000000000000" & wb_readdata;
--map lowest 8bits coming from avalon to writedata of can core
wb_writedata <= avs_s0_writedata(7 downto 0);
--avs_s0_readdatavalid <= '0';
avs_irq_n <= not avs_irq;;
end architecture rtl; -- of OC_Can
As I can not simulate it for mixed signal reasons, I tried to access the CAN Core with the following very basic programm from the NIOS:
# include <stdio.h># include <io.h># include "system.h"# include "sys/alt_stdio.h"
int main()
{
unsigned int temp;
printf("Hello from Nios II!\n");
temp = IORD_32DIRECT(OC_CAN_0_BASE,4);
printf("%u",temp);
while(1);
return 0;
}
What I'm experiencing is that the CPU is getting stuck at the IORD_32DIRECT access. Can anyone see where the problem might be hidden? As dev board I'm using a de0-nano. Did anyone get this CAN Controller running on a cyclone IV device? Thanks in advance!
- Tags:
- qsys
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I used the OC CAN controller on CIII and this is my wrapper (Verilog).
As you can see, I don't use readdatavalid signal.
module CAN_av_wrapper(
//Avalon common
input av_clk,
input av_reset,
//Avalon control port
input av_address,
input av_chipselect,
input av_write,
input av_read,
input av_writedata,
output av_readdata,
input av_byteenable,
output av_waitrequest_n,
// CAN interface
input CAN_clk,
input CAN_reset,
input CAN_rx,
output CAN_tx,
output CAN_bus_off,
output CAN_irq,
output CAN_clkout
);
wire wb_ack_o;
assign av_waitrequest_n = wb_ack_o;
wire wb_cs_i;
assign wb_cs_i = (av_byteenable == 4'b0001);
assign av_readdata = 24'hz;
can_top wishbone_can_inst
(
.wb_clk_i(av_clk),
.wb_rst_i(av_reset | CAN_reset),
.wb_dat_i(av_writedata),
.wb_dat_o(av_readdata),
.wb_cyc_i(av_write | av_read),
.wb_stb_i(av_chipselect & (av_write | av_read)),
.wb_we_i(av_write & ~av_read),
.wb_adr_i({2'b0, av_address}),
.wb_ack_o(wb_ack_o),
.clk_i(CAN_clk),
.rx_i(CAN_rx),
.tx_o(CAN_tx),
.bus_off_on(CAN_bus_off),
.irq_on(CAN_irq),
.clkout_o(CAN_clkout)
);
endmodule
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Thanks a lot for the help! There's some communication going on now! You pointed out some major flaws in my wrapper. The chipselect could actually just be skipped, as it suggested in the avalon specification? But I don't understand the addressing .wb_adr_i({2'b0, av_address})
printf("Goint to reset mode \n");
IOWR_32DIRECT(OC_CAN_VERILOG_WRAP_0_BASE,0,1);
for(i = 4; i < 120; i += 4) {
temp = IORD_32DIRECT(OC_CAN_VERILOG_WRAP_0_BASE,i);
printf("%u: R %u ",i/4,temp);
IOWR_32DIRECT(OC_CAN_VERILOG_WRAP_0_BASE,i,255);
temp = IORD_32DIRECT(OC_CAN_VERILOG_WRAP_0_BASE,i);
printf("W+R255 %u ", temp);
printf("\n");
}
it outputs the following: --- Quote Start --- Goint to reset mode 0: R 1 W+R255 0 1: R 0 W+R255 0 2: R 0 W+R255 0 3: R 0 W+R255 0 4: R 0 W+R255 0 5: R 0 W+R255 0 6: R 0 W+R255 0 7: R 0 W+R255 0 8: R 4 W+R255 4 9: R 4 W+R255 4 10: R 4 W+R255 4 11: R 4 W+R255 4 12: R 0 W+R255 0 13: R 0 W+R255 0 14: R 0 W+R255 0 15: R 0 W+R255 0 16: R 255 W+R255 0 17: R 0 W+R255 0 18: R 0 W+R255 0 19: R 0 W+R255 0 20: R 0 W+R255 0 21: R 0 W+R255 0 22: R 0 W+R255 0 23: R 0 W+R255 0 24: R 255 W+R255 255 25: R 255 W+R255 255 26: R 255 W+R255 255 27: R 255 W+R255 255 28: R 255 W+R255 255 29: R 255 W+R255 255 --- Quote End --- The avalon clock is of course connected to the nios clock (100MHz), the external clock to a 10MHz clock, reset to the global reset and the other exports to pins of the IO header of the de0-nano - no CAN Transceiver yet. But the reading/writing of the registers should work. Something is going wrong somewhere... What were your experiences with the controller in general. Is it working reliably and thus usable? Thanks again!
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
It has been quite a long time since I worked with this CAN controller, so I don't remember everything exactly.
Anyway, I try to recollect here some information. .wb_adr_i({2'b0, av_address[7:2]}) As you correctly pointed out, this is because Avalon is 32bit wide but it uses byte addressing. In a perfect world I've used the CAN controller with byte accesses (i.e. IORD_8DIRECT,IOWR_8DIRECT). Unfortunately Avalon fabric generates 4 8bit reads even with IORD_8DIRECT, because it requires a 32bit complete access to be performed: this is generally invisible to the application, since only the requested byte is returned by IORD_8DIRECT, but it makes a mess with devices involving fifo register which automatically pop data at every read access, and this CAN controller is one of them. That's why I remapped CAN register in order to access them as if they were 32bit wide. Please note that you must feed register addresses with multiple of 4, and discard higher 24 bits: data = IORD(OC_CAN_VERILOG_WRAP_0_BASE, reg*4) & 0xFF; IOWR(OC_CAN_VERILOG_WRAP_0_BASE, reg*4, data); The CAN controller works. I had some problems with FIFOs because of what I said above, but then it worked fine. I suggest you use 24 or 40MHz for CAN clock; IIRC with 10MHz you can't achieve all standard CAN baudrates- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I'm new with the use of IP cores and this forum has been helpful to use the CAN controller from OpenCores. At the moment I've added the component to avalon bus, following the Wrapper, in a project with the DE0-nano development board, but I'm still working with the software interface.
The documentation of the opencores project indicates that CAN controller description is compatible with the SJA1000 controller, but want to know if the registers address are identical to those of SJA1000 controller?, there is a problem when accessing registers? or just the need of addresses multipled by 4? thanks and I hope early reply.- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi,
for you and the people of the future here the wrapper I used:module OC_Can_av_wrapper(
//Avalon common
input av_clk,
input av_reset,
//Avalon control port
input av_address,
input av_chipselect,
input av_write,
input av_read,
input av_writedata,
output av_readdata,
input av_byteenable,
output av_waitrequest_n,
// CAN interface
input CAN_clk,
input CAN_reset,
input CAN_rx,
output CAN_tx,
output CAN_bus_off,
output CAN_irq,
output CAN_clkout
);
wire wb_ack_o;
assign av_waitrequest_n = wb_ack_o;
assign av_readdata = 24'hz;
can_top wishbone_can_inst
(
.wb_clk_i(av_clk),
.wb_rst_i(av_reset | CAN_reset),
.wb_dat_i(av_writedata),
.wb_dat_o(av_readdata),
.wb_cyc_i(av_write | av_read),
.wb_stb_i(av_chipselect & (av_write | av_read)),
.wb_we_i(av_write & ~av_read),
.wb_adr_i({av_address}),
.wb_ack_o(wb_ack_o),
.clk_i(CAN_clk),
.rx_i(CAN_rx),
.tx_o(CAN_tx),
.bus_off_on(CAN_bus_off),
.irq_on(CAN_irq),
.clkout_o(CAN_clkout)
);
endmodule
Using this wrapper, the addresses should be according to the data sheet. Here a little snippet I used to verify the correct behaviour: #include <stdio.h>
# include <io.h>
# include "system.h"
# include "sys/alt_stdio.h"
int main()
{
unsigned int temp;
int i = 0;
printf("Control Register \n");
temp = IORD(OC_CAN_VERILOG_WRAP_0_BASE,0x0000);
printf("%u : R %u \n",i,temp);
printf("Goint to OP mode \n");
IOWR_32DIRECT(OC_CAN_VERILOG_WRAP_0_BASE,0,32);
temp = IORD_32DIRECT(OC_CAN_VERILOG_WRAP_0_BASE,0x0000);
printf("%u : R %u \n",i,temp);
/*printf("Goint to reset mode \n");
IOWR_32DIRECT(OC_CAN_VERILOG_WRAP_0_BASE,0,32);
temp = IORD_32DIRECT(OC_CAN_VERILOG_WRAP_0_BASE,0x0000);
printf("%u : R %u \n",i,temp); */
printf("Double check \n");
temp = IORD(OC_CAN_VERILOG_WRAP_0_BASE,0x0000);
printf("%u : R %u \n",i,temp);
printf("Read Clock Divider Reg \n");
i=31;
temp = IORD(OC_CAN_VERILOG_WRAP_0_BASE,31);
printf("%u : R %u \n",i,temp);
printf("Set it to extended mode \n");
IOWR(OC_CAN_VERILOG_WRAP_0_BASE,31,128);
temp = IORD(OC_CAN_VERILOG_WRAP_0_BASE,31);
printf("%u : R %u \n",i,temp);
printf("And back \n");
IOWR(OC_CAN_VERILOG_WRAP_0_BASE,31,0);
temp = IORD(OC_CAN_VERILOG_WRAP_0_BASE,31);
printf("%u : R %u \n",i,temp);
for(i = 1; i < 32; i++) {
IOWR_32DIRECT(OC_CAN_VERILOG_WRAP_0_BASE,i*4,0);
temp = IORD_32DIRECT(OC_CAN_VERILOG_WRAP_0_BASE,i*4);
printf("%u: R %u \n",i,temp);
}
printf("Goint to reset mode \n");
IOWR_32DIRECT(OC_CAN_VERILOG_WRAP_0_BASE,0,33);
temp = IORD_32DIRECT(OC_CAN_VERILOG_WRAP_0_BASE,0x0000);
printf("%u : R %u \n",i,temp);
printf("Double check \n");
temp = IORD(OC_CAN_VERILOG_WRAP_0_BASE,0x0000);
for(i = 1; i < 32; i++) {
IOWR_32DIRECT(OC_CAN_VERILOG_WRAP_0_BASE,i*4,0);
temp = IORD_32DIRECT(OC_CAN_VERILOG_WRAP_0_BASE,i*4);
printf("%u: R %u \n",i,temp);
}
printf("\nDONE");
return 0;
}
I mixed a bit the use of IO** and IO**_32DIRECT. This shouldn't be a problem as long as you are aware of the difference (see this thread (http://www.alteraforum.com/forum/showthread.php?t=32282)). The activation of the reset mode is commented to test if the core can just be set to extended mode if in reset mode (see data sheet (http://www.nxp.com/documents/data_sheet/sja1000.pdf) at page 56). I hope this helps!
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Thanks a lot for the help! I will test on DE0-nano.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi, I need help, I'm testing the CAN controller with a DE0-nano board and I used the wrapper and it works fine, I have made the software test and it responds, but when I try to send a message, the can controller generates errors (reflected in the status reg). I'm using a 25Mhz can clock and I don't know what else should I test, can you help me, I send the code used in software to test and send a message.
main program code:
printf("Start CAN operation:\n");
unsigned int temp;
i=0;
read_status();
reset_mode();
read_status();
op_mode();
read_status();
can_init(Basic_can , 0x00FF, 0x00FF, Fosc_14);
read_status();
can_tx= 0x0F;
can_tx= 0x0E;
can_tx= 0x0D;
can_tx= 0x0C;
can_tx= 0x0B;
can_tx= 0x0A;
can_tx= 0xF1;
can_tx= 0xF7;
reset_mode();
read_regs_can();
op_mode();
read_regs_can();
send_msg(can_tx, 0x0001, 0x08, 0);
read_regs_can();
read_status();
while(1)
{}
in a header file (M_can.h) I define:# define Basic_can 0x00# define Peli_can 0x80# define Fosc_14 0x06# define Bus_Tx_libre 0x0C in a source file (M_can.c) I define the functions: # include"M_can.h"
# include <stdio.h># include <string.h>
void reset_mode()
{
unsigned char temp;
printf("Reset mode\n");
temp = IORD_32DIRECT(CAN_CONTROLLER_0_BASE,0x0000);
printf("%u : Reg %X h \n",0,temp);
printf("%u : Reg %u decimal \n",0,temp);
IOWR_32DIRECT(CAN_CONTROLLER_0_BASE,0, (temp | 0x01));
temp = IORD_32DIRECT(CAN_CONTROLLER_0_BASE,0x0000);
printf("%u : Reg %X h \n",0,temp);
printf("%u : Reg %u decimal \n",0,temp);
}
void op_mode()
{
unsigned char temp;
printf("OP mode:\n");
temp = IORD_32DIRECT(CAN_CONTROLLER_0_BASE,0x0000);
printf("%u : Reg %X h \n",0,temp);
printf("%u : Reg %u decimal \n",0,temp);
IOWR_32DIRECT(CAN_CONTROLLER_0_BASE,0, (0xFE & temp));
temp = IORD_32DIRECT(CAN_CONTROLLER_0_BASE,0x0000);
printf("%u : Reg %X h \n",0,temp);
printf("%u : Reg %u decimal \n",0,temp);
}
unsigned char read_status()
{
unsigned char status;
printf("reading status \n");
status = IORD(CAN_CONTROLLER_0_BASE,2);
printf("Now %u : Reg %X h \n",2,status);
printf("%u : Reg %u decimal \n",2,status);
return(status);
}
void read_regs_can(void)
{
int i;
unsigned char temp;
for(i = 0; i < 32; i++)
{
temp = IORD_32DIRECT(CAN_CONTROLLER_0_BASE,i*4);
printf("Reg %u : %X h ",i,temp);
printf("Reg %u: %u decimal \n",i,temp);
}
}
void send_msg(unsigned char *vector, unsigned int id, unsigned char long_bytes_msg, unsigned char rtr)
{
unsigned char filtro_h, filtro_l, status;
int i;
printf("sending msg");
status=0x00;
filtro_h = (id >> 3);
filtro_l = (id << 5);
if (rtr ==1)
filtro_l = filtro_l | 0x10;
if(long_bytes_msg > 0x08)
long_bytes_msg = 0x08;
filtro_l = filtro_l | long_bytes_msg;
IOWR(CAN_CONTROLLER_0_BASE,10,filtro_h);
IOWR(CAN_CONTROLLER_0_BASE,11,filtro_l);
for(i=0 ; i<long_bytes_msg ; i++)
{
IOWR(CAN_CONTROLLER_0_BASE,(12+i),*vector);
vector = vector+1;
}
// sending request
IOWR(CAN_CONTROLLER_0_BASE,1,0x01);
while(status != Bus_Tx_free)
{
status = read_status();
status = status & Bus_Tx_libre;
}
printf("Msg Sended \n");
}
void can_init(unsigned char mode, unsigned int masc, unsigned int filtro, unsigned char fout)
{
printf("init can \n");
unsigned char temp;
reset_mode();
temp = modo | fout;
temp = temp | 0x60;
IOWR(CAN_CONTROLLER_0_BASE,31,temp);
IOWR(CAN_CONTROLLER_0_BASE,4,filtro);
config_timing_reg(1000000, SJW_1, SAM_1);
config_output(normal_mode, push_pull);
op_mode();
printf("end init \n");
}
void config_timing_reg(float frec_CAN, unsigned char SJW, unsigned char muest)
{
float BRP;
unsigned int BRP_int;
unsigned char temp, temp2;
BRP = (( (F_crystal * T_crystal) / (2.0) ) - 1.0);
BRP_int = BRP; // casting a int.
temp = BRP_int; // casting a char.
temp = SJW | temp;
IOWR(CAN_CONTROLLER_0_BASE,6,temp);
temp2 = muest | seg1 | seg2;
IOWR(CAN_CONTROLLER_0_BASE,7,temp2);
}
void config_output(unsigned char mode, unsigned char output_pol)
{
unsigned char temp;
temp= mode | output_pol;
IOWR(CAN_CONTROLLER_0_BASE,8,temp);
}
when I test the main program, the CAN controller send bits in the Tx pin, but then the Bus_off pin changes and in the status reg I see the 0xD4h errors, I don't know if maybe the process of sending the message is right. thanks.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I don't have the time to carefully analyze your code now.
Just a few question which could help to identify your problem: - do you connect to a CAN device on the other side or do you test the core without bus connection? - are timing registers correctly configured for the bus baudrate? IIRC 25MHz clock frequency is generally not used for CAN since you can't achieve all standard baudrates; if you can have it, use 24MHZ or 48MHz. - Do you see any waveform on bus lines when you call the send_msg the first time?- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi, acording to questions, fistly, I was testing the can core without an external can device, and when I read the status reg, after a transmission request, I find a 0xD4 wich means bus_off, error, Tx in progress and Tx buffer released. Then I use a MCP2551 can transceiver and a external can device, another MCP2551 and a PIC30F4013 to test it. with the external hardware, I send again a message and find in the status reg again a 0xD4, so I don't know what is happend. I have tested the status reg in every step of initialization but when I send the comand for transmition request the status changes from 0x0C (Tx complete and Tx buffer released) to 0xD4, in this process to changes I see that the can controller send a package in the Tx pin, but with an osciloscope it seem to be the error frame.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
--- Quote Start --- in this process to changes I see that the can controller send a package in the Tx pin, but with an osciloscope it seem to be the error frame. --- Quote End --- What do you mean with error frame? On tx pin you must see the frame you write in the tx buffer, namely can_tx[] values coded according to CAN protocol. An error frame would be possibly transmitted back from the can slave. A few stupid questions: Did you check with the oscilloscope if the baudrate you see on tx pin is correct? Is PIC30F4013 CAN interface set to the same baudrate? Did you try the rx as well? I mean transmit from the PIC30F and check if you receive anything on the DE2-nano
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page