⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 c_can.c

📁 HMS30C7202下的CAN驱动
💻 C
📖 第 1 页 / 共 3 页
字号:
/** * c_can.c * Linux CAN-bus device driver. * * This file holds the methods which access the C_CAN module. * * Written by Sebastian Stolzenberg email:stolzi@sebastian-stolzenberg.de * Version 1.0  04 Feb 2003 */#define __NO_VERSION__#include <linux/delay.h>#include "../include/candrv.h"#include "../include/c_can.h"#include "../include/hms30c7202_can.h"extern int stdmask;extern int extmask;////////////////////////////////////////////////////////////////////////** * This function sets the C_CAN module in the configuration mode */int c_can_enable_configuration(struct chip_t *pchip){        int i=0;        u16 flags;        DEBUGMSG("(c%d)calling c_can_enable_configuration(...)", pchip->chip_nr);        //read Control Register        flags=pchip->read_register(pchip, CCCR);        //set Init-Bit in the Control Register (10 tries)        while ((!(flags & CR_INIT)) && (i<=10)) {                pchip->write_register(flags|CR_INIT, pchip, CCCR);                udelay(1000);                i++;                flags=pchip->read_register(pchip, CCCR);        }        if (i>=10) {                CANMSG("Reset error");                //enable_irq(chip->chip_irq);                return -ENODEV;        }        DEBUGMSG(" -> ok");        return 0;}////////////////////////////////////////////////////////////////////////** * This function stops the configuration mode of the C_CAN module */int c_can_disable_configuration(struct chip_t *pchip){        int i=0;        u16 flags;        DEBUGMSG("(c%d)calling c_can_disable_configuration(...)", pchip->chip_nr);        //read Control Register        flags=pchip->read_register(pchip, CCCR);        //reset Init-Bit in the Control Register (10 tries)        while ( (flags & CR_INIT) && (i<=10) ) {                pchip->write_register(flags & ~CR_INIT, pchip, CCCR);                udelay(1000); //1000 microseconds                i++;                flags=pchip->read_register(pchip, CCCR);        }        if (i>=10) {                CANMSG("Error leaving reset status");                return -ENODEV;        }        DEBUGMSG(" -> ok");        return 0;}////////////////////////////////////////////////////////////////////////** * Configures baudrate, IRQs and message objects of a C_CAN chip */int c_can_chip_config(struct chip_t *pchip){        DEBUGMSG("(c%d)calling c_can_chip_config(...)", pchip->chip_nr);        // Validate pointer        if ( NULL == pchip ) return -1;        if (pchip->baudrate == 0)                pchip->baudrate=1000;        if (c_can_baud_rate(pchip,pchip->baudrate*1000,pchip->clock,0,75,0)) {                CANMSG("Error configuring baud rate");                return -ENODEV;        }        if (c_can_clear_objects(pchip)) {                CANMSG("Error clearing message objects");                return -ENODEV;        }        if ( ! pchip->time_triggered ) {                if (c_can_config_irqs(pchip, CR_MIE | CR_SIE | CR_EIE)) {                        CANMSG("Error configuring interrupts");                        return -ENODEV;                }        } else {                if (c_can_config_irqs(pchip, CR_SIE | CR_EIE)) {                        CANMSG("Error configuring interrupts");                        return -ENODEV;                }        }        DEBUGMSG(" -> Configured successfully");#ifdef REGDUMP        c_can_registerdump(pchip);#endif        return 0;}////////////////////////////////////////////////////////////////////////** * Checks if the Busy-Bit in the IF1-Command-Request Register is set */int c_can_if1_busycheck(struct chip_t *pchip){        int i=0;        while ( ( pchip->read_register( pchip, CCIF1CR) & IFXCR_BUSY) &&                (i++ <= 10) ) ;        if (i>=10) {                CANMSG("Error Busy-Bit stays set");                return -ENODEV;        }        return 0;}////////////////////////////////////////////////////////////////////////** * Checks if the Busy-Bit in the IF2-Command-Request Register is set */int c_can_if2_busycheck(struct chip_t *pchip){        int i=0;        while ( (pchip->read_register( pchip, CCIF2CR) & IFXCR_BUSY) &&                (i++ <= 10) ) ;        if (i>=10) {                CANMSG("Error Busy-Bit stays set");                return -ENODEV;        }        return 0;}////////////////////////////////////////////////////////////////////////** * Set communication parameters. * param rate baud rate in Hz * param clock frequency of C-CAN clock in Hz * param sjw synchronization jump width (0-3) prescaled clock cycles * param sampl_pt sample point in % (0-100) sets (TSEG1+2)/(TSEG1+TSEG2+3) ratio * param flags fields BTR1_SAM, OCMODE, OCPOL, OCTP, OCTN, CLK_OFF, CBP */int c_can_baud_rate(struct chip_t *pchip,                    u32 rate,                    u32 clock,                    u32 sjw,                    u32 sampl_pt,                    u32 flags){        int best_error = 1000000000, error;        int best_tseg=0, best_brp=0, best_rate=0, brp=0;        int tseg=0, tseg1=0, tseg2=0;        unsigned short tempCR = 0;        DEBUGMSG("(c%d)calling c_can_baud_rate(...)", pchip->chip_nr);        if (c_can_enable_configuration(pchip))                return -ENODEV;        clock /=2;        /* tseg even = round down, odd = round up */        for (tseg=(0+0+2)*2; tseg<=(MAX_TSEG2+MAX_TSEG1+2)*2+1; tseg++) {                brp = clock/((1+tseg/2)*rate)+tseg%2;                if (brp == 0 || brp > 64)                        continue;                error = rate - clock/(brp*(1+tseg/2));                if (error < 0)                        error = -error;                if (error <= best_error) {                        best_error = error;                        best_tseg = tseg/2;                        best_brp = brp-1;                        best_rate = clock/(brp*(1+tseg/2));                }        }        if (best_error && (rate/best_error < 10)) {                CANMSG("baud rate %d is not possible with %d Hz clock",                        rate, 2*clock);                CANMSG("%d bps. brp=%d, best_tseg=%d, tseg1=%d, tseg2=%d",                        best_rate, best_brp, best_tseg, tseg1, tseg2);                return -EINVAL;        }        tseg2 = best_tseg-(sampl_pt*(best_tseg+1))/100;        if (tseg2 < 0)                tseg2 = 0;        if (tseg2 > MAX_TSEG2)                tseg2 = MAX_TSEG2;        tseg1 = best_tseg-tseg2-2;        if (tseg1 > MAX_TSEG1) {                tseg1 = MAX_TSEG1;                tseg2 = best_tseg-tseg1-2;        }        DEBUGMSG(" -> Setting %d bps.\n", best_rate);        DEBUGMSG(" -> brp=%d, best_tseg=%d, tseg1=%d, tseg2=%d, sampl_pt=%d",                  best_brp, best_tseg, tseg1, tseg2,                  (100*(best_tseg-tseg2)/(best_tseg+1)));        //read Control Register        tempCR = pchip->read_register( pchip, CCCR);        //Configuration Change Enable        pchip->write_register(tempCR | CR_CCE, pchip, CCCR);        pchip->write_register(((unsigned short)tseg2)<<12 | ((unsigned short)tseg1)<<8                              | (unsigned short)sjw<<6 | (unsigned short) best_brp,                              pchip, CCBT);        if (c_can_disable_configuration(pchip))                return -ENODEV;        return 0;}////////////////////////////////////////////////////////////////////////** * Configures the mask bits of the specified message object */int c_can_mask(struct msgobj_t *pmsgobj,               u32 mask,               u16 usedirbit){        unsigned short tempreg = 0;        unsigned short readMaskCM;        unsigned short writeMaskCM;        DEBUGMSG("(c%dm%d)calling c_can_mask(...)", pmsgobj->hostchip->chip_nr, pmsgobj->object);        readMaskCM = IFXCM_CNTRL | IFXCM_ARB | IFXCM_MASK;        writeMaskCM = IFXCM_CNTRL | IFXCM_ARB | IFXCM_MASK | IFXCM_WRRD;        spin_lock( &pmsgobj->hostchip->if1lock );        /* load Message Object in IF1 */        if (c_can_if1_busycheck(pmsgobj->hostchip)) return -ENODEV;        pmsgobj->hostchip->write_register(readMaskCM, pmsgobj->hostchip, CCIF1CM);        pmsgobj->hostchip->write_register(pmsgobj->object+1, pmsgobj->hostchip, CCIF1CR);        /* setting Message Valid Bit to zero */        if (c_can_if1_busycheck(pmsgobj->hostchip)) return -ENODEV;        tempreg = pmsgobj->hostchip->read_register(pmsgobj->hostchip, CCIF1A2);        pmsgobj->hostchip->write_register(tempreg & ~(IFXARB2_MVAL), pmsgobj->hostchip, CCIF1A2);        pmsgobj->hostchip->write_register(writeMaskCM, pmsgobj->hostchip, CCIF1CM);        pmsgobj->hostchip->write_register(pmsgobj->object+1, pmsgobj->hostchip, CCIF1CR);        /* setting UMask, MsgVal and Mask Register */        if (c_can_if1_busycheck(pmsgobj->hostchip)) return -ENODEV;        /* writing acceptance mask for extended or standart mode */        if (pmsgobj->msg_mode & 1) {                if (usedirbit)                        pmsgobj->hostchip->write_register((mask>>16 & 0x1FFF) | IFXMSK2_MXTD                                                          | IFXMSK2_MDIR,                                                          pmsgobj->hostchip, CCIF1M2);                else                        pmsgobj->hostchip->write_register((mask>>16 & 0x1FFF) | IFXMSK2_MXTD,                                                          pmsgobj->hostchip, CCIF1M2);                        pmsgobj->hostchip->write_register((mask & 0xFFFF), pmsgobj->hostchip,                                                          CCIF1M1);        } else {                if (usedirbit)                        pmsgobj->hostchip->write_register(((mask<<2) & 0x1FFC) | IFXMSK2_MDIR,

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -