STM32 USB 上位机驱动和应用简单图例
新近项目需要,简单研究下STM32 USB的应用,power avr的开发板,CPU是stm32103rbt6。
Firmware我就不说了,stm的usb开发包有例子,直接在框架的基础上修改。这里以图片的形式讨论上位机的驱动和应用程序的简单过程。
1.开发环境的配置可以搜索下先辈的经验,我用的是winddk2600+driverstudio3.2+vc6。
2.打开driverstudio的开始菜单ddk build setting然后launch program启动开发环境。
3.开始driverwizard。
4.然后顺序完成以下12项设置。
5.然后会在vc插入ds自动生成的框架。包括驱动和app。
6.驱动需要修改的有两个地方:
1)是bug,10进制改成16进制;
2)是读写read,write或者iocontrol函数。根据需要,注意读写的方式,有的是直接IO,有的是
buffer IO,还有其他的类型,这些的区别建议阅读有关windows驱动的书籍。另外这里的读写函数
是同步的,用linux的话是阻塞类型,所以没有用到完成例程或者异步的机制,需要的话也请参考有关
书籍。
///////////////////////////////////////////////////////////////////////////////////////////////////
// USB_DemoDevice::Read
// Dispatch routine for IRP_MJ_READ requests.
//
// Arguments:
// IN I
// the read IRP
//
// Return Value:
// NTSTATUS
//
NTSTATUS USB_DemoDevice::Read(KIrp I)
{
T.Trace(TraceInfo, __FUNCTION__"++. IRP %p\n", I);
NTSTATUS status = STATUS_SUCCESS;
// TODO: Validate the parameters of the IRP. Replace "FALSE"
// in the following line with error checking code that
// evaulates to TRUE if the request is not valid.
if (FALSE)
{
status = STATUS_INVALID_PARAMETER;
I.Information() = 0;
I.PnpComplete(status);
T.Trace(TraceWarning, __FUNCTION__"--. IRP %p, STATUS %x\n", I, status);
return status;
}
// Always ok to read 0 elements
if (I.ReadSize() == 0)
{
I.Information() = 0;
I.PnpComplete(this, status);
T.Trace(TraceInfo, __FUNCTION__"--. IRP %p, STATUS %x\n", I, status);
return status;
}
KMemory Mem(I.Mdl()); // Declare a memory object
// Get a pointer to the caller's buffer. Note that this
// routine is safe on all platforms.
PUCHAR pBuffer = (PUCHAR) Mem.MapToSystemSpace();
ULONG readSize = I.ReadSize();
ULONG bytesRead = 0;
// TODO: At this point, perform any processing for IRP_MJ_READ
// To satisfy the read now, transfer data from the driver
// to the caller's buffer at "pBuffer". Then, indicate
// how much data was transferred:
PURB pUrb = EP2_IN.BuildInterruptTransfer(
pBuffer,
readSize,
TRUE,
NULL,
NULL,
TRUE);
if (pUrb == NULL)
{
status = STATUS_INSUFFICIENT_RESOURCES;
}
else
{
status = EP2_IN.SubmitUrb(pUrb,NULL,NULL,0);//100MS
bytesRead = pUrb->UrbBulkOrInterruptTransfer.TransferBufferLength;//pUrb->UrbInterruptTransfer.TransferBufferLength;
delete pUrb;
}
I.Information() = bytesRead;
I.PnpComplete(this, status);
T.Trace(TraceInfo, __FUNCTION__"--. IRP %p, STATUS %x\n", I, status);
return status;
}
///////////////////////////////////////////////////////////////////////////////////////////////////
// USB_DemoDevice::Write
// Dispatch routine for IRP_MJ_WRITE requests.
//
// Arguments:
// IN I
// the write IRP
//
// Return Value:
// NTSTATUS
//
NTSTATUS USB_DemoDevice::Write(KIrp I)
{
T.Trace(TraceInfo, __FUNCTION__"++. IRP %p\n", I);
NTSTATUS status = STATUS_SUCCESS;
// TODO: Validate the parameters of the IRP. Replace "FALSE"
// in the following line with error checking code that
// evaulates to TRUE if the request is not valid.
if (FALSE)
{
status = STATUS_INVALID_PARAMETER;
I.Information() = 0;
I.PnpComplete(status);
T.Trace(TraceWarning, __FUNCTION__"--. IRP %p, STATUS %x\n", I, status);
return status;
}
// Always ok to write 0 elements
if (I.WriteSize() == 0)
{
I.Information() = 0;
I.PnpComplete(this, status);
T.Trace(TraceInfo, __FUNCTION__"--. IRP %p, STATUS %x\n", I, status);
return status;
}
KMemory Mem(I.Mdl()); // Declare a memory object
// Get a pointer to the caller's buffer. Note that this
// routine is safe on all platforms.
PUCHAR pBuffer = (PUCHAR) Mem.MapToSystemSpace();
ULONG writeSize = I.WriteSize();
ULONG bytesSent = 0;
// TODO: At this point, perform any processing for IRP_MJ_WRITE
// To satisfy the write now, transfer data to the driver
// from the caller's buffer at "pBuffer". Then, indicate
// how much data was transferred:
PURB pUrb = EP1_OUT.BuildInterruptTransfer(
pBuffer,
writeSize,
TRUE,
NULL,
NULL,
FALSE);
if (pUrb == NULL)
{
status = STATUS_INSUFFICIENT_RESOURCES;
}
else
{
status = EP1_OUT_Out.SubmitUrb(pUrb,NULL,NULL,0);
bytesSent = pUrb->UrbBulkOrInterruptTransfer.TransferBufferLength;//pUrb->UrbInterruptTransfer.TransferBufferLength;
delete pUrb;
}
I.Information() = bytesSent;
I.PnpComplete(this, status);
T.Trace(TraceInfo, __FUNCTION__"--. IRP %p, STATUS %x\n", I, status);
return status;
}
7.然后build with build exe,生成驱动的sys和inf,以及app的exe测试程序。
8.插入硬件,stm32的开发板,系统提示安装驱动。
9.选择手动安装,指定路径。
10.安装成功
11.打开bus hound测试下。
12.选择端点1写入GOOG,bus hound会捕捉到写入的请求和数据。
13.选择端点2读入4字节数据。
14.好,现在打开driverstudio生成的测试应用程序,写入4字节数据。
15.完
下面是简单的应用,开发板上的两个按键和两个LED,读取按键的状态,控制LED的亮灭。
很简单吧?!
用户958884 2012-8-25 13:56