wince TQ2440 定时器驱动 编写问题

时间:2021-03-22 18:11:36
近期用定时器定时时,总是无法改变频率,不知问题何在,求解答!

以下是我写的驱动(改写的原BSP中的EINTDriver):


#include <windows.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 <windev.h>
#include <pm.h>

#include "BSP.h"

#include "pmplatform.h"
#include "Pkfuncs.h"

static volatile S3C2440A_IOPORT_REG * v_pIOPregs;
volatile S3C2440A_INTR_REG * v_pINTRregs;
volatile S3C2440A_PWM_REG *v_pPWMregs;

UINT32 g_KeySysIntr;
INT32 xinhao=0;
static DWORD  m_s3c2440_pclk;
#define DEFAULT_S3C2440X_PCLK (405000000 / 8)


HANDLE IntThread;
HANDLE IntEvent;

void Virtual_Alloc(); // Virtual allocation
DWORD IntProcessThread(void);
static void PWM_ConfigPWMDefault();



DWORD IntProcessThread(void)
{
UINT32 IRQ;

IntEvent = CreateEvent(NULL, FALSE, FALSE, NULL);    
if (!IntEvent)
{
RETAILMSG(1, (TEXT("ERROR: kEYBD: Failed to create event.\r\n")));
return FALSE;
}

IRQ = 10; //IRQ_TIMER0;
if (!KernelIoControl(IOCTL_HAL_REQUEST_SYSINTR, &IRQ, sizeof(UINT32), &g_KeySysIntr, sizeof(UINT32), NULL))
{
RETAILMSG(1, (TEXT("ERROR: kEYBD: Failed to request sysintr value.\r\n")));
return FALSE;
}

if (!InterruptInitialize(g_KeySysIntr, IntEvent, NULL, 0))
{
RETAILMSG(1,(TEXT("Fail to initialize userkey interrupt event\r\n")));
return FALSE;
}


while(1)
{
WaitForSingleObject(IntEvent, INFINITE);

if(v_pINTRregs->INTMSK & (1<<IRQ_TIMER0))
{
RETAILMSG(1,(TEXT("TIMER_INT success\r\n")));

xinhao++;
if((xinhao>=1)&&(xinhao<=10))
{
v_pIOPregs->GPBDAT=v_pIOPregs->GPBDAT&~(0x1<<8);//LED4 亮
RETAILMSG(1,(TEXT("open\r\n")));
}
else if((xinhao>=11)&&(xinhao<=20))
{
v_pIOPregs->GPBDAT=v_pIOPregs->GPBDAT|(0x1<<8);//LED4灭
RETAILMSG(1,(TEXT("close\r\n")));
}
else
xinhao=0;


InterruptDone(g_KeySysIntr);

}
}
}



void Virtual_Alloc()
{

/* IO Register Allocation */
v_pIOPregs = (volatile S3C2440A_IOPORT_REG *) VirtualAlloc(0,sizeof(S3C2440A_IOPORT_REG),MEM_RESERVE, PAGE_NOACCESS);
if(v_pIOPregs == NULL)
{
RETAILMSG(1,(TEXT("For IOPregs: VirtualAlloc failed!\r\n")));
}
else
{
if(!VirtualCopy((PVOID)v_pIOPregs,(PVOID)(S3C2440A_BASE_REG_PA_IOPORT >> 8),sizeof(S3C2440A_IOPORT_REG), PAGE_PHYSICAL | PAGE_READWRITE | PAGE_NOCACHE))
{
RETAILMSG(1,(TEXT("For IOPregs: VirtualCopy failed!\r\n")));
}
}
 
/* INTR Register Allocation */
v_pINTRregs = (volatile S3C2440A_INTR_REG *)VirtualAlloc(0, sizeof(S3C2440A_INTR_REG), MEM_RESERVE, PAGE_NOACCESS);
if (v_pINTRregs == NULL) 
{
ERRORMSG(1,(TEXT("For INTRregs : VirtualAlloc failed!\r\n")));
}
else 
{
if (!VirtualCopy((PVOID)v_pINTRregs, (PVOID)(S3C2440A_BASE_REG_PA_INTR >> 8), sizeof(S3C2440A_INTR_REG), PAGE_PHYSICAL | PAGE_READWRITE | PAGE_NOCACHE)) 
{
ERRORMSG(1,(TEXT("For INTRregs: VirtualCopy failed!\r\n")));
}
}
/* PWM Register Allocation */
v_pPWMregs = (volatile S3C2440A_PWM_REG *)VirtualAlloc(0, sizeof(S3C2440A_PWM_REG), MEM_RESERVE, PAGE_NOACCESS);
if (v_pPWMregs == NULL) 
{
ERRORMSG(1,(TEXT("For INTRregs : VirtualAlloc failed!\r\n")));
}
else 
{
if (!VirtualCopy((PVOID)v_pPWMregs, (PVOID)(S3C2440A_BASE_REG_PA_PWM >> 8), sizeof(S3C2440A_PWM_REG), PAGE_PHYSICAL | PAGE_READWRITE | PAGE_NOCACHE)) 
{
ERRORMSG(1,(TEXT("For INTRregs: VirtualCopy failed!\r\n")));
}
}


}

BOOL WINAPI  
DllEntry(HANDLE hinstDLL, DWORD dwReason, LPVOID  Reserved/* lpvReserved */)
{
switch(dwReason)
{
case DLL_PROCESS_ATTACH:
DEBUGREGISTER((HINSTANCE)hinstDLL);
return TRUE;
case DLL_THREAD_ATTACH:
break;
case DLL_THREAD_DETACH:
break;
case DLL_PROCESS_DETACH:
break;
#ifdef UNDER_CE
case DLL_PROCESS_EXITING:
break;
case DLL_SYSTEM_STARTED:
break;
#endif
}

return TRUE;
}


BOOL INT_Deinit(DWORD hDeviceContext)
{
BOOL bRet = TRUE;

RETAILMSG(1,(TEXT("USERKEY: INT_Deinit\r\n")));
PWM_ConfigPWMDefault();
InterruptDisable(g_KeySysIntr);

CloseHandle(IntThread);
CloseHandle(IntEvent);
v_pIOPregs->GPBCON  = v_pIOPregs->GPBCON  |(3 << 16) ; // GPB8 == reserved.
v_pPWMregs->TCON &=~(1<<0);
VirtualFree((void*)v_pIOPregs, sizeof(S3C2440A_IOPORT_REG), MEM_RELEASE);
VirtualFree((void*)v_pINTRregs, sizeof(S3C2440A_INTR_REG), MEM_RELEASE);
VirtualFree((void*)v_pPWMregs,sizeof(S3C2440A_PWM_REG),MEM_RELEASE);

return TRUE;


BOOL Eint_GPIO_Init()
{
RETAILMSG(1,(TEXT("INT_GPIO_Setting----\r\n")));
v_pIOPregs->GPBCON  = (v_pIOPregs->GPBCON  &~(3 << 16)) | (1<< 16); // GPB8 == OUTPUT.
//v_pIOPregs->GPBDAT  =  v_pIOPregs->GPBDAT&~(0x1<<5);




return TRUE;
}

BOOL TIMER_Init()
{
v_pPWMregs->TCFG0&=~(0xff);
v_pPWMregs->TCFG0|=(0xfc<<0);//预分频值249
v_pPWMregs->TCFG1&=~(0xf0000f<<0);//中断、1/2

v_pPWMregs->TCNTB0&=~(0xff);//计数值
v_pPWMregs->TCNTB0|=200& 0xFFFF;//计数值为200
//v_pPWMregs->TCMPB0&=~(0xff);//占空比0

RETAILMSG(1,(TEXT("TIMER_Init----\r\n")));

v_pPWMregs->TCON &= ~0x1f; // Timer0 TCON 
v_pPWMregs->TCON = v_pPWMregs->TCON & (~0x0F) | (1 << 1); // 更新TCNTB0, TCMPB0
v_pPWMregs->TCON = v_pPWMregs->TCON & (~0x0F) | (1 << 0) | (1 << 3);    // 开启定时器,自动重载
v_pPWMregs->TCON &=~2;//clear manual update bit

return TRUE;

}
 void PWM_ConfigPWMDefault()
{

// TOUT0口设置
v_pIOPregs->GPBCON &= ~(0x03 << 0); // rGPBCON[1:0] = 00b,设置GPB0 为输入GPIO
v_pIOPregs->GPBUP &= ~(0x1 << 0); // 上拉 

v_pPWMregs->TCFG0 &= ~0xFF; // Timer0 预分频恢复为0
v_pPWMregs->TCFG1 &= ~0x0F; // MUX0

v_pPWMregs->TCON &= ~0x1F; // Timer0 TCON 
v_pPWMregs->TCNTB0 = 0; // 定时值(PWM周期)       
v_pPWMregs->TCMPB0 = 0; // 设置PWM占空比
}

DWORD INT_Init(DWORD dwContext)
{
DWORD       threadID;                         // thread ID
PROCESSOR_INFO procInfo;
DWORD dwBytesReturned;
RETAILMSG(1,(TEXT("INT_Init----\r\n")));

Virtual_Alloc();

Eint_GPIO_Init();
TIMER_Init();

//显示PCLK
if (!KernelIoControl(IOCTL_PROCESSOR_INFORMATION, NULL, 0, &procInfo, sizeof(PROCESSOR_INFO), &dwBytesReturned))
{
m_s3c2440_pclk = DEFAULT_S3C2440X_PCLK;
RETAILMSG(TRUE, (TEXT("WARNING: DAC_Init:: failed to obtain processor frequency - using default value (%d).\r\n"), m_s3c2440_pclk)); 
}
else
{
m_s3c2440_pclk = procInfo.dwClockSpeed;
RETAILMSG(TRUE, (TEXT("INFO: DAC_Init:: using processor frequency reported by the OAL (%d).\r\n"), m_s3c2440_pclk)); 
}
RETAILMSG(1, (TEXT("m_s3c2440_pclk  is %d).\r\n"), m_s3c2440_pclk)); 


//创建中断服务线程
IntThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)IntProcessThread, 0, 0, &threadID);

