您的位置:首页 > 其它

bootloader---25.u-boot-2010.06-rc1移植之5usb下载

2016-08-30 11:14 267 查看
以前做过usb下载的东东,现在把它搞到u-boot-2010.06-rc1上去.

网上有usb下载的代码,可以在这儿下载:

http://blogimg.chinaunix.net/blog/upfile2/100109001526.bz2

一. 先编译过再说

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中结构体都是小写,跟下载的代码中结构体名字是大写的,需要将大写的名字改成小写的,这样才可以编译过去.

a. 将usbin.c中 

L21

    /* 

    extern S3C24X0_USB_DEVICE * usbdevregs;

    extern S3C24X0_DMAS * dmaregs;

    */

    extern struct s3c24x0_usb_device * usbdevregs;

    extern struct s3c24x0_dmas * dmaregs;

L32 解决: warning: suggest parentheses around arithmetic in operand of |

 #define SET_EP1_IN_PKT_READY()  usbdevregs->EP0_CSR_IN_CSR1_REG= ( (in_csr1 &(~ EPI_WR_BITS)) \

         | EPI_IN_PKT_READY )

 #define SET_EP1_SEND_STALL()    usbdevregs->EP0_CSR_IN_CSR1_REG= ( (in_csr1 & (~EPI_WR_BITS))\

         | EPI_SEND_STALL) )

 #define CLR_EP1_SENT_STALL()    usbdevregs->EP0_CSR_IN_CSR1_REG= ( (in_csr1 & (~EPI_WR_BITS))\

          &(~EPI_SENT_STALL) )

 #define FLUSH_EP1_FIFO()    usbdevregs->EP0_CSR_IN_CSR1_REG= ( (in_csr1 & (~EPI_WR_BITS))\

          |(EPI_FIFO_FLUSH) )

b. 将usblib.c中

L23

    /*

    extern S3C24X0_INTERRUPT * intregs;

    extern S3C24X0_USB_DEVICE * usbdevregs;

    extern S3C24X0_DMAS * dmaregs;

    */

    extern struct s3c24x0_interrupt * intregs;

    extern struct s3c24x0_usb_device *usbdevregs;

    extern struct s3c24x0_dmas * dmaregs;

c. usbinit.c 中 

L22

    /*

    extern S3C24X0_INTERRUPT * intregs;

    S3C24X0_USB_DEVICE * usbdevregs;

    S3C24X0_DMAS * dmaregs;

    S3C24X0_CLOCK_POWER * clk_powerregs;

    S3C24X0_GPIO * gpioregs;

    */

    extern struct s3c24x0_interrupt * intregs;

    struct s3c24x0_usb_device * usbdevregs;

    struct s3c24x0_dmas * dmaregs;

    struct s3c24x0_clock_power * clk_powerregs;

    struct s3c24x0_gpio * gpioregs;

L122:

    //gpioregs = S3C24X0_GetBase_GPIO(); 

    gpioregs = s3c24x0_get_base_gpio();

L222

    /*

    clk_powerregs = S3C24X0_GetBase_CLOCK_POWER();

    usbdevregs = S3C24X0_GetBase_USB_DEVICE();

    dmaregs = S3C24X0_GetBase_DMAS();

    */

    clk_powerregs = s3c24x0_get_base_clock_power();

    usbdevregs = s3c24x0_get_base_usb_device();

    dmaregs = s3c24x0_get_base_dmas();

L297

    //S3C24X0_INTERRUPT * intregs;

    struct s3c24x0_interrupt * intregs;

    //intregs = S3C24X0_GetBase_INTERRUPT();

    intregs = s3c24x0_get_base_interrupt();

d. usbmain.c 中 

L20

    /*

    extern S3C24X0_USB_DEVICE * usbdevregs;

    extern S3C24X0_DMAS * dmaregs;

    */

    extern struct s3c24x0_usb_device * usbdevregs;

    extern struct s3c24x0_dmas * dmaregs;

L444 解决: warning: suggest parentheses around arithmetic in operand of |

444     gpioregs->MISCCR = (gpioregs->MISCCR&~(7<<4)) | (clock_sel<<4);

445     gpioregs->GPHCON = (gpioregs->GPHCON&~(3<<18)) | (2<<18);

e. usbout.c中 

L28

    /*

    extern S3C24X0_INTERRUPT * intregs;

    extern S3C24X0_USB_DEVICE * usbdevregs;

    extern S3C24X0_DMAS * dmaregs;

    */

    extern struct s3c24x0_interrupt * intregs;

    extern struct s3c24x0_usb_device * usbdevregs;

    extern struct s3c24x0_dmas * dmaregs;

L188

    //ClearPending_my(BIT_DMA2);

   ClearPending(BIT_DMA2);

f. usbsetup.c中 

L19

    /*

    extern S3C24X0_INTERRUPT * intregs;

    extern S3C24X0_USB_DEVICE * usbdevregs;

    extern S3C24X0_DMAS * dmaregs;

    */

    extern struct s3c24x0_interrupt * intregs;

    extern struct s3c24x0_usb_device * usbdevregs;

    extern struct s3c24x0_dmas * dmaregs;

L46 解决: warning: suggest parentheses around arithmetic in operand of |

#define CLR_EP0_OUT_PKT_RDY()       usbdevregs->EP0_CSR_IN_CSR1_REG=( (ep0_csr
& (~EP0_WR_BITS))| \

        EP0_SERVICED_OUT_PKT_RDY )

#define CLR_EP0_OUTPKTRDY_DATAEND()     usbdevregs->EP0_CSR_IN_CSR1_REG=( (ep0_csr & (~EP0_WR_BITS) )| \

        (EP0_SERVICED_OUT_PKT_RDY|EP0_DATA_END) )

#define SET_EP0_IN_PKT_RDY()        usbdevregs->EP0_CSR_IN_CSR1_REG=( (ep0_csr & (~EP0_WR_BITS) ) | \

        (EP0_IN_PKT_READY) )

#define SET_EP0_INPKTRDY_DATAEND()  usbdevregs->EP0_CSR_IN_CSR1_REG=( (ep0_csr & (~EP0_WR_BITS))| \

        (EP0_IN_PKT_READY|EP0_DATA_END) )

#define CLR_EP0_SETUP_END()         usbdevregs->EP0_CSR_IN_CSR1_REG=( (ep0_csr & (~EP0_WR_BITS)) | \

        (EP0_SERVICED_SETUP_END) )

#define CLR_EP0_SENT_STALL()        usbdevregs->EP0_CSR_IN_CSR1_REG=( (ep0_csr & (~EP0_WR_BITS) )& \

        (~EP0_SENT_STALL) )

#define FLUSH_EP0_FIFO()        {while(usbdevregs->OUT_FIFO_CNT1_REG)usbdevregs->fifo[0].EP_FIFO_REG;}

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

common/cmd_usbslave.c 

 cmd_usbslave.c.txt 
 
(改名为: cmd_usbslave.c, 放在common/目录下)

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/
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: