#include "USB.h"
#include "USB_Desc.h"
#include "usb_hid.h"
#include "usb_cdc.h"
//BDT缓冲区,理论上只要申请512字节,但是由于缓冲区地址的低9位必须为0(不然USB模块无法使用)
//所以申请1024从中找出地址低9位为0的缓冲区地址作为首地址。
__align(512) tBDT tBDTtable[16]; //内部SRAM内存池
//各个端点的数据缓冲区
u8 gu8EP0_OUT_ODD_Buffer[EP0_SIZE];
u8 gu8EP0_OUT_EVEN_Buffer[EP0_SIZE];
u8 gu8EP0_IN_ODD_Buffer[EP0_SIZE];
u8 gu8EP0_IN_EVEN_Buffer[EP0_SIZE];
u8 gu8EP1_OUT_ODD_Buffer[EP1_SIZE];
u8 gu8EP1_OUT_EVEN_Buffer[EP1_SIZE];
u8 gu8EP1_IN_ODD_Buffer[EP1_SIZE];
u8 gu8EP1_IN_EVEN_Buffer[EP1_SIZE];
u8 gu8EP2_OUT_ODD_Buffer[EP2_SIZE];
u8 gu8EP2_OUT_EVEN_Buffer[EP2_SIZE];
u8 gu8EP2_IN_ODD_Buffer[EP2_SIZE];
u8 gu8EP2_IN_EVEN_Buffer[EP2_SIZE];
u8 gu8EP3_OUT_ODD_Buffer[EP3_SIZE];
u8 gu8EP3_OUT_EVEN_Buffer[EP3_SIZE];
u8 gu8EP3_IN_ODD_Buffer[EP3_SIZE];
u8 gu8EP3_IN_EVEN_Buffer[EP3_SIZE];
//指向各个缓冲区的地址指针
u8 *BufferPointer[]=
{
gu8EP0_OUT_ODD_Buffer,
gu8EP0_OUT_EVEN_Buffer,
gu8EP0_IN_ODD_Buffer,
gu8EP0_IN_EVEN_Buffer,
gu8EP1_OUT_ODD_Buffer,
gu8EP1_OUT_EVEN_Buffer,
gu8EP1_IN_ODD_Buffer,
gu8EP1_IN_EVEN_Buffer,
gu8EP2_OUT_ODD_Buffer,
gu8EP2_OUT_EVEN_Buffer,
gu8EP2_IN_ODD_Buffer,
gu8EP2_IN_EVEN_Buffer,
gu8EP3_OUT_ODD_Buffer,
gu8EP3_OUT_EVEN_Buffer,
gu8EP3_IN_ODD_Buffer,
gu8EP3_IN_EVEN_Buffer
};
//每个缓冲区大小
const u8 cEP_Size[]=
{
EP0_SIZE,
EP0_SIZE,
EP0_SIZE,
EP0_SIZE,
EP1_SIZE,
EP1_SIZE,
EP1_SIZE,
EP1_SIZE,
EP2_SIZE,
EP2_SIZE,
EP2_SIZE,
EP2_SIZE,
EP3_SIZE,
EP3_SIZE,
EP3_SIZE,
EP3_SIZE
};
//StringDesc描述符指针
const u8* String_Table[4]=
{
String_Descriptor0,
String_Descriptor1,
String_Descriptor2,
String_Descriptor3
};
//SETUP包后面只能跟DATA0
//端点IN(2)状态
u8 vEP2State = kUDATA1;
//端点OUT(3)状态
u8 vEP3State = kUDATA0;
//保存端点OUT的数据
u8 RecDataBuff[EP3_SIZE];
//数据长度
u32 RecDataLength;
//USB模块内部全局变量
u8 gu8USBClearFlags; //用于发送和接收 不需要关注
u8 *pu8IN_DataPointer; //用于发送和接收 不需要关注
u8 gu8IN_Counter; //用于发送和接收 不需要关注
u8 gu8USB_Toogle_flags; //用于发送和接收 不需要关注
u8 gu8USB_State; //保存USB端点0的状态
tUSB_Setup *Setup_Pkt; //指向端点0OUT数据首地址
u8 gu8USB_Flags; //USB接收完成标志位
/*
* USB_DeviceEnumed
* 判断当前CDC设备是否被主机枚举 非阻塞式
*/
u8 USB_IsDeviceEnumed(void)
{
if(gu8USB_State == uENUMERATED) return 1;
return 0;
}
/*
* EP_IN_Transfer
* 端点IN传送,在不同USB模式下IN的含义不同
* 在USB主机模式下(USB host) IN表示 USB Host接收 USB Device的数据包
* 在USB设备模式下(USB Device)IN表示 USB Host向 USB Device发送数据包
* 当前在USB Device模式下,该函数的作用是Device设备发送数据包
*/
void USB_EP_IN_Transfer(u8 u8EP,u8 *pu8DataPointer,u8 u8DataSize)
{
u8 *pu8EPBuffer;
u8 u8EPSize; //端点的数据长度
u16 u16Lenght=0;
u8 u8EndPointFlag;
/*调整当前缓冲区的位置*/
u8EndPointFlag=u8EP;
if(u8EP) //如果不是端点0,
u8EP=(u8)(u8EP<<2);
u8EP+=2; //EP值加2
pu8EPBuffer=BufferPointer[u8EP]; //将新EP的BUFFER地址给pu8EPBuffer
if(BIT_CHK(fIN,gu8USBClearFlags)) //如果gu8USBClearFlags = 1
{
pu8IN_DataPointer = pu8DataPointer; //将用户数据存储区的首地址给pu8IN_DataPointer
gu8IN_Counter = u8DataSize; //将用户数据长度给gu8IN_Counter
u16Lenght=(Setup_Pkt->wLength_h<<8)+Setup_Pkt->wLength_l ;//将setup数据的长度给u16Lenght
if((u16Lenght < u8DataSize) && (u8EP==2)) //如果所发送的数据长度大于setup所设定的长度 同时 端点值 == 2
{
gu8IN_Counter=Setup_Pkt->wLength_l; //只发送setup中的低8位长度
}
}
/*检查发送长度*/
if(gu8IN_Counter > cEP_Size[u8EP]) //如果发送数据包的长度 大于32字节时
{
u8EPSize = cEP_Size[u8EP]; //将此时端点的长度限制在端点的默认长度
gu8IN_Counter-=cEP_Size[u8EP]; //将数据包的长度减少EP_Size
BIT_CLR(fIN,gu8USBClearFlags);//将gu8USBClearFlags清零
}
else
{
u8EPSize = gu8IN_Counter; //如果小于
gu8IN_Counter=0;
BIT_SET(fIN,gu8USBClearFlags);//将gu8USBClearFlags置一
}
/*将用户缓冲的区的值复制到EP 缓冲区中准备发送*/
tBDTtable[u8EP].Cnt=(u8EPSize); //复制所要发送的数据长度
while(u8EPSize--)
*pu8EPBuffer++=*pu8IN_DataPointer++; //将用户的数据赋值给EP存储区
if(BIT_CHK(u8EndPointFlag,gu8USB_Toogle_flags)) //如果相应端点的gu8USB_Toogle_flags == 1
{
tBDTtable[u8EP].Stat._byte= kUDATA0;
BIT_CLR(u8EndPointFlag,gu8USB_Toogle_flags);//清零相应端点的gu8USB_Toogle_flags
}
else
{
tBDTtable[u8EP].Stat._byte= kUDATA1;
BIT_SET(u8EndPointFlag,gu8USB_Toogle_flags);//置位gu8USB_Toogle_flags
}
}
/*
* EP_OUT_Transfer
* 端点OUT传送,在不同USB模式下OUT的含义不同
* 在USB主机模式下(USB host) OUT表示 USB Host向 USB Device发送数据包
* 在USB设备模式下(USB Device)OUT表示 USB Host从 USB Device接收数据包
* 当前在USB Device模式下,该函数的作用是Device设备接收数据包
* 返回值,返回接收到的数据的长度
*/
u8 EP_OUT_Transfer(u8 u8EP,u8 *pu8DataPointer)
{
u8 *pu8EPBuffer;
u8 u8EPSize;
/* 调整缓冲区的位置 */
u8EP++;
/* 分配合适的EP缓冲,EP0是控制点,EP1为输入中断点,EP2是输入BULK点 */
pu8EPBuffer=BufferPointer[u8EP];
u8EPSize=tBDTtable[u8EP].Cnt;
u8EP=u8EPSize;
/* 将EP缓冲的数据复制给用户区 */
while(u8EPSize--)
*pu8DataPointer++=*pu8EPBuffer++;
return(u8EP);
}
/*
* USB_EP_OUT_SizeCheck
* 端点输入数据长度检查
*
*/
u16 USB_EP_OUT_SizeCheck(u8 u8EP)
{
u8 u8EPSize;
/* 读取缓冲区的长度 */
u8EPSize = tBDTtable[u8EP<<2].Cnt;
return(u8EPSize & 0x03FF);
}
//=========================================================================
//函数名: hw_usb_set_interface
//功 能: USB模块的描述符
//参 数: 无
//返 回: 接收到的数据长度
//=========================================================================
void USB_EnableInterface(void)
{
/* 端点寄存器设置 */
USB0->ENDPOINT[1].ENDPT= EP1_VALUE | USB_ENDPT_EPHSHK_MASK; //设置端点1为中断端点
USB0->ENDPOINT[2].ENDPT= EP2_VALUE | USB_ENDPT_EPHSHK_MASK; //设置端点2为输入 BULK端点
USB0->ENDPOINT[3].ENDPT= EP3_VALUE | USB_ENDPT_EPHSHK_MASK; //设置端点3为输出 BULK端点
USB0->ENDPOINT[4].ENDPT= EP4_VALUE | USB_ENDPT_EPHSHK_MASK; //禁止端点
USB0->ENDPOINT[5].ENDPT= EP5_VALUE | USB_ENDPT_EPHSHK_MASK; //禁止端点
USB0->ENDPOINT[6].ENDPT= EP6_VALUE | USB_ENDPT_EPHSHK_MASK; //禁止端点
// 设置 1 BDT 设置
// 把控制权交给MCU
tBDTtable[bEP1IN_ODD].Stat._byte= kUDATA1; //发送DATA1数据包
tBDTtable[bEP1IN_ODD].Cnt = 0x00; //计数器清空
tBDTtable[bEP1IN_ODD].Addr =(u32)gu8EP1_IN_ODD_Buffer; //地址指向对应的缓冲区
// 设置 2 BDT 设置
// 把控制权交给MCU
tBDTtable[bEP2IN_ODD].Stat._byte= kUDATA1;
tBDTtable[bEP2IN_ODD].Cnt = 0x00;
tBDTtable[bEP2IN_ODD].Addr =(u32 )gu8EP2_IN_ODD_Buffer;
// 设置 3 BDT 设置
// 把控制权交给MCU
tBDTtable[bEP3OUT_ODD].Stat._byte= kUDATA0;
tBDTtable[bEP3OUT_ODD].Cnt = 0xFF;
tBDTtable[bEP3OUT_ODD].Addr =(u32)gu8EP3_OUT_ODD_Buffer;
}
//描述符处理函数
void USB_GetDescHandler(void)
{
switch((Setup_Pkt->wValue_h) & 0xFF)
{
case DEVICE_DESCRIPTOR:
#if (DEBUG_PRINT == 1)
printf("设备描述符\r\n");
#endif
USB_EP_IN_Transfer(EP0,(u8*)Device_Descriptor,sizeof(Device_Descriptor));//发送设备描述符
break;
case CONFIGURATION_DESCRIPTOR:
#if (DEBUG_
没有合适的资源?快使用搜索试试~ 我知道了~
温馨提示
超核 飞思卡尔Kinetis K60 固件库系列例程35-串口Bootloader下位机程序(V2.40版本) 编译器: MDK4.53(Keil) 调试器: Jlink V8 使用Keil4.53 ARM 版本 打开 PRJ文件夹下的template.uvproj PRJ:存放Keil工程文件 SRC:源码 OBJ:生成的中间文件
资源推荐
资源详情
资源评论
收起资源包目录
35-使用USB转串口实现Bootloader程序.zip (39个子文件)
35-使用USB转串口实现Bootloader程序
SRC
USB
usb_cdc.c 2KB
usb_hid.c 4KB
USB.c 25KB
usb_hid.h 304B
USB_Desc.h 6KB
usb_cdc.h 779B
usb.h 6KB
SYSTEM
SYS
sys.c 16KB
sys.h 6KB
GPIO
gpio.h 2KB
gpio.c 4KB
UART
uart.h 759B
uart.c 8KB
WDOG
wdog.h 712B
wdog.c 2KB
DELAY
delay.c 5KB
delay.h 440B
USER
main.c 669B
BOOTLOADER
flash_operate.h 492B
bootloader.c 12KB
message_manage.c 927B
bootloader.h 708B
message_manage.h 446B
bootloader_util.c 4KB
bootloader_util.h 1KB
flash_operate.c 8KB
def.h 2KB
HARDWARE
KEY
key.h 564B
key.c 380B
LED
led.h 686B
led.c 447B
keilkill.bat 399B
PRJ
JLinkSettings.ini 573B
test.uvproj 18KB
test.hex 27KB
test.uvgui.Administrator 84KB
test.uvopt 14KB
%APPDATA%
Microsoft
Windows
IETldCache
index.dat 16KB
startup_MK60D10.s 31KB
共 39 条
- 1
资源评论
- ualberta2017-07-30Very good! I like it.
- solo3322014-07-29很好的资料多谢啦
- 2020~developer2015-03-03还好,要是加个文档说明就更好了!挺不错的,多谢了。
yandld
- 粉丝: 36
- 资源: 14
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功