if (NULL == IntThread )
{
RETAILMSG(1,(TEXT("ERROR: failed to Create Key Thread!\r\n")));
return FALSE;
}
return TRUE;
}

//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
BOOL INT_IOControl(DWORD hOpenContext, DWORD dwCode, PBYTE pBufIn, DWORD dwLenIn, PBYTE pBufOut, DWORD dwLenOut, PDWORD pdwActualOut)
{
return TRUE;


//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
DWORD INT_Open(DWORD hDeviceContext, DWORD AccessCode, DWORD ShareMode)
{
return TRUE;


//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
BOOL INT_Close(DWORD hOpenContext)
{
PWM_ConfigPWMDefault();

return TRUE;


//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
void INT_PowerDown(DWORD hDeviceContext)
{



//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
void INT_PowerUp(DWORD hDeviceContext)
{
RETAILMSG(1,(TEXT("USERKEY: INT_PowerUp\r\n")));


//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
DWORD INT_Read(DWORD hOpenContext, LPVOID pBuffer, DWORD Count)
{
RETAILMSG(1,(TEXT("USERKEY: INT_Read\r\n")));
return TRUE;


//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
DWORD INT_Seek(DWORD hOpenContext, long Amount, DWORD Type)
{
return 0;


//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
DWORD INT_Write(DWORD hOpenContext, LPCVOID pSourceBytes, DWORD NumberOfBytes)
{
return 0;
}


2 个解决方案

#1


串口打印信息表明进入了中断,示波器显示出矩形波,但是频率为0.33hz.奇怪的是,不管我怎么改变TCFG0,TCFG1以及TCMPB0的值,定时器输出的频率都没有改变。

#2


还有我使用的是动态加载流驱动的方式。请路过的高手指点一下吧!

#1


串口打印信息表明进入了中断,示波器显示出矩形波,但是频率为0.33hz.奇怪的是,不管我怎么改变TCFG0,TCFG1以及TCMPB0的值,定时器输出的频率都没有改变。

#2


还有我使用的是动态加载流驱动的方式。请路过的高手指点一下吧!