[En-Nut-Discussion] Ethernut with CAN-IF

Ole Reinhardt ole.reinhardt at kernelconcepts.de
Wed Jul 27 12:29:19 CEST 2005


Hello,

> I'm searching for some information how the ethernut could be extended with a new CAN device.
> I've seen already some sources sja1000.c etc. with a complete set of HW Driver functions.
> How is this connected with Nut/OS ? (Same as already existing devices NutRegister,NUTDEVICE......) 

I have added CAN support for SJA1000 devices. Especialy I have made
these extensions having our own CAN board in mind. 

http://www.kernelconcepts.de/products/mcan/

In detail you can use the SJA1000 driver like a "normal" device driver.

Initialisation phase:

u_short base_address = 0x8000;
NutRegisterDevice(&devSJA1000, base_address, 0);

The base address can be passed as parameter of NutRegisterDevice.
The interrupt can not be passed, but specified in include files (see
include/cfg/m-can.h). I don't use the configurator as it is not running
on my system, but it should be possible to set the interrupt in the
configurator as well.

Configuration example:

#define SJA_SIGNAL     sig_INTERRUPT7
#define SJA_EICR       EICRB
#define SJA_SIGNAL_BIT 7

After initialisation you can use the functions defined in 
include/dev/can_dev.h

These functions can transmit only raw frames. A frame is defined as:

struct _CANFRAME {              // todo: Implement flags
    u_long id;                  // Identifier
    u_char len;                 // Length of frame, max = 8
    u_char byte[8];
    u_char ext;                 // Boolean, extendet frame
    u_char rtr;                 // Boolean, remote transmition bit
};

The functions you can use are:

Setting an acceptance filter and acceptance mask: 

void   CAN_SetFilter(NUTDEVICE *dev, u_char *ac, u_char *am);

For more information about this filter take a look into the sja1000
datasheet.


Transmit a frame (blocking):

void   CAN_TxFrame(NUTDEVICE *dev, CANFRAME *frame);

Try to transmit a frame:

u_char CAN_TryTxFrame(NUTDEVICE *dev, CANFRAME *frame);

On success this returns 0, if there is no free transmit buffer 1.

u_char CAN_TxFree(NUTDEVICE *dev);

This returns the space available in the transmit buffer.


Same for the receiving functions:

void   CAN_RxFrame(NUTDEVICE *dev, CANFRAME *frame);
u_char CAN_TryRxFrame(NUTDEVICE *dev, CANFRAME *frame);
u_char CAN_RxAvail(NUTDEVICE *dev);

An example receive code could look like this:


while (!CAN_TryRxFrame(&devSJA1000, &frame))
{
    if (count == MAX_DEVICES) {
        error = ERR_TOO_MUCH_DEVICES;
        break;
    }
    if ((frame.rtr) || (!frame.ext)) {
        error = ERR_INVALID_FRAME;
    } else {
        source_id = (u_char) frame.id;
        dest_id = (u_char) (frame.id >> 8);
        cmd = (u_char) (frame.id >> 16);
...

An example send code could look like this:

void SendCANFrame(u_char prio, u_char source, u_char dest, u_char cmd,
u_char length, can_msg_t * message)
{
    CANFRAME frame;
    frame.id = ((u_long) (prio & 0x07) << 26) | ((u_long) cmd << 16) |
((u_long) dest << 8) | ((u_long) source);
    frame.len = length;
    frame.ext = 1;
    frame.rtr = 0;
    memcpy(frame.byte, message, length);
    CAN_TxFrame(&devSJA1000, &frame);
}

Hope this helps... If you need help with your application feel free to
contact us.

Best regards,

Ole Reinhardt

-- 
kernel concepts    Tel: +49-271-771091-14
Dreisbachstr. 24   Fax: +49-271-771091-19
D-57250 Netphen    E+ : +49-177-7420433
--





More information about the En-Nut-Discussion mailing list