以前做过usb下载的东东,现在把它搞到u-boot-2010.06-rc1上去.
网上有usb下载的代码,可以在这儿下载:
一. 先编译过再说
1.下载后,解压到u-boot-2010.06-rc1/drivers/usb/slave目录
并在顶层Makefile中添加: LIBS += drivers/usb/slave/libusb_slave.a
2. 将driver/usb/slave/目录下所有C文件所个替换
-
a.
-
#if defined(CONFIG_S3C2400)
-
#include <s3c2400.h>
-
#elif defined(CONFIG_S3C2410) || defined(CONFIG_S3C2440)
-
#include <s3c2410.h>
-
#endif
-
#include
-
替换为
-
#include
-
b. 删除driver/usb/slave/interrupt.c
-
c. 修改driver/usb/slave/Makefile中的 COBJS, 去掉interrupt.o
3.u-boot-2010.06-rc1中结构体都是小写,跟下载的代码中结构体名字是大写的,需要将大写的名字改成小写的,这样才可以编译过去.
4.arch/arm/include/asm/arch/s3c24x0.h中
-
a. 添加两个宏定义
-
#define BIT_DMA2 (0x1<<19)
-
#define BIT_USBD (0x1<<25)
-
-
b. 修改s3c24x0_usb_device结构体
-
//u8 res10[7]
-
u8 res10[3];
-
//u8 res12[3]
-
u8 res12[7];
-
//u8 res13[7]
-
u8 res13[3];
-
/*
-
struct s3c24x0_usb_dev_fifos fifo[5];
-
struct s3c24x0_usb_dev_dmas dma[5];
-
*/
-
u32 res17[8];
-
struct s3c24x0_usb_dev_fifos fifo[5];
-
u32 res18[11];
-
struct s3c24x0_usb_dev_dmas ep1;
-
struct s3c24x0_usb_dev_dmas ep2;
-
u8 res19[16];
-
struct s3c24x0_usb_dev_dmas ep3;
-
struct s3c24x0_usb_dev_dmas ep4;
-
-
c. 修改 struct s3c24x0_gpio
-
L481 添加:
-
/* s3c2440 */
-
u32 res9[4];
-
u32 GPJCON;
-
u32 GPJDAT;
-
u32 GPJUP;
5. usbmain.c中void IsrUsbd(void)调用了ClearPending,其实现如下:
-
arch/arm/cpu/arm920t/interrupt.c
-
//添加 ClearPending的实现:
-
void ClearPending(int bit)
-
{
-
intregs->SRCPND = bit;
-
intregs->INTPND = bit;
-
}
-
并修改driver/usb/slave/usbmain.c
-
//ClearPending_my(BIT_USBD);
-
ClearPending(BIT_USBD);
6. usbmain.c的usb_init_slave(void)调用了Isr_Init(),其实现如下
arch/arm/cpu/arm920t/interrupt.c中添加
-
#include <asm/arch/s3c24x0_cpu.h>
-
-
struct s3c24x0_interrupt * intregs;
-
void (*isr_handle_array[50])(void);
-
extern void IsrUsbd(void);
-
extern void IsrDma2(void);
-
void Dummy_isr(void)
-
{
-
printf("Dummy_isr error, interrupt number: %d, INTMSK = 0x%x\n", intregs->INTOFFSET, intregs->INTMSK);
-
while(1);
-
}
-
//初始化irq的中断向量表
-
void Isr_Init(void)
-
{
-
int i = 0;
-
intregs = s3c24x0_get_base_interrupt();
-
-
for (i = 0; i < sizeof(isr_handle_array) / sizeof(isr_handle_array[0]); i++ )
-
{
-
isr_handle_array[i] = Dummy_isr;
-
}
-
-
intregs->INTMOD=0x0; // All=IRQ mode
-
intregs->INTMSK=BIT_ALLMSK; // All interrupt is masked.
-
-
#ifdef CONFIG_USB_DEVICE
-
isr_handle_array[ISR_USBD_OFT] = IsrUsbd;
-
isr_handle_array[ISR_DMA2_OFT] = IsrDma2;
-
ClearPending(BIT_DMA2);
-
ClearPending(BIT_USBD);
-
#endif
-
}
-
b. 同时在 arch/arm/include/asm/arch/s3c24x0.h中添加
-
-
#define ISR_DMA2_OFT 19
-
#define ISR_USBD_OFT 25
-
c. 并在 include/configs/smdk2410.h 中添加
-
#define CONFIG_USB_DEVICE 1
-
d. arch/arm/lib/bootm.c中,注掉udc_disconnect,否则编译不过
-
-
#ifdef CONFIG_USB_DEVICE
-
{
-
extern void udc_disconnect (void);
-
//udc_disconnect ();
-
}
-
#endif
7. 开启中断
start_armboot --> 调用enable_interrupts ();
在include/configs/smdk2410.h 中添加
-
//#undef CONFIG_USE_IRQ /* we don't need IRQ/FIQ stuff */
-
#define CONFIG_USE_IRQ 1
这会导致arch/arm/cpu/arm920t/s3c24x0/interrupt.c 因为缺少readl而出错
同时报错说没有arch_interrupt_init的定义
在arch/arm/cpu/arm920t/s3c24x0/interrupt.c 中添加
-
#include <asm/io.h>
-
-
int arch_interrupt_init(void)
-
{
-
return (0);
-
}
8.还要在arch/arm/lib/board.c中添加
-
/* enable exceptions */
-
enable_interrupts ();
-
-
//调用usb 初始化函数
-
usb_init_slave();
10. 还编译不过,需要在arch/arm/cpu/arm920t/interrupt.c中添加
-
static int intCount;
-
-
void Timer_InitEx(void)
-
{
-
intCount=0;
-
intregs->SUBSRCPND = (1<<13);
-
ClearPending(BIT_WDT_AC97/*BIT_WDT*/);
-
intregs->INTMSK&=~(BIT_WDT_AC97 /*BIT_WDT*/);
-
intregs->INTSUBMSK &= ~(1<<13);
-
}
-
-
void Timer_StartEx(void)
-
{
-
//S3C24X0_WATCHDOG * const wdtregs = S3C24X0_GetBase_WATCHDOG();
-
struct s3c24x0_watchdog * const wdtregs = s3c24x0_get_base_watchdog();
-
wdtregs->WTCON=((get_PCLK()/1000000-1)<<8)|(0<<3)|(1<<2); // 16us
-
wdtregs->WTDAT=0xffff;
-
wdtregs->WTCNT=0xffff;
-
-
// 1/16/(65+1),interrupt enable,reset disable,watchdog enable
-
wdtregs->WTCON=((get_PCLK()/1000000-1)<<8)|(0<<3)|(1<<2)|(0<<0)|(1<<5);
-
}
-
unsigned int Timer_StopEx(void)
-
{
-
int count;
-
//S3C24X0_WATCHDOG * const wdtregs = S3C24X0_GetBase_WATCHDOG();
-
struct s3c24x0_watchdog * const wdtregs = s3c24x0_get_base_watchdog();
-
-
wdtregs->WTCON=((get_PCLK()/1000000-1)<<8);
-
intregs->INTMSK|=BIT_WDT_AC97; //BIT_WDT;
-
intregs->INTSUBMSK |= (1<<13);
-
-
count=(0xffff-wdtregs->WTCNT)+(intCount*0xffff);
-
return ((unsigned int)count*16/1000000);
-
}
11. 加入usbslave命令
Common/Makefile中
-
COBJS-$(CONFIG_USB_DEVICE) += usb_storage.o
12 打通中断的路
arch/arm/cpu/arm920t/start.S
L399
-
irq:
-
/*
-
get_irq_stack
-
irq_save_user_regs
-
bl do_irq
-
irq_restore_user_regs
-
*/
-
-
sub lr, lr, #4 @ the return address
-
/*@在完成保存堆栈的操作后,跳到中断处理函数IRQ_Handle中*/
-
ldr sp, IRQ_STACK_START @ the stack for irq
-
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
arch/arm/cpu/arm920t/interrupt.c //
irq的中断服务程序
-
void IRQ_Handle()
-
{
-
unsigned long oft = intregs->INTOFFSET;
-
//S3C24X0_GPIO * const gpio = S3C24X0_GetBase_GPIO();
-
struct s3c24x0_gpio *const gpio = s3c24x0_get_base_gpio();
-
-
//清中断
-
if( oft == 4 ) gpio->EINTPEND = 1<<7; //EINT4-7合用IRQ4,注意EINTPEND[3:0]保留未用,向这些位写入1可能导致未知结果
-
intregs->SRCPND = 1<<oft;
-
intregs->INTPND = intregs->INTPND;
-
-
/* run the isr */
-
isr_handle_array[oft]();
-
}
在Isr_init()中
isr_handle_array[ISR_USBD_OFT] = IsrUsbd;
isr_handle_array[ISR_DMA2_OFT] = IsrDma2;
所以当有usb中断时,就会调用IsrUsbd()函数.
13. 最关键的一步, 打开irq中断,重启复位时默认进入0xD3模式,并不开启irq中断,
在start_armboot中完成Port_init之后就要打开irq中断.
-
/* enable IRQ interrupts */
-
void enable_interrupts (void)
-
{
-
unsigned long temp;
-
__asm__ __volatile__("mrs %0, cpsr\n"
-
"bic %0, %0, #0x80\n"
-
"msr cpsr_c, %0"
-
: "=r" (temp)
-
:
-
: "memory");
-
}
当调用enable_interrupts函数之后,irq中断这条路就己经通了,当有usb中断发生时就会进入自己写的usb中断服务程序.
二.调试
2.1 当编译好之后,下载到板子上运行,usb设备枚举正常,但在下载时出现问题
-
SMDK2410 # usbslave 1 0x30000000
-
USB host is connected. Waiting a download.
-
-
Now, Downloading [ADDRESS:30000000h,TOTAL:1942578]
-
RECEIVED FILE SIZE: 65536Dummy_isr error, interrupt number: 9, INTMSK = 0xfff7fdff
2.2 加入watchdog和timer中断
-
int g_TimerIntHappen;
-
static int intCount;
-
void IsrTimer4(void)
-
{
-
ClearPending(BIT_TIMER4);
-
*(volatile int *)&g_TimerIntHappen = 1;
-
}
-
-
-
void Dummy_isr(void)
-
{
-
printf("Dummy_isr error, interrupt number: %d, INTMSK = 0x%x\n", intregs->INTOFFSET, intregs->INTMSK);
-
while(1);
-
}
-
void Isr_Init(void) //加入中断处理函数
-
{
-
isr_handle_array[ISR_TIMER4_OFT] = IsrTimer4;
-
isr_handle_array[ISR_WDT_OFT] = IsrWatchdog;
}
[参考文章]
http://singleboy.blog.163.com/blog/static/549001942011417917635/
阅读(2806) | 评论(0) | 转发(1) |