6255|13

1

帖子

0

TA的资源

一粒金砂(初级)

楼主
 

第一次写驱动程序,无法读写硬件,请高手指点! [复制链接]

我把周立功的实验教材上的流接口驱动程序的例子进行了修改,加入了写硬件的部分,但是驱动程序无法读写硬件,请高手帮我分析一下。
测试程序中只用到了写函数,,目的是往硬件里写数据,从串口打印的信息显示数据正确,但是硬件里没反应。

#include
#include
#include
#include

#pragma comment(lib,"ceddk.lib")

#define IOP_BASE      0xB0000000 // 0x38000000虚拟地址

static BYTE g_Tmp=0;
static DWORD g_OpenCount=0;
PHYSICAL_ADDRESS phyAdd1={0xB0000000,0x0};       

PVOID m_pCS8900IoPort1;
short  *ptPA,*ptPB,*ptPC,*ptCTRL;
int IOPA,IOPB,IOPC;

int BOrCReadFlag=0;//默认B口读


BOOL WINAPI DllEntry(HANDLE hInstDll,DWORD dwReason,LPVOID lpvReserved)
{
        switch(dwReason)
        {
        case DLL_PROCESS_ATTACH://提示驱动程序加载
                RETAILMSG(1,(TEXT("IOP:DLL_PROCESS_ATTACH.\r\n")));
                DisableThreadLibraryCalls((HMODULE)hInstDll);
                break;
        case DLL_PROCESS_DETACH://提示驱动程序卸载
                RETAILMSG(1,(TEXT("IOP:DLL_PROCESS_DETACH.\r\n")));
                break;
        }
        return(TRUE);
}


DWORD IOP_Init(DWORD dwContext)//可以将映射物理地址到虚拟地址工作放在这里
{
        RETAILMSG(1,(TEXT("IOP_Init.\r\n")));
        g_Tmp=0;
        g_OpenCount=0;
        BOOL        RetValue = TRUE;
//        m_pCS8900IoPort1=MmMapIoSpace(phyAdd1,0x100,TRUE);
        m_pCS8900IoPort1 = (PVOID)VirtualAlloc(0, 0xff, MEM_RESERVE, PAGE_NOACCESS);//地址映射部分       
         if (m_pCS8900IoPort1 == NULL)
        {
                ERRORMSG(1,(TEXT("For ADCregs : VirtualAlloc failed!\r\n")));
                RetValue = FALSE;
        }
        else
        {
                if (!VirtualCopy((PVOID)m_pCS8900IoPort1 ,(PVOID)(IOP_BASE), 0xff, PAGE_READWRITE | PAGE_NOCACHE))
                {
                        ERRORMSG(1,(TEXT("For m_pCS8900IoPort: VirtualCopy failed!\r\n")));
                        RetValue = FALSE;
                }
        }
        if (!RetValue)
        {
                RETAILMSG (1, (TEXT(":::InitializeAddresses - Fail!!\r\n") ));
               
                if (m_pCS8900IoPort1)
                {
                        VirtualFree((PVOID) m_pCS8900IoPort1, 0, MEM_RELEASE);
                }
               
                m_pCS8900IoPort1 = NULL;
        }
        else RETAILMSG (1, (TEXT(":::InitializeAddresses - Success\r\n") ));       
        ptPA                =(short *)m_pCS8900IoPort1+0+16 ;//默认是读写第一块板子
        ptPB                =(short *)m_pCS8900IoPort1+2+16;
        ptPC                =(short *)m_pCS8900IoPort1+4+16 ;
        ptCTRL                =(short *)m_pCS8900IoPort1+6+16 ;
        *ptCTRL                =0x8B;// 1 0 0 0 1 0 1 1
        //                         | |   | |______C口读下半段
    //                         | |   |________B口读
        //                         | |____________C口读上半段
        //                         |______________A口写

        return 1;
}


BOOL IOP_Deinit(DWORD dwContext)//当然,这里应该取消物理地址与虚拟地址的映射
{
        RETAILMSG(1,(TEXT("IOP_Deinit.\r\n")));

        g_Tmp=0;
        g_OpenCount=0;

//        MmUnmapIoSpace(m_pCS8900IoPort1,0x100);       
        if (m_pCS8900IoPort1)
        {
                VirtualFree((PVOID) m_pCS8900IoPort1, 0, MEM_RELEASE);
        }
        return TRUE;
}

DWORD IOP_Open(DWORD hDeviceContext,DWORD AccessCode,DWORD ShareMode)
{
        RETAILMSG(1,(TEXT("IOP:Open.\r\n")));//提示驱动程序打开

        //不允许多次打开驱动
        if(g_OpenCount!=0)
        {
                RETAILMSG(1,(TEXT("IOP has been Opened.\r\n")));
                return 0;
        }
        g_OpenCount++;
        char array[20];
        sprintf(array,"  c o d e = %x %x \r\n\0\0",AccessCode/10,AccessCode-AccessCode/10);
        RETAILMSG(1,((const unsigned short *)array));
        if(AccessCode>=0&&AccessCode<=7)
        {
                ptPA                =(short *)m_pCS8900IoPort1+0 +(int)(AccessCode)* 16;
                ptPB                =(short *)m_pCS8900IoPort1+2+(int)(AccessCode)* 16;
                ptPC                =(short *)m_pCS8900IoPort1+4 +(int)(AccessCode)* 16;
                ptCTRL                =(short *)m_pCS8900IoPort1+6 +(int)(AccessCode)* 16;
        }
        *ptCTRL                =0x8B;
        Sleep(20);
        return g_OpenCount;
}

BOOL IOP_Close(DWORD hOpenContext)
{
        RETAILMSG(1,(TEXT("IOP_Close.\r\n")));//提示驱动关闭
        if(g_OpenCount!=0)
                g_OpenCount--;//驱动打开计数器减1
        ptPA                =(short *)m_pCS8900IoPort1+0 ;
        ptPB                =(short *)m_pCS8900IoPort1+1 ;
        ptPC                =(short *)m_pCS8900IoPort1+2 ;
        ptCTRL                =(short *)m_pCS8900IoPort1+3 ;
        return TRUE;
}

BOOL IOP_IOControl(DWORD hOpenContext,
                                   DWORD dwCode,
                                   PBYTE pBufIn,
                                   DWORD dwLenIn,
                                   PBYTE pBufOut,
                                   DWORD dwLenOut,
                                   PDWORD pdwActualOut
                                   )
{
        RETAILMSG(1,(TEXT("IOP_IOControl.\r\n")));//提示i/O请求函数执行
        switch(dwCode)
        {
        case 0:
                //读B口数据
                BOrCReadFlag=0;
                break;
        case 1:
                //读C口数据
                BOrCReadFlag=0;
                break;
        default:
                RETAILMSG(1,(TEXT("IOP_IOControl() parameter is error.\r\n")));//提示i/O请求函数执行
                break;
        }
        return TRUE;
}

void IOP_PowerUp(void)
{
        RETAILMSG(1,(TEXT("IOP_PowerUp.\r\n")));

}

void IOP_PowerDown(void)
{
        RETAILMSG(1,(TEXT("IOP_PowerDown.\r\n")));

}


DWORD IOP_Read(DWORD hOpenContext,LPVOID pBuffer,DWORD Count)
{
//        uchar * pReadBuffer;

        RETAILMSG(1,(TEXT("IOP_Read.\r\n")));
        if((pBuffer==NULL)||(Count<=0))
        {
                RETAILMSG(1,(TEXT("IOP_Read() parameter is error.\r\n")));
                return 0;
        }
        //pReadBuffer=MapPtrToProcess((uchar *)pBuffer,GetCallerProcess());
//        pBuffer=pReadBuffer;
        if(BOrCReadFlag==0)
                pBuffer=(LPVOID *)((*ptPB)&0x0FF);
        if(BOrCReadFlag==1)
                pBuffer=(LPVOID *)((*ptPC)&0x0FF);
        return 1;
}


DWORD IOP_Write(DWORD hOpenContext,LPVOID pBuffer,DWORD Count)
{
        uchar * pWriteBuffer;
        char array[20];
        RETAILMSG(1,(TEXT("IOP_Write.\r\n")));
        if((pBuffer==NULL)||(Count<=0))
        {
                RETAILMSG(1,(TEXT("IOP_Write() parameter is error.\r\n")));
                return 0;
        }
//        sprintf(array,"  p B u f = %x %x \r\n",(* pBuffer)/16,(pBuffer)-(pBuffer)/16);
//        RETAILMSG(1,((const unsigned short *)array));
//        pWriteBuffer=MapPtrToProcess((LPVOID)pBuffer,GetCallerProcess());
        pWriteBuffer=(uchar *)pBuffer;
        *ptPA=*pWriteBuffer;
        *ptPB=*pWriteBuffer;
        *ptPC=*pWriteBuffer;
        Sleep(100);
        sprintf(array,"  p t p a = %x %x \r\n",(*ptPA)/16,(*ptPA)-(*ptPA)/16;//从串口打印数据,显示的数据正确,但是不能写到硬件
        RETAILMSG(1,((const unsigned short *)array));
        return 1;
}

DWORD IOP_Seek(DWORD hOpenContext,long Amount,DWORD Type)
{
        RETAILMSG(1,(TEXT("IOP_Seek.\r\n")));
        return 0;

}

最新回复

没人回复了,无奈中结贴  详情 回复 发表于 2009-6-3 09:24
点赞 关注

回复
举报

2

帖子

0

TA的资源

一粒金砂(初级)

沙发
 
首先明确一点IOP_BASE应该是物理地址而不是虚拟地址
其次使用VirtualCopy时,最后一个参数最好或上PAGE_PHYSICAL,然后将第二个参数IOP_BASE右移8位后强制类型转换成void *
原因见函数原型说明如下:

BOOL VirtualCopy(
LPVOID lpvDest,
LPVOID lpvSrc,
DWORD cbSize,
DWORD fdwProtect
);

Parameters

lpvDest
    [in] Pointer to the destination memory, which must be reserved.
lpvSrc
    [in] Pointer to committed memory.
cbSize
    [in] Size, in bytes, of the region. The allocated pages include all pages containing one or more bytes in the range from lpAddress to lpAddress+cbSize. This means that a 2-byte range straddling a page boundary causes both pages to be included in the allocated region.


fdwProtect
    [in] Type of access protection. If the pages are being committed, any one of a number of flags can be specified, along with the PAGE_GUARD and PAGE_NOCACHE, protection modifier flags. The following table shows the flags that can be specified.
    Value         Description
    PAGE_READONLY         Enables read access to the committed region of pages. An attempt to write to the committed region results in an access violation. If the system differentiates between read-only access and execute access, an attempt to execute code in the committed region results in an access violation.
    PAGE_READWRITE         Enables both read and write access to the committed region of pages.
    PAGE_EXECUTE         Enables execution access to the committed region of pages. An attempt to read or write to the committed region results in an access violation.
    PAGE_EXECUTE_READ         Enables execute and read access to the committed region of pages. An attempt to write to the committed region results in an access violation.
    PAGE_EXECUTE_READWRITE         Enables execute, read, and write access to the committed region of pages.
    PAGE_GUARD         Pages in the region become guard pages. Any attempt to read from or write to a guard page causes the operating system to raise the STATUS_GUARD_PAGE exception and turn off the guard page status. Guard pages thus act as a one-shot access alarm.

    The PAGE_GUARD flag is a page protection modifier. An application uses it with one of the other page protection flags, with one exception: it cannot be used with PAGE_NOACCESS.

    When an access attempt leads the operating system to turn off guard page status, the underlying page protection takes over.

    If a guard page exception occurs during a system service, the service typically returns a failure status indicator.
    PAGE_NOACCESS         Disables all access to the committed region of pages. An attempt to read from, write to, or execute in the committed region results in an access violation exception, called a general protection (GP) fault.
    PAGE_NOCACHE         Allows no caching of the committed regions of pages. The hardware attributes for the physical memory should be specified as no cache. It is useful for device drivers; when, for example, mapping a video frame buffer with no caching. This flag is a page protection modifier and is valid only when used with one of the page protections other than PAGE_NOACCESS.
    PAGE_PHYSICAL         [b]Used to map a physical memory region. When using this flag, divide the physical address — that is, lpvSrc — by 256. Memory mapped with PAGE_PHYSICAL is not freed until the device is rebooted. Calling VirtualFree will not free this mapped physical memory. PAGE_PHYSICAL is intended for use with dedicated hardware buffers, so it cannot be freed after being mapped.
 
 

回复

4

帖子

0

TA的资源

一粒金砂(初级)

板凳
 
uping
 
 
 

回复

4

帖子

0

TA的资源

一粒金砂(初级)

4
 
// m_pCS8900IoPort1=MmMapIoSpace(phyAdd1,0x100,TRUE);
//这行为什么被注释掉???


m_pCS8900IoPort1 = (PVOID)VirtualAlloc(0, 0xff, MEM_RESERVE, PAGE_NOACCESS);//地址映射部分
//映射地址,必须是VirtualCopy和VirtualAlloc一起使用。MmMapIoSpace中就是使用了这两个函数。
 
 
 

回复

1

帖子

0

TA的资源

一粒金砂(初级)

5
 
回一楼:
   我试了一下,将IOP_BASE改成其物理地址:0X38000000;(映射成虚拟地址是0X9000 0000)
VirtuaCopy中的两个参数都改了,结果驱动程序装载之后发生了异常。
回三楼:
   开始写程序时使用的是上面的函数,结果不能通过编译,然后改成了
下面的一段代码,就可以通过编译。所以上面一行注释了。


哦,操作系统是 Windows ce.NET

谢谢!
 
 
 

回复

1

帖子

0

TA的资源

一粒金砂(初级)

6
 
我感觉应该是地址映射方面的问题,因为从串口打印出的数据信息来看,
数据都送到驱动程序里面也可以显示正确,但是就是不能写到硬件里面,
望能帮我解决。
 
 
 

回复

6

帖子

0

TA的资源

一粒金砂(初级)

7
 
uping
 
 
 

回复

1

帖子

0

TA的资源

一粒金砂(初级)

8
 
最好把你修改之后的代码贴出来
 
 
 

回复

3

帖子

0

TA的资源

一粒金砂(中级)

9
 
“开始写程序时使用的是上面的函数,结果不能通过编译,然后改成了”,估计是提示“无法找到VirtualAlloc”才错误。因为只要调用的函数存在,哪怕你传错的值,都不会编译不过,只是运行出错而已。
这个函数要链接并且包含头文件的,跟VirtualCopy不一样。
 
 
 

回复

1

帖子

0

TA的资源

禁止访问

10
 
提示: 作者被禁止或删除 内容自动屏蔽
 
 
 

回复

1

帖子

0

TA的资源

一粒金砂(初级)

11
 
mark
 
 
 

回复

4

帖子

0

TA的资源

禁止访问

12
 
提示: 作者被禁止或删除 内容自动屏蔽
 
 
 

回复

4

帖子

0

TA的资源

一粒金砂(初级)

13
 
学习关注中!
 
 
 

回复

1

帖子

0

TA的资源

一粒金砂(初级)

14
 
没人回复了,无奈中结贴
 
 
 

回复
您需要登录后才可以回帖 登录 | 注册

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/6 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表