📄 can.cpp
字号:
/*******************************Copyright (c)**********************************
** Guangzhou ZHIYUAN electronics Co.,LTD.
**
** http://www.zyinside.com
**
**--------------File Info------------------------------------------------------
** File Name: can.c
** Last modified Date: 2006-11-06
** Last Version: V1.0
** Description: S3C2410 SJA1000主机 驱动
**
**-----------------------------------------------------------------------------
** Created By: ruifeng qin 覃瑞峰
** Created date: 2006-11-06
** Version: V1.0
** Descriptions: The original version
**
******************************************************************************/
// can.cpp : 定义 DLL 应用程序的入口点。
//
#include <windows.h>
#include <types.h>
#include <excpt.h>
#include <tchar.h>
#include <tuple.h>
#include <devload.h>
#include <nkintr.h>
#include <windev.h>
#include <pkfuncs.h>
#include <ceddk.h>
#include <s3c2410x.h>
#define SJA1000_PELICAN_MODE
#include "can.h"
#define SJA1000_REGISTER_READ(reg, val) \
SJA1000_ReadRegister(reg, &(val))
#define SJA1000_REGISTER_WRITE(reg, val) \
SJA1000_WriteRegister(reg, val)
static HANDLE g_htCanIST; // 中断处理线程句柄
static HANDLE g_hInterrupt;
static HANDLE g_hRxEvent;
static HANDLE g_hTxEvent;
static UINT8 g_regCmd;
static CAN_MSG g_rxMsg;
#define CAN_RW_TIMEOUT 2000 // 访问超时
BOOL g_bKillIST; // 控制 IST 退出
UINT32 g_nCanIrq = IRQ_EINT5; // 的物理中断号及逻辑中断号
UINT32 g_nCanSysIntr = SYSINTR_UNDEFINED;
volatile UINT8 *g_lpBaseSJA1000 = NULL;
volatile S3C2410X_IOPORT_REG *g_lpBaseEXINT = NULL;
#define EXINT_ADDR_RANGE sizeof(S3C2410X_IOPORT_REG)
#define EXINT_PHYSICAL_ADDR S3C2410X_BASE_REG_PA_IOPORT
#define SJA1000_ADDR_RANGE 16
#define SJA1000_PHYSICAL_ADDR 0x20000000
//#define SJA1000_DAT_ADDR 0x20000004
//#define SJA1000_ALE_ADDR 0x20000008
INSTANTIATE_CAN_ZONES(0xffff, "CAN driver");
DWORD g_OpenCount = 0;
///////////////////////////////////////////////////////////////////////////////
BOOL APIENTRY DllEntry( HANDLE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
DisableThreadLibraryCalls((HMODULE) hModule);
DEB_0(ZONE_ERROR, _T(" CAN DLL_PROCESS_ATTACH\r"));
break;
case DLL_PROCESS_DETACH:
DEB_0(ZONE_ERROR, _T(" CAN DLL_PROCESS_DETACH\r"));
break;
default:
DEB_0(ZONE_ERROR, _T(" CAN DLL_PROCESS_DEFAULT\r"));
break;
}
return TRUE;
}
/*******************************************************************************
函数名称: CAN_Init
描 述: 驱动程序初始化函数
输入参数: DWORD dwContext: 设备管理器传递给本驱动的参数, 通常为流接口驱动在
注册表内的位置
输出参数: 无
返 回: 驱动程序句柄
*******************************************************************************/
DWORD CAN_Init(LPCTSTR pContext, LPCVOID lpvBusContext)
{
DWORD dwThreadID;
#ifdef DEBUG
UINT8 regval[128];
#endif
BOOL bResult = FALSE;
DEBUGMSG (ZONE_FUNCTION, (TEXT("+ ")TEXT(__FUNCTION__)TEXT("\r\n")));
// 分配 EXINT 访问空间 ------------------------------------------
g_lpBaseEXINT = (volatile S3C2410X_IOPORT_REG *)VirtualAlloc( 0,
EXINT_ADDR_RANGE,
MEM_RESERVE,
PAGE_NOACCESS);
if (g_lpBaseEXINT == NULL)
{
DEB_0(ZONE_INIT, _T(" EXINT VirtualAlloc failed\r"));
goto exit;
}
if (!VirtualCopy((PVOID)g_lpBaseEXINT,
(PVOID)(EXINT_PHYSICAL_ADDR >> 8),
EXINT_ADDR_RANGE,
PAGE_PHYSICAL | PAGE_READWRITE | PAGE_NOCACHE))
{
DEB_0(ZONE_INIT, _T(" EXINT VirtualCopy failed\r"));
goto exit;
}
// 分配 SJA1000 访问空间 ----------------------------------------
g_lpBaseSJA1000 = (volatile UINT8 *)VirtualAlloc( 0,
SJA1000_ADDR_RANGE,
MEM_RESERVE,
PAGE_NOACCESS);
if (g_lpBaseSJA1000 == NULL)
{
DEB_0(ZONE_INIT, _T(" SJA1000 VirtualAlloc failed\r"));
goto exit;
}
if (!VirtualCopy((PVOID)g_lpBaseSJA1000,
(PVOID)(SJA1000_PHYSICAL_ADDR >> 8),
SJA1000_ADDR_RANGE,
PAGE_PHYSICAL | PAGE_READWRITE | PAGE_NOCACHE))
{
DEB_0(ZONE_INIT, _T(" SJA1000 VirtualCopy failed\r"));
goto exit;
}
// 从 OAL 请求一个 SYSINTR 值 -----------------------------------
if (!KernelIoControl(IOCTL_HAL_REQUEST_SYSINTR,
&g_nCanIrq,
sizeof(UINT32),
&g_nCanSysIntr,
sizeof(UINT32),
NULL))
{
DEB_0(ZONE_INIT, _T(" failed to request sysintr value for ")
_T("CAN Bus interrupt\r"));
goto exit;
}
DEB_2(ZONE_INIT, _T(" mapped IRQ 0x%x to sysintr 0x%x\r"),
g_nCanIrq, g_nCanSysIntr);
g_htCanIST = CreateThread(NULL,
0,
(LPTHREAD_START_ROUTINE) CAN_IntrThread,
NULL,
0,
&dwThreadID);
if (g_htCanIST == 0)
{
DEB_0(ZONE_INIT, _T(" create thread failed\r"));
goto exit;
}
g_hInterrupt = CreateEvent(NULL, FALSE, FALSE, NULL);
g_hRxEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
g_hTxEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
// 初始化 SJA1000 -----------------------------------------------
EINT_ConfigInterruptPin();
SJA1000_Init();
SJA1000_SetFilter(0x00000000, 0xffffffff);
UINT8 BTR[] = {0x00, 0x14};
SJA1000_BaudSet(BTR);
g_OpenCount = 0;
#ifdef DEBUG
for (int i = 0; i < 32; i++) {
SJA1000_REGISTER_READ(i, regval[i]);
}
TCHAR szOut[256];
_stprintf(szOut, _T("physical address: 0x%8.8X mapped to ")
_T("virtual address: 0x%8.8X\r\n"),
SJA1000_PHYSICAL_ADDR, g_lpBaseSJA1000);
DEBUGMSG(ZONE_FUNCTION, (szOut));
for (int j = 0; j < 32; j += 8)
{
_stprintf(szOut, _T(__FUNCTION__)_T(": [ %2.2X ] ")
_T("%2.2X %2.2X %2.2X %2.2X ")
_T("%2.2X %2.2X %2.2X %2.2X\r\n"),
j,
regval[j+0], regval[j+1], regval[j+2], regval[j+3],
regval[j+4], regval[j+5], regval[j+6], regval[j+7]);
DEBUGMSG(ZONE_FUNCTION, (szOut));
}
#endif // DEBUG
bResult = TRUE;
exit:
if (!bResult)
{
InterruptDone(g_nCanSysIntr);
InterruptDisable(g_nCanSysIntr);
CloseHandle(g_hRxEvent);
if (g_lpBaseSJA1000)
VirtualFree((PVOID)g_lpBaseSJA1000, 0, MEM_RELEASE);
if (g_lpBaseEXINT)
VirtualFree((PVOID)g_lpBaseEXINT, 0, MEM_RELEASE);
CloseHandle(g_hInterrupt);
CloseHandle(g_hRxEvent);
CloseHandle(g_hTxEvent);
}
DEBUGMSG (ZONE_FUNCTION, (TEXT("- ")TEXT(__FUNCTION__)TEXT("\r\n")));
return bResult;
}
/*******************************************************************************
函数名称: CAN_Deinit
描 述: 驱动程序卸载函数
输入参数: DWORD dwContext: 驱动程序句柄
输出参数: 无
返 回: FALSE: 失败 TRUE: 成功
*******************************************************************************/
BOOL CAN_Deinit(DWORD hDeviceContext)
{
DEBUGMSG (ZONE_FUNCTION, (TEXT("+ ")TEXT(__FUNCTION__)TEXT("\r\n")));
if (g_htCanIST)
{
g_bKillIST = TRUE; // 通知中断服务线程退出
SetEvent(g_hInterrupt);
SetEvent(g_hTxEvent);
SetEvent(g_hRxEvent);
Sleep(200);
}
// 释放中断资源
InterruptDone(g_nCanSysIntr);
InterruptDisable(g_nCanSysIntr);
KernelIoControl(IOCTL_HAL_RELEASE_SYSINTR,
&g_nCanSysIntr,
sizeof(UINT32),
NULL,
0,
NULL);
// 释放申请的虚拟内存
if (g_lpBaseSJA1000)
VirtualFree((PVOID)g_lpBaseSJA1000, 0, MEM_RELEASE);
if (g_lpBaseEXINT)
VirtualFree((PVOID)g_lpBaseEXINT, 0, MEM_RELEASE);
// 关闭 CAN 事件句柄
CloseHandle(g_hInterrupt);
CloseHandle(g_hRxEvent);
CloseHandle(g_hTxEvent);
g_OpenCount = 0;
DEBUGMSG (ZONE_FUNCTION, (TEXT("- ")TEXT(__FUNCTION__)TEXT("\r\n")));
return TRUE;
}
/*******************************************************************************
函数名称: CAN_Open
输入参数: DWORD hDeviceContext : 设备驱动程序句柄
DWORD AccessCode : 访问请求代码,是读和写的组合
DWORD ShareMode : 共享模式
输出参数:
返 回: 驱动程序引用事例句柄
*******************************************************************************/
DWORD CAN_Open(DWORD hDeviceContext, DWORD AccessCode, DWORD ShareMode)
{
DEBUGMSG (ZONE_FUNCTION, (TEXT("+ ")TEXT(__FUNCTION__)TEXT("\r\n")));
if (g_OpenCount) return 0; // 只允许打开一次
SJA1000_Init();
SJA1000_REGISTER_WRITE(IER, IER_RIE | IER_TIE | IER_EIE | IER_DOIE |
IER_WUIE | IER_EPIE | IER_ALIE | IER_BEIE);
g_regCmd = CMR_TR;
UINT8 regMode;
SJA1000_REGISTER_READ(MOD, regMode);
SJA1000_REGISTER_WRITE(MOD, regMode & ~(MOD_STM | MOD_RM));
SetEvent(g_hTxEvent); // 使能发送
ResetEvent(g_hRxEvent); // 等待接收
g_OpenCount++;
DEBUGMSG (ZONE_FUNCTION, (TEXT("- ")TEXT(__FUNCTION__)TEXT("\r\n")));
return 1;
}
/*******************************************************************************
函数名称: CAN_Close
描 述: 驱动程序关闭函数
输入参数: DWORD Handle:驱动程序句柄
输出参数: 无
返 回: FALSE: 失败 TRUE: 成功
*******************************************************************************/
BOOL CAN_Close(DWORD hOpenContext)
{
DEBUGMSG (ZONE_FUNCTION, (TEXT("+ ")TEXT(__FUNCTION__)TEXT("\r\n")));
if (!g_OpenCount) return FALSE;
UINT8 regval;
SJA1000_REGISTER_READ(MOD, regval);
SJA1000_REGISTER_WRITE(MOD, regval | MOD_RM); // 脱离总线
SJA1000_REGISTER_READ(IER, regval);
regval &= ~(IER_RIE | IER_TIE | IER_EIE | IER_DOIE | IER_WUIE |
IER_EPIE | IER_ALIE | IER_BEIE);
SJA1000_REGISTER_WRITE(IER, regval); // 关闭 CAN 控制器中断
g_OpenCount--;
SetEvent(g_hTxEvent);
SetEvent(g_hRxEvent);
DEBUGMSG (ZONE_FUNCTION, (TEXT("- ")TEXT(__FUNCTION__)TEXT("\r\n")));
return TRUE;
}
/*******************************************************************************
函数名称: CAN_IOControl
描 述: 驱动程序 I/O 请求
输入参数:
输出参数:
返 回: TRUE: 成功 FALSE: 失败
*******************************************************************************/
BOOL CAN_IOControl(DWORD hOpenContext,
DWORD dwCode,
PBYTE pBufIn,
DWORD dwLenIn,
PBYTE pBufOut,
DWORD dwLenOut,
PDWORD pdwActualOut)
{
DEBUGMSG (ZONE_FUNCTION, (TEXT("+ ")TEXT(__FUNCTION__)TEXT("\r\n")));
if (!g_OpenCount) return FALSE;
BOOL bError = FALSE;
switch (dwCode)
{
case IOCTL_SET_CAN_BAUD:
SJA1000_BaudSet(pBufIn);
bError = TRUE;
break;
case IOCTL_SET_CAN_TXMODE: {
UINT8 regMod;
SJA1000_REGISTER_READ(MOD, regMod);
SJA1000_REGISTER_WRITE(MOD, regMod | MOD_RM);/* enter reset mode */
switch ((int)*pBufIn)
{
case 0: /* Transmission Request */
g_regCmd = CMR_TR;
SJA1000_REGISTER_WRITE(MOD, regMod & ~(MOD_STM | MOD_RM));
break;
case 1: /* Single Shot */
g_regCmd = CMR_TR | CMR_AT;
SJA1000_REGISTER_WRITE(MOD, regMod & ~(MOD_STM | MOD_RM));
break;
case 2: /* Self Reception Request */
g_regCmd = CMR_SRR;
SJA1000_REGISTER_WRITE(MOD, (regMod | MOD_STM) & ~MOD_RM);
break;
case 3: /* Single Shot and Self Reception Request */
g_regCmd = CMR_AT | CMR_SRR;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -