当前位置:首页 > 模拟 > 模拟
[导读]把它写成了实验报告的样子! 在此BLOG中的有些函数是针对特定的BSP, 比如:地址的映射函数, 在每一个BSP中它的地址映射函数都不同, 但是都是地址映射(废话当然是地址映射了)。其实里面有很多的东西都还可以添加

把它写成了实验报告的样子! 在此BLOG中的有些函数是针对特定的BSP, 比如:地址的映射函数, 在每一个BSP中它的地址映射函数都不同, 但是都是地址映射(废话当然是地址映射了)。其实里面有很多的东西都还可以添加:比如添加读取LED信息状态, 优化地址映射(不必把全部的GPIO都映射, 可以自定义一个小的结构体来实现)。
一. 实验目的
a) 掌握流驱动的结构
b) 掌握一般流驱动的编写方法

二. 实验设备
a) S3C6410 开发板一台
b) PC 机一台, VS2005, CE6.0 环境

三. 实验内容
a) 进行简单 LED 驱动的编写。

四. 实验原理
a) 硬件原理图
i.
ii.
iii. 从原理图可以知道如果我们要点亮 LEDx , 只需要 GPMx 输出高电平, 如果要熄灭 LEDx , 只需要 GPMx 输出低电平即可。

b) 软件原理设计
i. 由于在 WINCE 中使用都是虚拟的地址, 所以需要将实际的物理地址转换为虚拟地址来使用。 在系统提供的 BSP 中提供了一个函数来实现从物理地址到虚拟地址的映射。
1. void *DrvLib_MapIoSpace (UINT32 PhysicalAddress , UINT32 NumberOfBytes , BOOL CacheEnable )
2. 把物理地址转换为虚拟地址。(其实它就是在地址映射表中查找相应的物理地址,然后返回对应的虚拟地址加上它的偏移。)
3. UINT32 PhysicalAddress :要实现映射的物理地址的起始地址。
4. UINT32 NumberOfBytes : 要映射物理地址的长度。
5. BOOL CacheEnable :该物理地址是否使用了CACHE.( 具体参照地址映射表) 。
ii. LED 上下文结构体的定义
1. 定义了一个 LED 驱动的上下文, 用来保存 LED 驱动的信息。 但是只是简单的 LED 驱动, 没有包含多的数据。
typedef struct
{
volatile S3C6410_GPIO_REG *pGPIOReg ;
}LED_PUBLIC_CONTEXT , *PLED_PUBLIC_CONTEXT ;
2 . S3C6410_GPIO_REG 是BSP 预先定义的一个GPIO 使用的数据结构。
iii. GPIO 寄存器的使用。 GPIO 寄存器的地址都映射到了虚拟的地址上。 BSP 提供了一个结构体方便 GPIO 寄存器的使用。
1. typedef struct
{ ……………..
UINT32 GPMCON; // 820
UINT32 GPMDAT; // 824
UINT32 GPMPUD; // 828
………………..
} S3C6410_GPIO_REG, *PS3C6410_GPIO_REG;
2. 在使用这个结构全的时候把 GPIO 的虚拟地址的基地址映射到此结构的开始即可以操作此结构体的数据来操作实际的寄存器。
3. 进行GPIO 物理地址到虚拟地址的映射: pLedContext ->pGPIOReg = (volatile S3C6410_GPIO_REG *)DrvLib_MapIoSpace (S3C6410_BASE_REG_PA_GPIO , sizeof (S3C6410_GPIO_REG ), FALSE ) ;
iv. 实现 LED 灯状态的操作。
1. 获得了 GPIO 的虚拟地址就可以像实际的物理地址那样实现寄存器的操作。
2.
a) // 使能上拉
b) pLedContext ->pGPIOReg ->GPMPUD |= 0x0ff;
c) // 设置为输出
d) pLedContext ->pGPIOReg ->GPMCON = 0x111111;
e) // 关闭所有的LED
f) LED_ALL_OFF (pLedContext ->pGPIOReg ->GPMDAT );
3. 为了方便进行操作,定义了一组宏。
// 打开或关闭LED0
#define LED0_ON (x ) (x |= 0x00000001)
#define LED0_OFF (x ) (x &= 0xfffffffe)
// 打开或关闭LED1
#define LED1_ON (x ) (x |= 0x00000002)
#define LED1_OFF (x ) (x &= 0xfffffffd)
// 打开或关闭LED2
#define LED2_ON (x ) (x |= 0x00000004)
#define LED2_OFF (x ) (x &= 0xfffffffb)
// 打开或关闭LED3
#define LED3_ON (x ) (x |= 0x00000008)
#define LED3_OFF (x ) (x &= 0xfffffff7)
// 打开或关闭所有的LED
#define LED_ALL_ON (x ) (x |= 0x0000000f)
#define LED_ALL_OFF (x ) (x &= 0xfffffff0)
五. 实验步骤
a) Xxx_Init 函数的原型:
i. DWORD XXX_Init( LPCTSTR pContext , DWORD dwBusContext );
ii. pContext: Pointer to a string containing the registry path to the active key for the stream interface driver.
iii. lpvBusContext: Potentially process-mapped pointer passed as the fourth parameter to ActivateDeviceEx . If this driver was loaded through legacy mechanisms, then dwBusContext is zero. This pointer, if used, has only been mapped again as it passes through the protected server library (PSL). The XXX _Init function is responsible for performing all protection checking
iv. 返回值 : Returns a handle to the device context created if successful. Returns zero if not successful. This handle is passed to the XXX_Open (Device Manager) , XXX_PowerDown (Device Manager) , XXX_PowerUp (Device Manager) , and XXX_Deinit (Device Manager) functions
v. 注意:当调用 设备管理程序当调用 ActivateDeviceEx 函数的时候会间接调用到此函数, ActivateDeviceEx 的作用就是加载设备
vi. LED_Init 函数的编写。 LED_Init 最主要的功能就是进行硬件的初使化。
vii. LED_Init 函数的实现:
DWORD Led_Init (LPCTSTR pContext )
{
volatile PLED_PUBLIC_CONTEXT pLedContext ;

RETAILMSG (DEBUG_LED ,(TEXT ("Led_Init Function!/n" )));

// 申请LED 的CONTEXT
pLedContext = (PLED_PUBLIC_CONTEXT )LocalAlloc (LPTR , sizeof (pContext ));
if (!pLedContext )
{
RETAILMSG (DEBUG_LED , (TEXT ("Can't alloc memory for led context!/n" )));
return NULL ;
}

// 得到GPIO 寄存器的地址
pLedContext ->pGPIOReg = (volatile S3C6410_GPIO_REG *)DrvLib_MapIoSpace (S3C6410_BASE_REG_PA_GPIO , sizeof (S3C6410_GPIO_REG ), FALSE );
if (pLedContext ->pGPIOReg == NULL )
{
RETAILMSG (DEBUG_LED , (TEXT ("LED for pGPIORges: DrvLib_MapIoSpace failed!/n" )));
LocalFree (pLedContext );
return NULL ;
}

// 使能上拉
pLedContext ->pGPIOReg ->GPMPUD |= 0x0ff;
// 设置为输出
pLedContext ->pGPIOReg ->GPMCON = 0x111111;
// 关闭所有的LED
LED_ALL_OFF (pLedContext ->pGPIOReg ->GPMDAT );
RETAILMSG (DEBUG_LED , (TEXT ("Led0 on! %d!/n" ), (pLedContext ->pGPIOReg ->GPMDAT )));

return pLedContext ;
` }
a) Xxx_Write 函数原型:
DWORD XXX_Write(DWORD
hOpenContext
, LPCVOID
pBuffer
, DWORD
Count
);


i. hOpenContext : Handle to the open context of the device. The call to the XXX_Open (Device Manager) function returns this identifier 。
ii. pBuffer : Pointer to the buffer that contains the data to write.
iii. Count: Number of bytes to write from the pBuffer buffer into the device.
iv. 返回值: The number of bytes written indicates success. A value of –1 indicates failure.
v. LED_Write 函数的作用只是进行对 LED 状态的写入。
自定义结构体:
typedef struct
{
unsigned char cLedNum ;
unsigned char fLedStatue ;
}LED_DATA , *PLED_DATA ;
cLedNum :LED 的标号。0 对应第一个LED, 1 对应第2 个LED … 4 表示全部熄灭(因为它只有4 个LED )
fLegStatue :将要实现的操作。 0 熄灭, 1 点亮。
vi. LED_Write 函数的实现。
DWORD Led_Write (DWORD hOpenContext ,
DWORD pBuffer ,
DWORD Count )
{
PLED_DATA pLedData = (PLED_DATA )pBuffer ;
RETAILMSG (DEBUG_LED , (TEXT ("Current hOpenContext %d /n" )), hOpenContext );
RETAILMSG (DEBUG_LED , (TEXT ("Corrent GPMDATA %d!/n" ), (((PLED_PUBLIC_CONTEXT )hOpenContext )->pGPIOReg ->GPMDAT )));

switch (pLedData ->cLedNum )
{
case 0:
if (pLedData ->fLedStatue )
{
LED0_ON (((PLED_PUBLIC_CONTEXT )hOpenContext )->pGPIOReg ->GPMDAT );
RETAILMSG (DEBUG_LED , (TEXT ("Led0 on! %d/n!" ), ((PLED_PUBLIC_CONTEXT )hOpenContext )->pGPIOReg ->GPMDAT ));
}
else
{
LED0_OFF (((PLED_PUBLIC_CONTEXT )hOpenContext )->pGPIOReg ->GPMDAT );
RETAILMSG (DEBUG_LED , (TEXT ("Led0 off!/n!" )));
}
break ;
case 1:
。。。。。。
break ;
case 2:
。。。。。。
break ;
case 3:
。。。。。。
case 4:
if (pLedData ->fLedStatue )
{ LED_ALL_ON (((PLED_PUBLIC_CONTEXT )hOpenContext )->pGPIOReg ->GPMDAT );
}
else
{ LED_ALL_OFF (((PLED_PUBLIC_CONTEXT )hOpenContext )->pGPIOReg ->GPMDAT );
}
default :
break ;
}

return (Count );
}

b) 其它流接口函数的编写:其它的流接口函数并没有实现函数过程, 它们一般就直接返回。在Led_Deinit 函数中进行了申请内存的释放,也调用了一个放弃映射的函数DrvLib_UnmapIoSpace , 其实这个函数在6.0 之中没有作用, 它是直接返回结果的函数。
c) LED 的配置:
设备管理器要使用LED 流驱动的接口,就必须将LED 提供的接口函数导出。在Led.def 文件中添加如下代码:
LIBRARY LED

EXPORTS Led_Init
Led_Deinit
Led_Open
Led_Close
Led_Read
Led_Write
Led_Seek
Led_PowerDown
Led_PowerUp
Led_IOControl

导出了LED 的接口函数,要把Led.dll 添加到镜像文件中去还要修改platform.bib 文件。

在 MODULES 节中添加代码如图:


最后修改注册表 platform.reg :
HKEY_LOCAL_MACHINE/Drives/BuildIn 下添加注册表项 LED( 任意名字都可 )
注册表项中的内容:

六. 实验结果及分析
a) 按照上述步骤进行 LED 流驱动的编写, 再编写一个简单的应用程序即可进行 LED 灯的控制。

 

本站声明: 本文章由作者或相关机构授权发布,目的在于传递更多信息,并不代表本站赞同其观点,本站亦不保证或承诺内容真实性等。需要转载请联系该专栏作者,如若文章内容侵犯您的权益,请及时联系本站删除。
换一批
延伸阅读

9月2日消息,不造车的华为或将催生出更大的独角兽公司,随着阿维塔和赛力斯的入局,华为引望愈发显得引人瞩目。

关键字: 阿维塔 塞力斯 华为

加利福尼亚州圣克拉拉县2024年8月30日 /美通社/ -- 数字化转型技术解决方案公司Trianz今天宣布,该公司与Amazon Web Services (AWS)签订了...

关键字: AWS AN BSP 数字化

伦敦2024年8月29日 /美通社/ -- 英国汽车技术公司SODA.Auto推出其旗舰产品SODA V,这是全球首款涵盖汽车工程师从创意到认证的所有需求的工具,可用于创建软件定义汽车。 SODA V工具的开发耗时1.5...

关键字: 汽车 人工智能 智能驱动 BSP

北京2024年8月28日 /美通社/ -- 越来越多用户希望企业业务能7×24不间断运行,同时企业却面临越来越多业务中断的风险,如企业系统复杂性的增加,频繁的功能更新和发布等。如何确保业务连续性,提升韧性,成...

关键字: 亚马逊 解密 控制平面 BSP

8月30日消息,据媒体报道,腾讯和网易近期正在缩减他们对日本游戏市场的投资。

关键字: 腾讯 编码器 CPU

8月28日消息,今天上午,2024中国国际大数据产业博览会开幕式在贵阳举行,华为董事、质量流程IT总裁陶景文发表了演讲。

关键字: 华为 12nm EDA 半导体

8月28日消息,在2024中国国际大数据产业博览会上,华为常务董事、华为云CEO张平安发表演讲称,数字世界的话语权最终是由生态的繁荣决定的。

关键字: 华为 12nm 手机 卫星通信

要点: 有效应对环境变化,经营业绩稳中有升 落实提质增效举措,毛利润率延续升势 战略布局成效显著,战新业务引领增长 以科技创新为引领,提升企业核心竞争力 坚持高质量发展策略,塑强核心竞争优势...

关键字: 通信 BSP 电信运营商 数字经济

北京2024年8月27日 /美通社/ -- 8月21日,由中央广播电视总台与中国电影电视技术学会联合牵头组建的NVI技术创新联盟在BIRTV2024超高清全产业链发展研讨会上宣布正式成立。 活动现场 NVI技术创新联...

关键字: VI 传输协议 音频 BSP

北京2024年8月27日 /美通社/ -- 在8月23日举办的2024年长三角生态绿色一体化发展示范区联合招商会上,软通动力信息技术(集团)股份有限公司(以下简称"软通动力")与长三角投资(上海)有限...

关键字: BSP 信息技术
关闭
关闭