?? sja1000p.cpp
字號:
/* sja1000.c * Linux CAN-bus device driver. * Written by Arnaud Westenberg email:arnaud@wanadoo.nl * This software is released under the GPL-License. * Version 0.6 18 Sept 2000 * Changed for PeliCan mode SJA1000 by Tomasz Motylewski (BFAD GmbH) * T.Motylewski@bfad.de */#include <windows.h>#include <windef.h>#include <types.h>#include <excpt.h>#include <tchar.h>#include <cardserv.h>#include <cardapi.h>#include <tuple.h>#include <devload.h>#include <diskio.h>#include <nkintr.h>#include <oalintr.h>#include <windev.h>#include <memory.h>#include <linklist.h>#include <pegdser.h>#include <pm.h>#include "sja1000p.h" int baudrate=0;int CLOCK = 24000000; // Chip CLOCK in Hzstatic volatile CAN_ADDR* m_pCanAddr = NULL;static void Delay(DWORD dwMSecs) { #define MSEC_DELAY_SCALER 0x2 volatile DWORD dwScaledSecs = (dwMSecs * MSEC_DELAY_SCALER); while (dwScaledSecs) { dwScaledSecs--; }}int CanP_VirtualAlloc(){ RETAILMSG(1, (TEXT("CAN:: CanVirtualAlloc++ \r\n") )); m_pCanAddr = ( volatile CAN_ADDR *)VirtualAlloc(0, sizeof(CAN_ADDR), MEM_RESERVE, PAGE_NOACCESS); if(m_pCanAddr == NULL) { RETAILMSG (1,(TEXT("CAN:: CanVirtualAlloc m_pCanAddr : VirtualAlloc failed!\r\n"))); goto error_return; } else { if(!VirtualCopy((PVOID)m_pCanAddr, (PVOID)(SJA1000_BASE), sizeof(CAN_ADDR), PAGE_READWRITE|PAGE_NOCACHE )) { RETAILMSG(1,(TEXT("CAN:: CanVirtualAlloc m_pCanAddr : VirtualCopy failed!\r\n"))); goto error_return; } } RETAILMSG(1, (TEXT("CAN:: m_pCanAddr %x\r\n"), m_pCanAddr)); RETAILMSG(1,(TEXT("CAN:: CanVirtualAlloc-- \r\n"))); return TRUE;error_return: if ( m_pCanAddr ) VirtualFree((PVOID)m_pCanAddr, 0, MEM_RELEASE); m_pCanAddr = NULL; return 0; } unsigned can_read_reg( unsigned short reg ){ m_pCanAddr->byteAddr = reg; //訪問地址指向控制寄存器 return m_pCanAddr->byteData; //保存原始值 }; void can_write_reg(unsigned char data, unsigned short reg ){ m_pCanAddr->byteAddr = reg; //訪問地址指向控制寄存器 m_pCanAddr->byteData = data; //保存原始值};// Enter reset mode.int sja1000p_enable_configuration( ){ int i=0; unsigned int flags; flags=can_read_reg( SJAMOD); while ((!(flags & MOD_RM)) && (i<=10)) { can_write_reg( MOD_RM, SJAMOD);// TODO: chinfigurable MOD_AFM (32/16 bit acceptance filter)// config MOD_LOM (listen only) Delay(10); i++; flags=can_read_reg( SJAMOD); } if (i>=10) { RETAILMSG(1,(TEXT("Reset error\n"))); return -1; } return 0;}// Quit reset mode.int sja1000p_disable_configuration( ){ int i=0; unsigned int flags; flags=can_read_reg( SJAMOD); while ( (flags & MOD_RM) && (i<=10) ) { can_write_reg( 0, SJAMOD);// TODO: chinfigurable MOD_AFM (32/16 bit acceptance filter)// config MOD_LOM (listen only) Delay(10); i++; flags=can_read_reg( SJAMOD); } if (i>=10) { RETAILMSG(1,(TEXT("Error leaving reset status\n"))); return -1; } return 0;}/************************************ ACR==0AAH,AMR==00H OC : 0xd9 為測試模式。 0xda 為正常工作模式 CDR=48H ************************************************/int sja1000p_chip_config( unsigned int uCDR, unsigned int uOCR, unsigned int uBTR0, unsigned int uBTR1, unsigned int uACR, unsigned int uAMR ){ if (sja1000p_enable_configuration()) return -1; can_write_reg( uCDR, SJACDR); can_write_reg( uOCR,SJAOCR); sja1000p_set_btregs( uBTR0, uBTR1 ); if (sja1000p_extended_mask( uACR, uAMR)) return -1; /* Enable hardware interrupts */ can_write_reg( ENABLE_INTERRUPTS, SJAIER); sja1000p_disable_configuration(); return 0;}int sja1000p_set_cdr_ocrregs( unsigned int uCDR, unsigned int uOCR){ if (sja1000p_enable_configuration()) return -1; can_write_reg( uCDR, SJACDR); can_write_reg( uOCR,SJAOCR); sja1000p_disable_configuration(); } // Config ACR, AMR registor.int sja1000p_extended_mask( unsigned long code, unsigned long mask){ int i; if (sja1000p_enable_configuration()) return -1;// LSB to +3, MSB to +0 for(i=SJA_PeliCAN_AC_LEN; --i>=0;) { can_write_reg( code&0xff,SJAACR0+i); can_write_reg( mask&0xff,SJAAMR0+i); code >>= 8; mask >>= 8; } sja1000p_disable_configuration(); return 0;}/* Set communication parameters. * param rate baud rate in Hz * param CLOCK frequency of sja1000 CLOCK in Hz (ISA osc is 14318000) * param sjw synchronization jump width (0-3) prescaled CLOCK cycles * param sampl_pt sample point in % (0-100) sets (TSEG1+1)/(TSEG1+TSEG2+2) ratio * param flags fields BTR1_SAM, OCMODE, OCPOL, OCTP, OCTN, CLK_OFF, CBP */int sja1000p_baud_rate( int rate, int sjw, int sampl_pt, int 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; if (sja1000p_enable_configuration()) return -1; 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)) { RETAILMSG(1,(TEXT("baud rate %d is not possible with %XHz CLOCK\n")), rate, 2*CLOCK); RETAILMSG(1,(TEXT("%d bps. brp=%d, best_tseg=%d, tseg1=%d, tseg2=%d\n")), best_rate, best_brp, best_tseg, tseg1, tseg2); return -1; } 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; } RETAILMSG(1,(TEXT("Setting %d bps.\n")), best_rate); RETAILMSG(1,(TEXT("brp=%d, best_tseg=%d, tseg1=%d, tseg2=%d, sampl_pt=%d\n")), best_brp, best_tseg, tseg1, tseg2, (100*(best_tseg-tseg2)/(best_tseg+1))); can_write_reg( sjw<<6 | best_brp, SJABTR0); can_write_reg( ((flags & BTR1_SAM) != 0)<<7 | (tseg2<<4) | tseg1, SJABTR1); sja1000p_disable_configuration(); return 0;}int sja1000p_set_btregs( unsigned int btr0, unsigned int btr1){ if (sja1000p_enable_configuration()) return -1; can_write_reg( btr0, SJABTR0); can_write_reg( btr1, SJABTR1); sja1000p_disable_configuration(); return 0;}int sja1000p_start_chip( ){ unsigned int flags; flags = can_read_reg( SJAMOD) & (MOD_LOM|MOD_STM|MOD_AFM|MOD_SM); can_write_reg( flags, SJAMOD); return 0;}int sja1000p_stop_chip( ){ unsigned int flags; flags = can_read_reg( SJAMOD) & (MOD_LOM|MOD_STM|MOD_AFM|MOD_SM); can_write_reg( flags|MOD_RM, SJAMOD); return 0;} int peli_DATA_RECEIVE( RXFIFO& rxfifo)// 讀寫函數都有問題,應該判斷是standard幀還是extended幀才能知道數據真正的長度 { int i = 0; BYTE byReg1 = 0; unsigned char TempCount; //訪問地址指向狀態寄存器 if((can_read_reg(SJASR)&0x01)==0) //判斷報文是否有效 這個應該是判斷接受緩沖區是否為空 by黎科峰 { RETAILMSG(1,(TEXT("SJA1K:: BCAN_DATA_RECEIVE-- no data error \r\n"))); return 1; } for( i = 0; i <= 12; i++) rxfifo.reg[i] = can_read_reg( 16+ i ); RETAILMSG(1, (TEXT(" TX buffer reg%x = %x\r\n"), i+16, rxfifo.reg[i] )); } // can_write_reg( CMR_RRB,SJACMR ); RETAILMSG(1,(TEXT("SJA1K:: BCAN_DATA_RECEIVE-- ok \r\n"))); return 0; } int peli_DATA_WRITE(unsigned int *SendDataBuf) { unsigned char TempCount; int i = 0; /* and leave Reset Mode */ sja1000p_disable_configuration(); if(( can_read_reg(SJASR)&0x08) == 0) //判斷上次發送是否完成 { RETAILMSG(1,(TEXT("SJA1K:: BCAN_DATA_WRITE-- not complete error \r\n"))); return 1; } if((can_read_reg(SJASR)&0x04)==0) //判斷發送緩沖區是否鎖定 { RETAILMSG(1,(TEXT("SJA1K:: BCAN_DATA_WRITE--lock error \r\n"))); return 1; } if((SendDataBuf[0]&0x40)==0) //判斷RTR,從而得出是數據幀還是遠程幀 { TempCount =(SendDataBuf[0]&0x0f) + 5; //輸入數據幀 } else { TempCount =5; //遠程幀 } // memcpy(m_pCanAddr->byteData,SendDataBuf,TempCount); for ( i = 0; i < TempCount; i++) { can_write_reg( SendDataBuf[i],SJAFRM + i); } RETAILMSG(1, (TEXT("CAN:: SendDatacount %x\r\n"), TempCount)); can_write_reg( CMR_TR,SJACMR ); RETAILMSG(1,(TEXT("SJA1K:: BCAN_DATA_WRITE-- ok \r\n"))); return 0;}void TestReadAllRegs( ){ int i = 0; unsigned int ireg = 0; RETAILMSG(1,(TEXT(" TestReadAllRegs++ \r\n"))); for( i = 0; i <= 0x1f; i++) { ireg = can_read_reg ( i ); RETAILMSG(1, (TEXT(" Reg%x = %x\r\n"),i, ireg )); } RETAILMSG(1,(TEXT(" TestReadAllRegs-- \r\n")));}void initcan( ){ BYTE byCDR,byOCR,byBTR0,byBTR1,byMOD,byCMR; unsigned regtmp = 0, RegInt = 0, Reg1 = 0, Reg2 = 0; RETAILMSG(1,(TEXT(" SlefTest ++ \r\n"))); RETAILMSG(1, (TEXT(" Hardware reset status \r\n"))); TestReadAllRegs(); // byCDR = 0xC8,byOCR= 0xda,byBTR0 = 0xc2, byBTR1 = 0x3a,byMOD = MOD_STM,byCMR = CMR_SRR; if (sja1000p_enable_configuration()) return ; // PeliCAN Mode can_write_reg( 0xC8, SJACDR); can_write_reg( 0x1a, SJAOCR); can_write_reg( 0x18, SJABTR0); can_write_reg( 0xef, SJABTR1); Delay(10); can_write_reg( 0x00, 16); can_write_reg( 0x00, 17); can_write_reg( 0x00, 18); can_write_reg( 0x00, 19); can_write_reg( 0xff, 20); can_write_reg( 0xff, 21); can_write_reg( 0xff, 22); can_write_reg( 0xff, 23); Sleep(5); RETAILMSG(1, (TEXT(" reset status After Setting \r\n"))); TestReadAllRegs(); sja1000p_disable_configuration(); //Enter Self Test Mode can_write_reg( MOD_AFM, SJAMOD); can_write_reg( ENABLE_INTERRUPTS, SJAIER); can_read_reg ( SJAIR ); RETAILMSG(1, (TEXT(" Operate status init \r\n"))); TestReadAllRegs(); for( regtmp = 0; regtmp <= 12; regtmp++) { Reg2 = can_read_reg( 96+ regtmp ); RETAILMSG(1, (TEXT(" TX buffer reg%x = %x\r\n"), regtmp+96, Reg2)); } RETAILMSG(1,(TEXT(" SlefTest-- \r\n"))); }
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -