Hello! We're working on bi-directional CAN gateway (basically a pass-through CAN0 <-> CAN1). Obviously we don't want to use any message filtering nor any acceptance masks. Any incoming message on CAN0 must be transmitted to CAN1 and vice versa. We're using Keil MBC1800 dev board with LPC1857. Unfortunately there is no example how to setup this chip in CAN basic mode. Reading this board I found an example how to setup CAN0_IRQHandler to accept any message. So the reception works now. But once we try to transmit the chip goes into infinite loop somewhere in the CAN stack. My understanding there should be something related to Tx states in CAN0_IRQHandler.
Here is our CAN0_IRQHandler. CAN1_IRQHandler is similar but using LPC_C_CAN1 instead of LPC_C_CAN0.
Hello ,
This CAN issue on Errata effects lpc185x/3x/2x/1x.
What about your basic CAN mode meaning?
The demo under LPCopen is a simple project that can send and receive.
From your code, do you want to use the CAN0 and CAN1 in LPC1857 to communicate?
BR
Alice
Alice,
On this MCU there is a CAN mode which, for some reasons, NXP called "Basic". UM10430 user's manual specifies: "The CAN Core can be set in Basic mode by programming the Test Register bit BASIC to one. In this mode the CAN controller runs without the Message RAM." We already figured out how it works, we can transmit and receive simultaneously from both channels. Btw, there is no example for this mode and I'm pretty sure very few people use it. Despite all transmit/receive functions being interrupt based, the performance of this mode is quite disappointing. In fact, if compared to LPC17xx series, NXP replaced the triple CAN Tx buffer of LPC1756, as example, by a single Tx buffer in LPC18xx. As a result, there is some lost of frames in both directions while operating in this mode, even under medium network load. So we cannot build a CAN gateway using this mode. Now the last hope will be to use the normal mode with Message RAM and somehow program the acceptance mask to accept any CAN id without specifying them. Do you have any idea how to do this? Thank you!
Hello,
Set the CAN message interface command mask registers to 0:
Alice,
Good advise, thank you! So we have initialized MSK1 and MSK2 with 0 values and we have our single Rx ID set to 0x1FFFFFF for both CAN0 and CAN1 controllers. In theory both controllers now must accept any frames within 0x0000001 to 0x1FFFFFF range. It works, so at this point we're getting close to our final goal. Now we have another issue while transferring data between CAN0 and CAN1. As we're working on a gateway, we're simple trying to receive a message from CAN0 channel and transmit it from CAN1 channel like this (inside the CAN0 IRQ
Chip_CCAN_GetMsgObject(LPC_C_CAN0, CCAN_MSG_IF1, can_int, &msg_buf);
Chip_CCAN_Send(LPC_C_CAN1, CCAN_MSG_IF1, false, &msg_buf);
So we inject a single message with canalizer connected to the CAN0 and we expect seeing it transmitted from CAN1.
It works BUT once the function Chip_CCAN_Send is called, it generates CAN1 IRQ (which is probably normal since we're expecting TX completed event). But somehow, in this IRQ, the previously transmitted message is detected as new RX message. And since we're using the same
Chip_CCAN_GetMsgObject(LPC_C_CAN1, CCAN_MSG_IF1, can_int, &msg_buf);
Chip_CCAN_Send(LPC_C_CAN0, CCAN_MSG_IF1, false, &msg_buf);
this will re-transmit the same message, this time through the CAN0 controller. Well, as you can imagine at the end we're going into loop where both controllers keep themselves busy by playing ping-pong with the same message (please see attached picture). As you can see, after the injection message at the line 1 the same message moves between CAN0 and CAN1.
We tried to use the Chip_CCAN_SetValidMsg(LPC_C_CAN0, CCAN_MSG_IF1, can_int, false) function to clear the message buffer but it doesn't work.
Any idea how can we prevent this behavior? Thanks again!
Hello Dim724,
Please allow me repeat your demands.
1) CAN0 received any data from other CAN nodes, then send it to CAN1, then CAN1 send to other CAN nodes.
2) CAN1 received any data from other CAN nodes, then send it to CAN0, then CAN0 send to other CAN nodes.
If I'm right, why do you need this function ? How about just use one CAN node as "gateway"?
If you must do like your that, how about set a judgment, compare the received data with last time send, if the dame, just clear, if not the same, send.
BR
Alice
Alice,
We're working on isolating gateway between 2 different CAN networks. The network A is connected to CAN0 and the network B to CAN1. The data exchange between both network is managed by LPC18xx MCU. There are some CAN ID from network A which are not allowed in network B and vice versa. It cannot be done using a single CAN channel. We're continuing to investigate but in our opinion there is untested bug inside LPCOpen CAN stack while both CAN controllers are working simultaneously. It appears that after each successful transmission the CAN(0/1) interrupt register (INT) continues to report the number of message object which caused interrupt even if there is no incoming messages. We're getting the Tx interrupt from successful transmission but there is no associate Rx interrupt (as it should be for each new Rx frame), so in reality there is no message pending. And there is no associated message data, cleaning buffers before calling Chip_CCAN_GetMsgObject() results in some random trash values. I'm pretty sure this case was never tested by people who used to work on LPCOpen CAN driver. Normally if you just send or receive frames from single (CAN0 or CAN1) controller all works fine. If you just receive frames on CAN0 and send them through CAN1 it works fine too. But if you do this simultaneously on both CAN0 and CAN1, something happens. It happens only if both controllers have possibility to send data to each other simultaneously. Ironically all this worked perfectly on LPC1756 with old CMSIS CAN drivers, no message-objects, no acceptance masks...we used these MCU for 10 years and never had any issues.
Hello Dim724,
I searched and talking with internal, yes, there isn't the case.
And you said it can work well on CMSIS CAN driver, so how about port it to LPC1857?
Following up, as we expected from Errata, the LPC1857 has some interactions with other peripherals on the same bus bridge... Disabling I2C0 communications brings back the CAN1_IRQHandler interrupts and (we're hoping) restores the normal CAN1 behavior...
But we still don't know how to transmit in basic CAN mode. Please advise!
A little update on CAN reception, in fact only 1 channel works at a time. We have both channels connected to the CAN network (quite low load) and it appears there are some issues with CAN1. Often it just does not generate the interrupt. It's not happens every time but occurs randomly after reset, very confusing. Most strange, if CAN1 gets the interrupt then CAN0 stops going into interrupt routine. And I don't see how possible both channels can interact. Also, we've noticed in the LPC18xx Errata some hardware issues with CAN1 on LPC185x, here it is:
Problem:
On the LPC185x flash-based devices, there is an issue with the C_CAN controller AHB bus address decoding that applies to both C_CAN controllers. It affects the C_CAN controllers when peripherals on the same bus are used. Writes to the ADC, DAC, I2C, and I2S peripherals can update registers in the C_CAN controller. Specifically, writes to I2C0, MCPWM, and I2S can affect C_CAN1. Writes to I2C1, DAC, ADC0, and ADC1 can affect C_CAN0. The spurious C_CAN controller writes will occur at the address offset written to the other peripherals on the same bus. For example, a write to ADC0 CR register which is at offset 0 in the ADC, will result in the same value being written to the C_CAN0 CNTL register which is at offset 0 in the C_CAN controller. Writes to the C_CAN controller will not affect other peripherals.
And as you can imagine, our dev board has the LPC1857...also this project uses I2C0 and according to UM10430 user's manual :
Remark: Use of C_CAN controller excludes operation of all other peripherals connected\to the same bus bridge. See the LPC18xx errata.
Could you please confirm if this issue is not present on lower series - LPC183x and LPC182x?
Here is again our updated CAN init function (I realized there are 2 different clock domains for CAN0 and CAN1 so there is an extra Chip_Clock_SetBaseClock(CLK_BASE_APB1, CLKIN_IDIVC, true, false) call compared to example.
Hello Alice,
The part number we will use for mass production will be LPC1837JET100, actually we do our evaluation tests on Keil MCB1800 equipped with LPC1857. The example provided with LPCOpen won’t work for our application (not 100% sure but unless you can setup the RX message objects for 100+ different CAN ID I don’t see how it could work). We eventually have tried this example, the transmission works fine but we got nothing on reception since we cannot specify all RX IDs. With CAN basic mode, the reception works fine but we cannot transmit. In my understanding, the basic mode requires completely different transmission setup (like using BUSY bit to execute transmission command) but there is no example how to do this and there is nothing in provided LPCOpen CCAN driver about this basic mode. It should be way simpler than using message objects and acceptance filters but even LPC18xx user’s manual barely mentions this basic mode so we definitely need a little help there.