bootloader---19.usb下载之设备枚举
2016-08-29 13:58
447 查看
在实现了读取内核并引导内核之后,下一步要实现的功能是内核下载。内核下载可以通过网络和usb下载,正好最近学习了usb的一些东东,现在就把usb下载的功能加入到myboot中,这样myboot看起来就像是那么回事了,呵呵。
usb主机要与usb设备进行通信,这儿要完成的是usb设备部分,那么usb主机部分肿么办呢?windows下的dnw没有代码的,而且还老蓝屏,但是linux下有基于libusb的源程序(dnw2)。 usb主机部分临时先用这个代码,等把usb设备完成之后,再自己动手写一下这个dnw2的代码,这样上下位机咱就都会了。
下面说一下思路,usb 设备部分主要实现如下功能:
1.实现usb的枚举
a. 以前代码中没有用到中断,所以这儿要实现中断
a.1 建立arm的中断向量表 (start.S中添加)
当发生 irq中断时,mcu跳到中断向量表的irq入口处,执行ldr pc, _irq命令。
因为定义了 _irq: .word irq, 所以程序跳到irq函数去执行。
点击(此处)折叠或打开
_start:
b reset
ldr pc, _undefined_instruction
ldr pc, _software_interrupt
ldr pc, _prefetch_abort
ldr pc, _data_abort
ldr pc, _not_used
ldr pc, _irq
ldr pc, _fiq
_undefined_instruction:
.word undefined_instruction
_software_interrupt:
.word software_interrupt
_prefetch_abort:
.word prefetch_abort
_data_abort:
.word data_abort
_not_used:
.word not_used
_irq:
.word irq
_fiq:
.word fiq
a.2 arm的中断服务程序,这儿只用到了irq (start.S中添加)
点击(此处)折叠或打开
undefined_instruction:
nop
software_interrupt:
nop
prefetch_abort:
nop
data_abort:
nop
not_used:
nop
irq:
sub lr, lr, #4
@ the return address
ldr sp, IRQ_STACK_START
@ the stack for irq @在完成保存堆栈的操作后,跳到中断处理函数IRQ_Handle中。
stmdb { r0-r12,lr}
@ save registers
ldr lr, =int_return
@ set the return addr
ldr pc, =irq_handle
@ call the isr
int_return:
ldmia { r0-r12,pc }^
@ return from interrupt
fiq:
nop
.globl IRQ_STACK_START
IRQ_STACK_START:
.word 0x33FF7000
a.3 irq的中断服务程序
点击(此处)折叠或打开
void (*isr_handle_array[50])(void);
void irq_handle(void)
{
unsigned long oft = INTOFFSET;
SRCPND = 1<<oft;
INTPND = 1<<oft;
(isr_handle_array[oft])();
return ;
}
a.4 初始化irq的中断向量表
点击(此处)折叠或打开
//这里只用usb中断和dma2
void Isr_Init(void)
{
u32 i = 0;
for(i=0; i<sizeof(isr_handle_array); i++)
{
isr_handle_array[i] = Dummy_isr;
}
//将所有中断设为IRQ模式,并屏闭所有中断
INTMOD = 0x0;
INTMSK = BIT_ALLMSK;
isr_handle_array[ISR_USBD_OFT] = IsrUsbd;
isr_handle_array[ISR_DMA2_OFT] = IsrDma2;
ClearPending(BIT_DMA2);
ClearPending(BIT_USBD);
return ;
}
a.5 最关键的一步,打开irq中断,重启复位时默认进入0xd3模式,并不开启irq中断。
点击(此处)折叠或打开
开启irq中断
void enable_irq(void)
{
asm volatile
(
"mrs r4,cpsr\n\t"
"bic r4,r4,#0x80\n\t"
"msr cpsr,r4\n\t"
:::"r4"
);
}
b. irq中断这条路己经通了,当有usb中断时就会进入usb中断服务程序,这一步要实现产生usb中断的所有准备
b.1 配置usb寄存器, 让usb设备工作起来
点击(此处)折叠或打开
void Init_Usb_Reg(void)
{
// *** End point
information ***
// EP0: control
// EP1: bulk in end point
// EP2: not used
// EP3: bulk out end point
// EP4: not used
#define PWR_REG_DEFAULT_VALUE (DISABLE_SUSPEND)
PWR_REG=PWR_REG_DEFAULT_VALUE; //disable
suspend mode //0x00
INDEX_REG=0;
MAXP_REG=FIFO_SIZE_8; //EP0
max packit size = 8 //datasheet:For EP1~4, MAXP=64 is recommended.
EP0_CSR_IN_CSR1_REG=EP0_SERVICED_OUT_PKT_RDY|EP0_SERVICED_SETUP_END; //EP0_CSR
EP0:clear OUT_PKT_RDY & SETUP_END
INDEX_REG=1;
MAXP_REG=FIFO_SIZE_32; //EP1:max
packit size = 32
EP0_CSR_IN_CSR1_REG=EPI_FIFO_FLUSH|EPI_CDT;
IN_CSR2_REG=EPI_MODE_IN|EPI_IN_DMA_INT_MASK|EPI_BULK; //IN mode, IN_DMA_INT=masked
OUT_CSR1_REG=EPO_CDT;
OUT_CSR2_REG=EPO_BULK|EPO_OUT_DMA_INT_MASK;
INDEX_REG=2;
MAXP_REG=FIFO_SIZE_64; //EP2:max
packit size = 64
EP0_CSR_IN_CSR1_REG=EPI_FIFO_FLUSH|EPI_CDT|EPI_BULK;
IN_CSR2_REG=EPI_MODE_IN|EPI_IN_DMA_INT_MASK; //IN mode, IN_DMA_INT=masked
OUT_CSR1_REG=EPO_CDT;
OUT_CSR2_REG=EPO_BULK|EPO_OUT_DMA_INT_MASK;
INDEX_REG=3;
MAXP_REG=FIFO_SIZE_32; //EP3:max
packit size = 32
EP0_CSR_IN_CSR1_REG=EPI_FIFO_FLUSH|EPI_CDT|EPI_BULK;
IN_CSR2_REG=EPI_MODE_OUT|EPI_IN_DMA_INT_MASK; //OUT
mode, IN_DMA_INT=masked
OUT_CSR1_REG=EPO_CDT;
//clear OUT_PKT_RDY, data_toggle_bit.
//The data toggle bit should be cleared when initialization.
OUT_CSR2_REG=EPO_BULK|EPO_OUT_DMA_INT_MASK;
INDEX_REG=4;
MAXP_REG=FIFO_SIZE_64; //EP4:max
packit size = 64
EP0_CSR_IN_CSR1_REG=EPI_FIFO_FLUSH|EPI_CDT|EPI_BULK;
IN_CSR2_REG=EPI_MODE_OUT|EPI_IN_DMA_INT_MASK; //OUT
mode, IN_DMA_INT=masked
OUT_CSR1_REG=EPO_CDT;
//clear OUT_PKT_RDY, data_toggle_bit.
//The data toggle bit should be cleared when initialization.
OUT_CSR2_REG=EPO_BULK|EPO_OUT_DMA_INT_MASK;
EP_INT_REG=EP0_INT|EP1_INT|EP2_INT|EP3_INT|EP4_INT;
USB_INT_REG=RESET_INT|SUSPEND_INT|RESUME_INT;
//Clear all usbd pending bits
//EP0,1,3 & reset
interrupt are enabled
EP_INT_EN_REG=EP0_INT|EP1_INT|EP3_INT;
USB_INT_EN_REG=RESET_INT;
//ep0State=EP0_STATE_INIT;
}
b.2 产生usb复位信号,进入usb枚举过程
点击(此处)折叠或打开
void usb_reconnect(void)
{
//tq2440: 在USB设备的信号线D+上接了一个1.5K的一个上拉电阻,这个上拉电阻是由usb_en控制的,当GPG12输出高电平的时候,主机的集线器才能检测到设备,从而给复位信号
//GPG12-->usb_en
GPGCON |= (OUTPUT_PIN<<24); //set GPG12
output
GPGDAT |= (1<<12); //enable
USB Device
}
b.3 usb中断最关键的一步
点击(此处)折叠或打开
INTMSK &= ~(BIT_USBD); //打开usb中断
c. 产生了usb中断了,但是usb中断服务程序还没有完成,马上。
注意: usb枚举过程是有时间限制的,如果printf打印的太多,会导致枚举失败。
点击(此处)折叠或打开
void IsrUsbd(void)
{
u8 usbdIntpnd,epIntpnd;
u8 saveIndexReg=INDEX_REG;
usbdIntpnd=USB_INT_REG;
epIntpnd=EP_INT_REG;
//uart_printf( "[INT:EP_I=%x,USBI=%x]",epIntpnd,usbdIntpnd );
if(usbdIntpnd&SUSPEND_INT) //出现suspend_int中断之后,直接清中断
{
USB_INT_REG=SUSPEND_INT; //向寄存器写1,清除该位
// uart_puts( "<sus]\n");
}
if(usbdIntpnd&RESUME_INT) //出现resume_int中断之后,直接清中断
{
USB_INT_REG=RESUME_INT; //向寄存器写1,清除该位
// uart_puts("<rsm]\n");
}
if(usbdIntpnd&RESET_INT) //出现reset_int中断之后,复位usb
{
//uart_puts( "<rst]
init_usb_reg\n");
//ResetUsbd();
Init_Usb_Reg();
USB_INT_REG=RESET_INT; //clear
RESET_INT
// PrepareEp1Fifo();
}
if(epIntpnd&EP0_INT)
{
EP_INT_REG=EP0_INT; //向寄存器写1,清除该位
Ep0Handler();
}
if(epIntpnd&EP1_INT)
{
EP_INT_REG=EP1_INT; //向寄存器写1,清除该位
Ep1Handler();
}
if(epIntpnd&EP2_INT)
{
EP_INT_REG=EP2_INT; //向寄存器写1,清除该位
uart_puts("<2:TBD]\n"); //not implemented
yet
//Ep2Handler();
}
if(epIntpnd&EP3_INT)
{
EP_INT_REG=EP3_INT;
Ep3Handler();
}
if(epIntpnd&EP4_INT)
{
EP_INT_REG=EP4_INT;
uart_puts("<4:TBD]\n"); //not implemented
yet
//Ep4Handler();
}
ClearPending(BIT_USBD);
INDEX_REG=saveIndexReg;
}
d.
e.
f.
2.实现数据的收取
a.
b.
c.
d.
e.
f.
参考文章:
1. s3c2440的USB主机控制器
http://blog.csdn.net/zhaocj/article/details/6083162
2. S3C2440之USB设备篇
http://blog.csdn.net/xuxg2005/article/details/6172412
3. S3C2440 USB设备控制器
http://blog.csdn.net/yaozhenguo2006/article/details/7405825
usb主机要与usb设备进行通信,这儿要完成的是usb设备部分,那么usb主机部分肿么办呢?windows下的dnw没有代码的,而且还老蓝屏,但是linux下有基于libusb的源程序(dnw2)。 usb主机部分临时先用这个代码,等把usb设备完成之后,再自己动手写一下这个dnw2的代码,这样上下位机咱就都会了。
下面说一下思路,usb 设备部分主要实现如下功能:
1.实现usb的枚举
a. 以前代码中没有用到中断,所以这儿要实现中断
a.1 建立arm的中断向量表 (start.S中添加)
当发生 irq中断时,mcu跳到中断向量表的irq入口处,执行ldr pc, _irq命令。
因为定义了 _irq: .word irq, 所以程序跳到irq函数去执行。
点击(此处)折叠或打开
_start:
b reset
ldr pc, _undefined_instruction
ldr pc, _software_interrupt
ldr pc, _prefetch_abort
ldr pc, _data_abort
ldr pc, _not_used
ldr pc, _irq
ldr pc, _fiq
_undefined_instruction:
.word undefined_instruction
_software_interrupt:
.word software_interrupt
_prefetch_abort:
.word prefetch_abort
_data_abort:
.word data_abort
_not_used:
.word not_used
_irq:
.word irq
_fiq:
.word fiq
a.2 arm的中断服务程序,这儿只用到了irq (start.S中添加)
点击(此处)折叠或打开
undefined_instruction:
nop
software_interrupt:
nop
prefetch_abort:
nop
data_abort:
nop
not_used:
nop
irq:
sub lr, lr, #4
@ the return address
ldr sp, IRQ_STACK_START
@ the stack for irq @在完成保存堆栈的操作后,跳到中断处理函数IRQ_Handle中。
stmdb { r0-r12,lr}
@ save registers
ldr lr, =int_return
@ set the return addr
ldr pc, =irq_handle
@ call the isr
int_return:
ldmia { r0-r12,pc }^
@ return from interrupt
fiq:
nop
.globl IRQ_STACK_START
IRQ_STACK_START:
.word 0x33FF7000
a.3 irq的中断服务程序
点击(此处)折叠或打开
void (*isr_handle_array[50])(void);
void irq_handle(void)
{
unsigned long oft = INTOFFSET;
SRCPND = 1<<oft;
INTPND = 1<<oft;
(isr_handle_array[oft])();
return ;
}
a.4 初始化irq的中断向量表
点击(此处)折叠或打开
//这里只用usb中断和dma2
void Isr_Init(void)
{
u32 i = 0;
for(i=0; i<sizeof(isr_handle_array); i++)
{
isr_handle_array[i] = Dummy_isr;
}
//将所有中断设为IRQ模式,并屏闭所有中断
INTMOD = 0x0;
INTMSK = BIT_ALLMSK;
isr_handle_array[ISR_USBD_OFT] = IsrUsbd;
isr_handle_array[ISR_DMA2_OFT] = IsrDma2;
ClearPending(BIT_DMA2);
ClearPending(BIT_USBD);
return ;
}
a.5 最关键的一步,打开irq中断,重启复位时默认进入0xd3模式,并不开启irq中断。
点击(此处)折叠或打开
开启irq中断
void enable_irq(void)
{
asm volatile
(
"mrs r4,cpsr\n\t"
"bic r4,r4,#0x80\n\t"
"msr cpsr,r4\n\t"
:::"r4"
);
}
b. irq中断这条路己经通了,当有usb中断时就会进入usb中断服务程序,这一步要实现产生usb中断的所有准备
b.1 配置usb寄存器, 让usb设备工作起来
点击(此处)折叠或打开
void Init_Usb_Reg(void)
{
// *** End point
information ***
// EP0: control
// EP1: bulk in end point
// EP2: not used
// EP3: bulk out end point
// EP4: not used
#define PWR_REG_DEFAULT_VALUE (DISABLE_SUSPEND)
PWR_REG=PWR_REG_DEFAULT_VALUE; //disable
suspend mode //0x00
INDEX_REG=0;
MAXP_REG=FIFO_SIZE_8; //EP0
max packit size = 8 //datasheet:For EP1~4, MAXP=64 is recommended.
EP0_CSR_IN_CSR1_REG=EP0_SERVICED_OUT_PKT_RDY|EP0_SERVICED_SETUP_END; //EP0_CSR
EP0:clear OUT_PKT_RDY & SETUP_END
INDEX_REG=1;
MAXP_REG=FIFO_SIZE_32; //EP1:max
packit size = 32
EP0_CSR_IN_CSR1_REG=EPI_FIFO_FLUSH|EPI_CDT;
IN_CSR2_REG=EPI_MODE_IN|EPI_IN_DMA_INT_MASK|EPI_BULK; //IN mode, IN_DMA_INT=masked
OUT_CSR1_REG=EPO_CDT;
OUT_CSR2_REG=EPO_BULK|EPO_OUT_DMA_INT_MASK;
INDEX_REG=2;
MAXP_REG=FIFO_SIZE_64; //EP2:max
packit size = 64
EP0_CSR_IN_CSR1_REG=EPI_FIFO_FLUSH|EPI_CDT|EPI_BULK;
IN_CSR2_REG=EPI_MODE_IN|EPI_IN_DMA_INT_MASK; //IN mode, IN_DMA_INT=masked
OUT_CSR1_REG=EPO_CDT;
OUT_CSR2_REG=EPO_BULK|EPO_OUT_DMA_INT_MASK;
INDEX_REG=3;
MAXP_REG=FIFO_SIZE_32; //EP3:max
packit size = 32
EP0_CSR_IN_CSR1_REG=EPI_FIFO_FLUSH|EPI_CDT|EPI_BULK;
IN_CSR2_REG=EPI_MODE_OUT|EPI_IN_DMA_INT_MASK; //OUT
mode, IN_DMA_INT=masked
OUT_CSR1_REG=EPO_CDT;
//clear OUT_PKT_RDY, data_toggle_bit.
//The data toggle bit should be cleared when initialization.
OUT_CSR2_REG=EPO_BULK|EPO_OUT_DMA_INT_MASK;
INDEX_REG=4;
MAXP_REG=FIFO_SIZE_64; //EP4:max
packit size = 64
EP0_CSR_IN_CSR1_REG=EPI_FIFO_FLUSH|EPI_CDT|EPI_BULK;
IN_CSR2_REG=EPI_MODE_OUT|EPI_IN_DMA_INT_MASK; //OUT
mode, IN_DMA_INT=masked
OUT_CSR1_REG=EPO_CDT;
//clear OUT_PKT_RDY, data_toggle_bit.
//The data toggle bit should be cleared when initialization.
OUT_CSR2_REG=EPO_BULK|EPO_OUT_DMA_INT_MASK;
EP_INT_REG=EP0_INT|EP1_INT|EP2_INT|EP3_INT|EP4_INT;
USB_INT_REG=RESET_INT|SUSPEND_INT|RESUME_INT;
//Clear all usbd pending bits
//EP0,1,3 & reset
interrupt are enabled
EP_INT_EN_REG=EP0_INT|EP1_INT|EP3_INT;
USB_INT_EN_REG=RESET_INT;
//ep0State=EP0_STATE_INIT;
}
b.2 产生usb复位信号,进入usb枚举过程
点击(此处)折叠或打开
void usb_reconnect(void)
{
//tq2440: 在USB设备的信号线D+上接了一个1.5K的一个上拉电阻,这个上拉电阻是由usb_en控制的,当GPG12输出高电平的时候,主机的集线器才能检测到设备,从而给复位信号
//GPG12-->usb_en
GPGCON |= (OUTPUT_PIN<<24); //set GPG12
output
GPGDAT |= (1<<12); //enable
USB Device
}
b.3 usb中断最关键的一步
点击(此处)折叠或打开
INTMSK &= ~(BIT_USBD); //打开usb中断
c. 产生了usb中断了,但是usb中断服务程序还没有完成,马上。
注意: usb枚举过程是有时间限制的,如果printf打印的太多,会导致枚举失败。
点击(此处)折叠或打开
void IsrUsbd(void)
{
u8 usbdIntpnd,epIntpnd;
u8 saveIndexReg=INDEX_REG;
usbdIntpnd=USB_INT_REG;
epIntpnd=EP_INT_REG;
//uart_printf( "[INT:EP_I=%x,USBI=%x]",epIntpnd,usbdIntpnd );
if(usbdIntpnd&SUSPEND_INT) //出现suspend_int中断之后,直接清中断
{
USB_INT_REG=SUSPEND_INT; //向寄存器写1,清除该位
// uart_puts( "<sus]\n");
}
if(usbdIntpnd&RESUME_INT) //出现resume_int中断之后,直接清中断
{
USB_INT_REG=RESUME_INT; //向寄存器写1,清除该位
// uart_puts("<rsm]\n");
}
if(usbdIntpnd&RESET_INT) //出现reset_int中断之后,复位usb
{
//uart_puts( "<rst]
init_usb_reg\n");
//ResetUsbd();
Init_Usb_Reg();
USB_INT_REG=RESET_INT; //clear
RESET_INT
// PrepareEp1Fifo();
}
if(epIntpnd&EP0_INT)
{
EP_INT_REG=EP0_INT; //向寄存器写1,清除该位
Ep0Handler();
}
if(epIntpnd&EP1_INT)
{
EP_INT_REG=EP1_INT; //向寄存器写1,清除该位
Ep1Handler();
}
if(epIntpnd&EP2_INT)
{
EP_INT_REG=EP2_INT; //向寄存器写1,清除该位
uart_puts("<2:TBD]\n"); //not implemented
yet
//Ep2Handler();
}
if(epIntpnd&EP3_INT)
{
EP_INT_REG=EP3_INT;
Ep3Handler();
}
if(epIntpnd&EP4_INT)
{
EP_INT_REG=EP4_INT;
uart_puts("<4:TBD]\n"); //not implemented
yet
//Ep4Handler();
}
ClearPending(BIT_USBD);
INDEX_REG=saveIndexReg;
}
d.
e.
f.
2.实现数据的收取
a.
b.
c.
d.
e.
f.
参考文章:
1. s3c2440的USB主机控制器
http://blog.csdn.net/zhaocj/article/details/6083162
2. S3C2440之USB设备篇
http://blog.csdn.net/xuxg2005/article/details/6172412
3. S3C2440 USB设备控制器
http://blog.csdn.net/yaozhenguo2006/article/details/7405825
相关文章推荐
- C#:USB设备枚举(四)Kernel32的PInvoke
- C#:USB设备枚举(八)创建基于WPF的USB设备浏览器
- mini2440 usb device controller 驱动的分析--gadget设备(二)---枚举
- USB设备的枚举过程
- USB学习系列之三——USB设备的枚举
- Linux USB Gadget--设备枚举
- Windows下USB磁盘开发系列三:枚举系统中U盘、并获取其设备信息
- Linux USB Gadget--设备枚举
- 高速USB设备枚举的握手过程
- 【转】Linux那些事儿 之 戏说USB(19)设备
- USB 枚举和设备描述符之学习笔记
- usb设备枚举过程
- C#USB设备枚举Kernel32的PInvoke
- 使枚举成功的USB设备成为WINUSB设备
- USB设备的枚举过程
- Linux USB Gadget--设备枚举
- 使用libusb库枚举mac设备下面的USB设备
- Linux设备驱动程序学习(19)-USB 驱动程序(四)
- C#:USB设备枚举(六)生成ListView数据源
- usb mass storage设备枚举过程