📄 sja1000.c
字号:
/********************************************************* * * * Advanced Ring Buffer Redundant Application for CAN * * * ********************************************************* * ArbraCan.c * ********************************************************* * This program is free software; you can redistribute * * it and/or modify it under the terms of the GNU General* * Public License as published by the Free Software * * Foundation; either version 2 of the License, or (at * * your option) any later version. * * * * This program is distributed in the hope that it will * * be useful, but WITHOUT ANY WARRANTY; without even the * * implied warranty of MERCHANTABILITY or FITNESS FOR A * * PARTICULAR PURPOSE. See the GNU General Public * * License for more details. * * * * You should have received a copy of the GNU General * * Public License along with this program; if not, write * * to The Free Software Foundation, Inc. * * 675 Mass Ave * * Cambridge * * MA 02139 * * USA. * ********************************************************* * * * Author: Edouard TISSERANT * * Contact: edouard.tisserant@esstin.u-nancy.fr * * Version: 1.0 * * Modification date: * * Description: * *-------------------------------------------------------* * Hardware dependant function for SJA1000 philips CAN * * controler. For use with ArbraCan * * * *********************************************************/#include <linux/version.h>#include <linux/kernel.h>#include <linux/ioport.h>#include <linux/pci.h>#include <asm/io.h>#include <can.h>#include <sja1000.h>#include <arbraCan.h>//#define DEBUG#ifdef DEBUGstatic char can_debug = 1;#define MSGK(string, args...) printk("%s:%d:",__FILE__,__LINE__);printk(string, ##args)#else#define MSGK(string, args...)#endifunsigned int PLX_9050_BASE;unsigned int SJA_BASE[CAN_BUS_COUNT];// initialisation de la carte PCI 7841 qui contient le SJA1000int initBoardSJA1000(struct pci_dev *dev){#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,13) PLX_9050_BASE = dev->resource[1].start & PCI_BASE_ADDRESS_IO_MASK;#else PLX_9050_BASE = dev->base_address[1] & PCI_BASE_ADDRESS_IO_MASK;#endif if(check_region(PLX_9050_BASE, 80)) { MSGK("Check region failure\n"); return EBUSY; }#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,13) SJA_BASE[0] = dev->resource[2].start & PCI_BASE_ADDRESS_IO_MASK;#else SJA_BASE[0] = dev->base_address[2] & PCI_BASE_ADDRESS_IO_MASK;#endif SJA_BASE[1] = SJA_BASE[0] + 128; if(check_region(SJA_BASE[0], 32)) { MSGK("Check region failure\n"); return EBUSY; } if(check_region(SJA_BASE[1], 32)) { MSGK("Check region failure\n"); return EBUSY; } request_region(PLX_9050_BASE, 80, "PCI7841/PLX9050"); request_region(SJA_BASE[0], 32, "PCI7841/SJA1000(1)"); request_region(SJA_BASE[1], 32, "PCI7841/SJA1000(2)"); return 0;}void closeBoardSJA1000(){ release_region(PLX_9050_BASE, 80); release_region(SJA_BASE[0], 32); release_region(SJA_BASE[1], 32);}// Initialisation du SJA10000void initSJA1000( int bus_nb, // numero du port unsigned char acc_code, // acceptance code unsigned char acc_mask, // acceptance mask int overrun_it, // activation IT overrun int error_it, // activation IT error int transmit_it, // activation IT transmit int receive_it, // activation IT receive int rate, int silent){ unsigned char it; unsigned int SJA = SJA_BASE[bus_nb]; // on passe en mode reset en desactivant toutes les it outb(RESET_MODE, CONTROL); // on force le mode BasicCAN outb(0x48, CLOCK_DIVIDER); // Identification du node and timing fixing outb(acc_code, ACCEPTANCE_CODE); outb(acc_mask, ACCEPTANCE_MASK); if(silent) outb(0x02, OUTPUT_CONTROL); else outb(0xFA, OUTPUT_CONTROL); switch (rate) { case 1000: { /* time quanta (tq) per bit : 8; *//* sync = 1tq, seg1 = 5tq, tseg2 = 2tq *//* conformance with Canopen DS301 recommandation *//* added by francis.dupin@inrets.fr. 2004 */ MSGK("Setting 1000 kbps.\n"); outb(0x00,BUS_TIMING_0); outb(0x14,BUS_TIMING_1); break; } case 500: { /* time quanta (tq) per bit : 16; *//* sync = 1tq, seg1 = 13tq, tseg2 = 2tq *//* conformance with Canopen DS301 recommandation *//* added by francis.dupin@inrets.fr. 2004 */ MSGK("Setting 500 kbps.\n"); outb(0x40,BUS_TIMING_0); outb(0x1C,BUS_TIMING_1); break; } case 250: { /* time quanta (tq) per bit : 16; *//* sync = 1tq, seg1 = 13tq, tseg2 = 2tq *//* conformance with Canopen DS301 recommandation *//* added by francis.dupin@inrets.fr. 2004 */ MSGK("Setting 250 kbps.\n"); outb(0x41,BUS_TIMING_0); outb(0x1C,BUS_TIMING_1); break; } case 125: { /* time quanta (tq) per bit : 16; *//* sync = 1tq, seg1 = 13tq, tseg2 = 2tq *//* conformance with Canopen DS301 recommandation *//* added by francis.dupin@inrets.fr. 2004 */ MSGK("Setting 125 kbps.\n"); outb(0x43,BUS_TIMING_0); outb(0x1C,BUS_TIMING_1); break; } case 100: { MSGK("Setting 100 kbps.\n"); outb(0x83,BUS_TIMING_0); outb(0x4d,BUS_TIMING_1); break; } case 50: {// Does not work MSGK("Setting 50 kbps.\n"); outb(0x18,BUS_TIMING_0); outb(0x1C,BUS_TIMING_1); break; } case 25: { MSGK("Setting 25 kbps.\n"); outb(0x8f,BUS_TIMING_0); outb(0x4d,BUS_TIMING_1); break; } case 10: { MSGK("Setting 10 kbps.\n"); outb(0xa7,BUS_TIMING_0); outb(0x4d,BUS_TIMING_1); break; } default: { MSGK("Baud rate not supported default to 1000.\n"); outb(0x00,BUS_TIMING_0); outb(0x14,BUS_TIMING_1); } } it = (overrun_it<<4) + (error_it<<3) + (transmit_it<<2) + (receive_it << 1); // switch to operating mode and activate irq's outb(it, CONTROL);}// envoi d'une trameMessage* sja1000_send_frame(int bus_nb, Message *mes){ int dlc, i; unsigned int SJA = SJA_BASE[bus_nb]; // bytes number dlc = mes->len & 0x0f; // COB_ID, RTR and DLC outb((((mes->cob_id.w >> 8) & 0x07) << 5) | ((mes->cob_id.w & 0xf8) >>3) , TRANSMIT_ID_0); outb(((mes->cob_id.w & 0x07) << 5) | ((mes->rtr & 0x01) << 4) | dlc , TRANSMIT_ID_1); // fill transmit buffer for(i=0; i < dlc; i++) { outb(mes->data[i], TRANSMIT_DATA+i); } // send outb(TRANS_REQUEST, COMMAND); return mes;}// reception d'une trameMessage* sja1000_rcv_frame(int bus_nb, Message *mes) { int i; char b0, b1; unsigned int SJA = SJA_BASE[bus_nb]; b0 = inb(RECEIVE_ID_0); b1 = inb(RECEIVE_ID_1); mes->cob_id.w = ((((b0 & 0xe0) >> 5) << 8) & 0xFF00) | //MSB ((((b0 & 0x1f) << 3) | ((b1 & 0xe0) >> 5)) & 0x00FF); //LSB mes->rtr = b1 & 0x10 ? 0x01 : 0x00; mes->len = b1 & 0x0f; for(i=0; i < mes->len; i++) { mes->data[i] = inb(RECEIVE_DATA+i); } // on acquitte la reception outb(RELEASE_RCV_BUFFER, COMMAND); return mes;}char sja1000_status(int bus_nb){ unsigned int SJA = SJA_BASE[bus_nb]; return inb(STATUS);}char sja1000_ir(int bus_nb){ unsigned int SJA = SJA_BASE[bus_nb]; return inb(INTERRUPT);}char plx_9050_ir(){ return inb(PLX_INTCSR);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -