?? sja1000.c
字號:
SJA1000_BT0 = 73; SJA1000_BT1 = 28; break; case CAN_SPEED_100K: SJA1000_BT0 = 68; SJA1000_BT1 = 28; break; case CAN_SPEED_125K: SJA1000_BT0 = 67; SJA1000_BT1 = 28; break; case CAN_SPEED_250K: SJA1000_BT0 = 65; SJA1000_BT1 = 28; break; case CAN_SPEED_500K: SJA1000_BT0 = 64; SJA1000_BT1 = 28; break; case CAN_SPEED_800K: SJA1000_BT0 = 64; SJA1000_BT1 = 22; break; case CAN_SPEED_1M: SJA1000_BT0 = 64; SJA1000_BT1 = 20; break; default: result = 1; } do { SJA1000_MODECTRL = 0x00; } while ((SJA1000_MODECTRL & RM_RR_Bit) != 0x00); // leave reset state return result;}/*! * \fn SJATxFrame(CANFRAME * CAN_frame) * \brief Sends a CAN Frane * * * \param CAN_frame Pointer to the send frame */void SJATxFrame(CANFRAME * CAN_frame){ u_long temp_id; temp_id = CAN_frame->id << 3; if (CAN_frame->ext) { SJA1000_TxFrameInfo = CAN_frame->len | CAN_29 | (CAN_frame->rtr ? CAN_RTR : 0); SJA1000_Tx1 = (uint8_t) (temp_id >> 24); // load High Byte SJA1000_Tx2 = (uint8_t) (temp_id >> 16); // load High Byte SJA1000_Tx3 = (uint8_t) (temp_id >> 8); // load High Byte SJA1000_Tx4 = (uint8_t) (temp_id & 0x00F8); // Low Byte and ignore bit 0-2 SJA1000_Tx5 = CAN_frame->byte[0]; SJA1000_Tx6 = CAN_frame->byte[1]; SJA1000_Tx7 = CAN_frame->byte[2]; SJA1000_Tx8 = CAN_frame->byte[3]; SJA1000_Tx9 = CAN_frame->byte[4]; SJA1000_Tx10 = CAN_frame->byte[5]; SJA1000_Tx11 = CAN_frame->byte[6]; SJA1000_Tx12 = CAN_frame->byte[7]; } else { SJA1000_TxFrameInfo = CAN_frame->len | (CAN_frame->rtr ? CAN_RTR : 0); SJA1000_Tx1 = (uint8_t) ((CAN_frame->id) >> 24); // load High Byte SJA1000_Tx2 = (uint8_t) ((CAN_frame->id) >> 16) & 0xE0; // Low Byte and ignore bit 0-4 SJA1000_Tx3 = CAN_frame->byte[0]; SJA1000_Tx4 = CAN_frame->byte[1]; SJA1000_Tx5 = CAN_frame->byte[2]; SJA1000_Tx6 = CAN_frame->byte[3]; SJA1000_Tx7 = CAN_frame->byte[4]; SJA1000_Tx8 = CAN_frame->byte[5]; SJA1000_Tx9 = CAN_frame->byte[6]; SJA1000_Tx10 = CAN_frame->byte[7]; } SJA1000_CMD = TR_Bit; // Start Transmission}/*! * \fn SJARxFrame(CANFRAME * CAN_frame) * \brief Receives a CAN Frane * * * \param CAN_frame Pointer to the receive frame */void SJARxFrame(CANFRAME * CAN_frame){ u_char FrameInfo = SJA1000_RxFrameInfo; CAN_frame->len = FrameInfo & 0x0F; // frame info mask off higher 4 bits CAN_frame->ext = FrameInfo & CAN_29 ? 1 : 0; CAN_frame->rtr = FrameInfo & CAN_RTR ? 1 : 0; if (CAN_frame->ext) { CAN_frame->id = (((uint32_t) SJA1000_Rx1 << 24) | ((uint32_t) SJA1000_Rx2 << 16) | ((uint32_t) SJA1000_Rx3 << 8) | ((uint32_t) SJA1000_Rx4 & 0xF8)) >> 3; CAN_frame->byte[0] = SJA1000_Rx5; CAN_frame->byte[1] = SJA1000_Rx6; CAN_frame->byte[2] = SJA1000_Rx7; CAN_frame->byte[3] = SJA1000_Rx8; CAN_frame->byte[4] = SJA1000_Rx9; CAN_frame->byte[5] = SJA1000_Rx10; CAN_frame->byte[6] = SJA1000_Rx11; CAN_frame->byte[7] = SJA1000_Rx12; // just fill the whole struct, less CPU cycles } else { CAN_frame->id = (((uint32_t) SJA1000_Rx1 << 24) | (uint32_t) SJA1000_Rx2 << 16) >> 3; // id_h and id_l CAN_frame->byte[0] = SJA1000_Rx3; CAN_frame->byte[1] = SJA1000_Rx4; CAN_frame->byte[2] = SJA1000_Rx5; CAN_frame->byte[3] = SJA1000_Rx6; CAN_frame->byte[4] = SJA1000_Rx7; CAN_frame->byte[5] = SJA1000_Rx8; CAN_frame->byte[6] = SJA1000_Rx9; CAN_frame->byte[7] = SJA1000_Rx10; // just fill the whole struct, less CPU cycles } SJA1000_CMD = RRB_Bit; // release the receive buffer}/*! * \fn CAN_Tx(void *arg) * \brief CAN transmitter thread. * * * This thread transmits data if there's some in the output buffer. * It runs with high priority. */THREAD(CAN_Tx, arg){ NUTDEVICE *dev; CANINFO *ci; CANFRAME out_frame; dev = arg; ci = (CANINFO *) dev->dev_dcb; NutThreadSetPriority(16); while (1) { NutEventWait(&ci->can_tx_rdy, NUT_WAIT_INFINITE); while ((SJA1000_STATUS & TBS_Bit) == TBS_Bit) // if transmit buffer released { out_frame = CANBufferGetMutex(&CAN_TX_BUF); SJATxFrame(&out_frame); // using SJA1000 TX buffer ci->can_tx_frames++; } }}/*! * \fn SJAInterrupt (void * arg) * \brief SJA interrupt entry. * * The interrupt handler posts events to the rx and tx thread wait queue. * receive interrupt will be disabled on reception and will be enabled by the * rx thread again. Otherwise interrupt would not stop (level triggered) */static void SJAInterrupt(void *arg){ CANINFO *ci; volatile u_char irq = SJA1000_INT; CANFRAME in_frame; ci = (CANINFO *) (((NUTDEVICE *) arg)->dev_dcb); ci->can_interrupts++; if (((irq & TI_Bit) == TI_Bit)) // transmit IRQ fired { NutEventPostFromIrq(&ci->can_tx_rdy); } if ((irq & RI_Bit) == RI_Bit) // Receive IRQ fired { if (CAN_RX_BUF.size-CAN_RX_BUF.datalength > 0) { SJARxFrame(&in_frame); CANBufferPut(&CAN_RX_BUF, &in_frame); if (CAN_RX_BUF.size==CAN_RX_BUF.datalength) SJA1000_IEN &= (~RIE_Bit); // Disable RX IRQ until data has been poped from input buffer NutEventPostFromIrq(&ci->can_rx_rdy); ci->can_rx_frames++; } } if ((irq & EI_Bit) == EI_Bit) //Error IRQ fired { ci->can_errors++; // TODO: Handle error } else if ((irq & DOI_Bit) == DOI_Bit) //Error IRQ fired { ci->can_overruns++; SJA1000_CMD = CDO_Bit; // Clear DO status; // TODO: Handle overrun }}/*! * \fn SJAInit(NUTDEVICE * dev) * \brief Initialize SJA1000 Canbus interface. * * * Applications typically do not use this function, but * call NutRegisterDevice(). * * \param dev Identifies the device to initialize. The * structure must be properly set. */int SJAInit(NUTDEVICE * dev){ IFCAN *ifc; CANINFO *ci; volatile u_char temp; sja_base = dev->dev_base; ifc = dev->dev_icb; memset(dev->dev_dcb, 0, sizeof(CANINFO)); ci = (CANINFO *) dev->dev_dcb; CANBufferInit(&CAN_RX_BUF, CAN_BufSize); CANBufferInit(&CAN_TX_BUF, CAN_BufSize); while ((SJA1000_MODECTRL & RM_RR_Bit) == 0x00) // entering reset mode SJA1000_MODECTRL = (RM_RR_Bit | SJA1000_MODECTRL); SJA1000_CLK_DIV = (CANMode_Bit | CBP_Bit | DivBy2 | ClkOff_Bit); // sets clock divide register SJA1000_IEN = (ClrIntEnSJA); // Disables CAN IRQ SJA1000_AC0 = ifc->can_acc_code[0]; SJA1000_AC1 = ifc->can_acc_code[1]; SJA1000_AC2 = ifc->can_acc_code[2]; SJA1000_AC3 = ifc->can_acc_code[3]; SJA1000_AM0 = ifc->can_acc_mask[0]; SJA1000_AM1 = ifc->can_acc_mask[1]; SJA1000_AM2 = ifc->can_acc_mask[2]; SJA1000_AM3 = ifc->can_acc_mask[3]; switch (ifc->can_baudrate) // setting actual bustiming { // all @ 16 Mhz case CAN_SPEED_10K: SJA1000_BT0 = 113; SJA1000_BT1 = 28; break; case CAN_SPEED_20K: SJA1000_BT0 = 88; SJA1000_BT1 = 28; break; case CAN_SPEED_50K: SJA1000_BT0 = 73; SJA1000_BT1 = 28; break; case CAN_SPEED_100K: SJA1000_BT0 = 68; SJA1000_BT1 = 28; break; case CAN_SPEED_125K: SJA1000_BT0 = 67; SJA1000_BT1 = 28; break; case CAN_SPEED_250K: SJA1000_BT0 = 65; SJA1000_BT1 = 28; break; case CAN_SPEED_500K: SJA1000_BT0 = 64; SJA1000_BT1 = 28; break; case CAN_SPEED_800K: SJA1000_BT0 = 64; SJA1000_BT1 = 22; break; case CAN_SPEED_1M: SJA1000_BT0 = 64; SJA1000_BT1 = 20; break; default: return errCAN_INVALID_BAUD; } SJA1000_OUTCTRL = (Tx1Float | Tx0PshPull | NormalMode); // Set up Output Control Register SJA1000_IEN = (RIE_Bit | TIE_Bit | EIE_Bit | DOIE_Bit ); // Enables receive IRQ SJA1000_MODECTRL = (AFM_Bit); // set single filter mode + sleep // *** Note - if you change SJA1000_MODECTRL, change it in // functions SJASetAccMask and SJASetAccCode also. do { SJA1000_MODECTRL = 0x00; } while ((SJA1000_MODECTRL & RM_RR_Bit) != 0x00); // leaves reset mode NutEnterCritical(); if (NutRegisterIrqHandler(&SJA_SIGNAL, SJAInterrupt, dev)) { NutExitCritical(); return -1; } cbi(EIMSK, SJA_SIGNAL_BIT); if (SJA_SIGNAL_BIT < 4) // Set corresponding interrupt to low { // level interrupt#ifdef __AVR_ENHANCED__ cbi(EICRA, (SJA_SIGNAL_BIT << 1)); cbi(EICRA, (SJA_SIGNAL_BIT << 1) + 1);#endif /* __AVR_ENHANCED__ */ } else { cbi(EICR, ((SJA_SIGNAL_BIT - 4) << 1)); cbi(EICR, ((SJA_SIGNAL_BIT - 4) << 1) + 1); } temp = SJA1000_INT; // Read interrupt register to clear pendin bits sbi(EIMSK, SJA_SIGNAL_BIT); sbi(PORTE, SJA_SIGNAL_BIT); NutThreadCreate("sjacantx", CAN_Tx, dev, 256); NutExitCritical(); return 0;}/*! * \brief Interface information structure. * * This struct stores some interface parameters like bautdate and * acceptance mask / code. Beside this Callback handlers are registered. */IFCAN ifc_sja1000 = { CAN_IF_2B, /*!< \brief Interface type. */ CAN_SPEED_500K, /*!< \brief Baudrate of device. */ {0xFF, 0xFF, 0xFF, 0xFF} , /*!< \brief Acceptance mask */ {0x00, 0x00, 0x00, 0x00} , /*!< \brief Acceptance code */ SJARxAvail, /*!< \brief Data in RxBuffer available? */ SJATxFree, /*!< \brief TxBuffer free? */ SJAInput, /*!< \brief CAN Input routine */ SJAOutput, /*!< \brief CAN Output routine */ SJASetAccCode, /*!< \brief Set acceptance code */ SJASetAccMask, /*!< \brief Set acceptance mask */ SJASetBaudrate /*!< \brief Set baudrate */};/*! * \brief Device information structure. * * Applications must pass this structure to NutRegisterDevice() * to bind this CAN device driver to the Nut/OS kernel. */NUTDEVICE devSJA1000 = { 0, /*!< Pointer to next device. */ {'s', 'j', 'a', '1', '0', '0', '0', 0, 0} , /*!< Unique device name. */ IFTYP_CAN, /*!< Type of device. */ 0, /*!< Base address. */ 0, /*!< First interrupt number. */ &ifc_sja1000, /*!< Interface control block. */ &dcb_sja1000, /*!< Driver control block. */ SJAInit, /*!< Driver initialization routine. */ 0, /*!< Driver specific control function. */ 0, /*!< Read from device. */ 0, /*!< Write to device. */ 0, /*!< Write from program space data to device. */ 0, /*!< Open a device or file. */ 0, /*!< Close a device or file. */ 0 /*!< Request file size. */};#elsevoid keep_icc_happy(void){}#endif/*@}*/
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -