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

📄 can.cpp

📁 SMDK2410_ZY_V11.rar
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/*******************************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 + -