Bootloader USB mode for PP502x. Enable only on GoGear SA9200 for the time being. Add HAVE_BOOTLOADER_USB_MODE to config if BOOTLOADER is defined to enable it. Clean up some kernel stuff a little to support it. Mess up a bunch of other stuff (hopefully not too badly).

git-svn-id: svn://svn.rockbox.org/rockbox/trunk@29053 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
Michael Sevakis 2011-01-15 08:19:30 +00:00
parent 53db95417d
commit 3a1127785b
26 changed files with 842 additions and 160 deletions

View file

@ -48,6 +48,7 @@
#include "usb.h"
#include "usb_drv.h"
#endif
#include "usb-target.h"
#if defined(SAMSUNG_YH925)
/* this function (in lcd-yh925.c) resets the screen orientation for the OF
* for use with dualbooting */
@ -451,8 +452,104 @@ int load_mi4_part(unsigned char* buf, struct partinfo* pinfo,
return EOK;
}
#endif /* (CONFIG_STORAGE & STORAGE_SD) */
#ifdef HAVE_BOOTLOADER_USB_MODE
/* Return USB_HANDLED if session took place else return USB_EXTRACTED */
static int handle_usb(int connect_timeout)
{
static struct event_queue q SHAREDBSS_ATTR;
struct queue_event ev;
int usb = USB_EXTRACTED;
long end_tick = 0;
if (!usb_plugged())
return USB_EXTRACTED;
queue_init(&q, true);
usb_init();
usb_start_monitoring();
/* Switch to verbose mode if not in it so that the status updates
* are shown */
/* TODO: Should we forgo any messages except the connect? It might be a
* charger, not a USB host. */
verbose = true;
printf("USB: Connecting");
if (connect_timeout != TIMEOUT_BLOCK)
end_tick = current_tick + connect_timeout;
while (1)
{
/* Sleep no longer than 1/2s */
queue_wait_w_tmo(&q, &ev, HZ/2);
if (ev.id == SYS_USB_CONNECTED)
{
/* Got the message - wait for disconnect */
printf("Bootloader USB mode");
usb = USB_HANDLED;
usb_acknowledge(SYS_USB_CONNECTED_ACK);
usb_wait_for_disconnect(&q);
break;
}
if (connect_timeout != TIMEOUT_BLOCK &&
TIME_AFTER(current_tick, end_tick))
{
/* Timed out waiting for the connect */
printf("USB: Timed out");
break;
}
if (!usb_plugged())
break; /* Cable pulled */
}
usb_close();
queue_delete(&q);
return usb;
}
#else /* !HAVE_BOOTLOADER_USB_MODE */
#if defined(SANSA_E200) || defined(SANSA_C200) || defined(PHILIPS_SA9200) \
|| defined (SANSA_VIEW)
/* Ignore cable state */
static int handle_usb(int connect_timeout)
{
return USB_EXTRACTED;
(void)connect_timeout;
}
#else
/* Return USB_INSERTED if cable present */
static int handle_usb(int connect_timeout)
{
int usb_retry = 0;
int usb = USB_EXTRACTED;
usb_init();
while (usb_drv_powered() && usb_retry < 5 && usb != USB_INSERTED)
{
usb_retry++;
sleep(HZ/4);
usb = usb_detect();
}
if (usb != USB_INSERTED)
usb = USB_EXTRACTED;
return usb;
(void)connect_timeout;
}
#endif
#endif /* HAVE_BOOTLOADER_USB_MODE */
void* main(void)
{
int i;
@ -460,29 +557,33 @@ void* main(void)
int rc;
int num_partitions;
struct partinfo* pinfo;
#if defined(SANSA_E200) || defined(SANSA_C200) || defined(PHILIPS_SA9200) \
|| defined (SANSA_VIEW)
#if !defined(USE_ROCKBOX_USB)
int usb_retry = 0;
#endif
bool usb = false;
#else
#if !(CONFIG_STORAGE & STORAGE_SD)
char buf[256];
unsigned short* identify_info;
#endif
int usb = USB_EXTRACTED;
chksum_crc32gentab ();
system_init();
kernel_init();
#ifdef HAVE_BOOTLOADER_USB_MODE
/* loader must service interrupts */
enable_interrupt(IRQ_FIQ_STATUS);
#endif
lcd_init();
font_init();
show_logo();
adc_init();
#ifdef HAVE_BOOTLOADER_USB_MODE
button_init_device();
#else
button_init();
#endif
#if defined(SANSA_E200) || defined(PHILIPS_SA9200)
i2c_init();
_backlight_on();
@ -506,20 +607,6 @@ void* main(void)
verbose = true;
}
#if defined(SANSA_E200) || defined(SANSA_C200) || defined(PHILIPS_SA9200)
#if !defined(USE_ROCKBOX_USB)
usb_init();
while (usb_drv_powered() && usb_retry < 5 && !usb)
{
usb_retry++;
sleep(HZ/4);
usb = (usb_detect() == USB_INSERTED);
}
if (usb)
btn |= BOOTLOADER_BOOT_OF;
#endif /* USE_ROCKBOX_USB */
#endif
lcd_setfont(FONT_SYSFIXED);
printf("Rockbox boot loader");
@ -560,6 +647,15 @@ void* main(void)
i, pinfo->type, pinfo->size / 2048);
}
/* Now that storage is initialized, check for USB connection */
if ((btn & BOOTLOADER_BOOT_OF) == 0)
{
usb_pin_init();
usb = handle_usb(HZ*2);
if (usb == USB_INSERTED)
btn |= BOOTLOADER_BOOT_OF;
}
/* Try loading Rockbox, if that fails, fall back to the OF */
if((btn & BOOTLOADER_BOOT_OF) == 0)
{
@ -576,7 +672,7 @@ void* main(void)
sleep(5*HZ);
}
else
return (void*)loadbuffer;
goto main_exit;
}
if(btn & BOOTLOADER_BOOT_OF)
@ -601,7 +697,7 @@ void* main(void)
printf("Can't load from partition");
printf(strerror(rc));
} else {
return (void*)loadbuffer;
goto main_exit;
}
} else {
printf("No hidden partition found.");
@ -615,7 +711,7 @@ void* main(void)
printf("Can't load /System/OF.ebn");
printf(strerror(rc));
} else {
return (void*)loadbuffer;
goto main_exit;
}
#endif
@ -628,7 +724,7 @@ void* main(void)
#if defined(SAMSUNG_YH925)
lcd_reset();
#endif
return (void*)loadbuffer;
goto main_exit;
}
printf("Trying /System/OF.bin");
@ -640,10 +736,17 @@ void* main(void)
#if defined(SAMSUNG_YH925)
lcd_reset();
#endif
return (void*)loadbuffer;
goto main_exit;
}
error(0, 0, true);
}
main_exit:
#ifdef HAVE_BOOTLOADER_USB_MODE
storage_close();
system_prepare_fw_start();
#endif
return (void*)loadbuffer;
}

View file

@ -508,8 +508,12 @@ target/arm/system-pp5002.c
target/arm/system-pp502x.c
#endif
#ifdef BOOTLOADER
target/arm/crt0-pp-bl.S
#ifdef HAVE_BOOTLOADER_USB_MODE
target/arm/crt0-pp502x-bl-usb.S
#else
target/arm/crt0-pp-bl.S
#endif /* HAVE_BOOTLOADER_USB_MODE */
#else /* !BOOTLOADER */
target/arm/pcm-pp.c
target/arm/debug-pp.c
#if !defined(SANSA_E200) && !defined(SANSA_C200)

View file

@ -693,7 +693,7 @@ Lyre prototype 1 */
#if (CONFIG_CODEC == SWCODEC)
#ifdef BOOTLOADER
#if CONFIG_CPU == IMX31L
#ifdef HAVE_BOOTLOADER_USB_MODE
/* Priority in bootloader is wanted */
#define HAVE_PRIORITY_SCHEDULING
#define USB_STATUS_BY_EVENT
@ -964,8 +964,8 @@ Lyre prototype 1 */
#ifdef BOOTLOADER
/* enable usb storage for targets that do bootloader usb */
#if (defined(TOSHIBA_GIGABEAT_S) || \
(defined(CREATIVE_ZVx) || \
#if defined(HAVE_BOOTLOADER_USB_MODE) || \
((defined(CREATIVE_ZVx) || \
defined(CPU_TCC77X) || defined(CPU_TCC780X))) || \
(CONFIG_USBOTG == USBOTG_JZ4740) || defined(IPOD_NANO2G) || \
CONFIG_USBOTG == USBOTG_AS3525

View file

@ -217,6 +217,10 @@
#define USB_VENDOR_ID 0x0930
#define USB_PRODUCT_ID 0x0010
#define HAVE_USB_HID_MOUSE
#ifdef BOOTLOADER
/* enable bootloader USB mode - ONLY define when also BOOTLOADER */
#define HAVE_BOOTLOADER_USB_MODE
#endif
/* Define this if you have ATA power-off control */
#define HAVE_ATA_POWER_OFF

View file

@ -172,10 +172,9 @@
#define USB_VENDOR_ID 0x0471
#define USB_PRODUCT_ID 0x014f
#define HAVE_USB_HID_MOUSE
/* WARNING! Enable Rockbox USB mass storage. */
#ifndef BOOTLOADER
#define USE_ROCKBOX_USB
#ifdef BOOTLOADER
/* enable bootloader USB mode - ONLY define when also BOOTLOADER */
#define HAVE_BOOTLOADER_USB_MODE
#endif
/* Define this if you have adjustable CPU frequency */

View file

@ -178,9 +178,10 @@ struct wakeup
/* global tick variable */
#if defined(CPU_PP) && defined(BOOTLOADER)
/* We don't enable interrupts in the iPod bootloader, so we need to fake
the current_tick variable */
#if defined(CPU_PP) && defined(BOOTLOADER) && \
!defined(HAVE_BOOTLOADER_USB_MODE)
/* We don't enable interrupts in the PP bootloader unless USB mode is
enabled for it, so we need to fake the current_tick variable */
#define current_tick (signed)(USEC_TIMER/10000)
static inline void call_tick_tasks(void)

View file

@ -224,6 +224,9 @@
#define CACHE_OP_FLUSH 0x0002
#define CACHE_OP_INVALIDATE 0x0004
/* Local interrupt vector table (set CACHE_CTL_VECT_REMAP to enable) */
#define INT_VECTOR_ENTRY(v) (*((volatile unsigned long *)(0x6000f100) + (v)))
/* GPIO Ports */
#define GPIO_BASE_ADDR 0x6000d000
#define GPIOA_ENABLE (*(volatile unsigned long *)(0x6000d000))

View file

@ -25,6 +25,10 @@
#include <stdbool.h>
#include "mv.h" /* for HAVE_MULTIDRIVE or not */
#ifdef HAVE_BOOTLOADER_USB_MODE
#define SD_DRIVER_CLOSE
#endif
#define SD_BLOCK_SIZE 512 /* XXX : support other sizes ? */
struct storage_info;

View file

@ -112,6 +112,7 @@ static inline void stub_storage_spindown(int timeout) { (void)timeout; }
#define storage_disk_is_active() 0
#define storage_soft_reset() (void)0
#define storage_init() sd_init()
#define storage_close() sd_close()
#ifdef HAVE_STORAGE_FLUSH
#define storage_flush() (void)0
#endif

View file

@ -55,6 +55,9 @@ enum {
#if defined(HAVE_USB_CHARGING_ENABLE) && defined(HAVE_USBSTACK)
USB_CHARGER_UPDATE, /* Event */
#endif
#ifdef HAVE_BOOTLOADER_USB_MODE
USB_HANDLED, /* Bootloader status code */
#endif
};
#ifdef HAVE_USB_POWER

View file

@ -48,10 +48,19 @@
#define KERNEL_ASSERT(exp, msg...) ({})
#endif
#if !defined(CPU_PP) || !defined(BOOTLOADER)
#if !defined(CPU_PP) || !defined(BOOTLOADER) || \
defined(HAVE_BOOTLOADER_USB_MODE)
volatile long current_tick SHAREDDATA_ATTR = 0;
#endif
/* Unless otherwise defined, do nothing */
#ifndef YIELD_KERNEL_HOOK
#define YIELD_KERNEL_HOOK() false
#endif
#ifndef SLEEP_KERNEL_HOOK
#define SLEEP_KERNEL_HOOK(ticks) false
#endif
/* List of tick tasks - final element always NULL for termination */
void (*tick_funcs[MAX_NUM_TICK_TASKS+1])(void);
@ -215,30 +224,25 @@ void timeout_register(struct timeout *tmo, timeout_cb_type callback,
****************************************************************************/
unsigned sleep(unsigned ticks)
{
#if defined(CPU_PP) && defined(BOOTLOADER)
unsigned stop = USEC_TIMER + ticks * (1000000/HZ);
while (TIME_BEFORE(USEC_TIMER, stop))
switch_thread();
#elif defined(CREATIVE_ZVx) && defined(BOOTLOADER)
/* hacky.. */
long sleep_ticks = current_tick + ticks + 1;
while (TIME_BEFORE(current_tick, sleep_ticks))
switch_thread();
#else
/* In certain situations, certain bootloaders in particular, a normal
* threading call is inappropriate. */
if (SLEEP_KERNEL_HOOK(ticks))
return 0; /* Handled */
disable_irq();
sleep_thread(ticks);
switch_thread();
#endif
return 0;
}
void yield(void)
{
#if ((defined(TATUNG_TPJ1022)) && defined(BOOTLOADER))
/* Some targets don't like yielding in the bootloader */
#else
/* In certain situations, certain bootloaders in particular, a normal
* threading call is inappropriate. */
if (YIELD_KERNEL_HOOK())
return; /* handled */
switch_thread();
#endif
}
/****************************************************************************

View file

@ -154,6 +154,9 @@ static long last_disk_activity = -1;
/** static, private data **/
static bool initialized = false;
static unsigned int sd_thread_id = 0;
#define Q_CLOSE 1
static long next_yield = 0;
#define MIN_YIELD_PERIOD 1000
@ -1106,7 +1109,9 @@ sd_write_error:
}
}
#ifndef SD_DRIVER_CLOSE
static void sd_thread(void) NORETURN_ATTR;
#endif
static void sd_thread(void)
{
struct queue_event ev;
@ -1175,10 +1180,30 @@ static void sd_thread(void)
case SYS_USB_DISCONNECTED:
usb_acknowledge(SYS_USB_DISCONNECTED_ACK);
break;
#ifdef SD_DRIVER_CLOSE
case Q_CLOSE:
return;
#endif
}
}
}
#ifdef SD_DRIVER_CLOSE
void sd_close(void)
{
unsigned int thread_id = sd_thread_id;
if (thread_id == 0)
return;
sd_thread_id = 0;
queue_post(&sd_queue, Q_CLOSE, 0);
thread_wait(thread_id);
}
#endif /* SD_DRIVER_CLOSE */
void sd_enable(bool on)
{
if(on)
@ -1241,8 +1266,8 @@ int sd_init(void)
ret = currcard->initialized;
queue_init(&sd_queue, true);
create_thread(sd_thread, sd_stack, sizeof(sd_stack), 0,
sd_thread_name IF_PRIO(, PRIORITY_USER_INTERFACE)
sd_thread_id = create_thread(sd_thread, sd_stack, sizeof(sd_stack),
0, sd_thread_name IF_PRIO(, PRIORITY_USER_INTERFACE)
IF_COP(, CPU));
/* enable interupt for the mSD card */

View file

@ -21,6 +21,10 @@
#ifdef CPU_PP
#ifdef HAVE_BOOTLOADER_USB_MODE
#define ATA_DRIVER_CLOSE
#endif
/* primary channel */
#define ATA_DATA (*((volatile unsigned short*)(IDE_BASE + 0x1e0)))
#define ATA_ERROR (*((volatile unsigned char*)(IDE_BASE + 0x1e4)))

View file

@ -0,0 +1,362 @@
/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
* $Id$
*
* Copyright (C) 2002 by Linus Nielsen Feltzing
* Copyright (C) 2010 by Michael Sevakis
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
****************************************************************************/
#include "config.h"
#include "cpu.h"
/* PortalPlayer bootloader and startup code based on startup.s from the iPodLinux
* loader
*
* Copyright (c) 2003, Daniel Palffy (dpalffy (at) rainstorm.org)
* Copyright (c) 2005, Bernard Leach <leachbj@bouncycastle.org>
*
*/
.equ PROC_ID, 0x60000000
.equ CPU_IDIS, 0x60004028
.equ CPU_CTRL, 0x60007000
.equ CPU_STATUS, 0x60007000
.equ COP_IDIS, 0x60004038
.equ COP_CTRL, 0x60007004
.equ COP_STATUS, 0x60007004
.equ CPU_SLEEPING,0x80000000
.equ COP_SLEEPING,0x80000000
.equ SLEEP, 0x80000000
.equ WAKE, 0x00000000
.equ MMAP_LOG, 0xf000f000 /* MMAP0 */
.equ MMAP_PHYS, 0xf000f004
.equ INT_VECT_TBL,0x6000f100
.equ CACHE_CTRL, 0x6000c000
.equ CACHE_ENAB, 0x1
.equ CACHE_OP_COMMIT_DISCARD, 0x1
.equ CACHE_OP_COMMIT , 0x0
#if MEM > 32
.equ MMAP_MASK, 0x00003c00
#else
.equ MMAP_MASK, 0x00003e00
#endif
.equ MMAP_FLAGS, 0x00000f84
/*
* Entry point
*/
.section .init.text,"ax",%progbits
.global start
start:
b newstart
#ifdef IPOD_ARCH
.align 8 /* starts at 0x100 */
.global boot_table
boot_table:
/* here comes the boot table, don't move its offset - preceding
code+data must stay <= 256 bytes */
.space 400
#else /* !IPOD_ARCH */
/* (more than enough) space for exception vectors and mi4 magic */
.space 68*4
#endif /* IPOD_ARCH */
newstart:
msr cpsr_c, #0xd3 /* enter supervisor mode, disable IRQ/FIQ */
adr r4, start /* cache initial load address */
/* Copy startup stub to IRAM since we need to both move the bootloader's
* location, which could overlap itself, and setup the memory mapper. */
adr r0, start_stub_begin
mov r1, #0x40000000
adr r2, start_stub_end
1:
ldr r3, [r0], #4
str r3, [r1], #4
cmp r0, r2
blo 1b
mov pc, #0x40000000
start_stub_begin:
ldr r0, =PROC_ID
ldrb r0, [r0]
cmp r0, #0x55
beq cpu
cop:
mov r0, #CACHE_OP_COMMIT_DISCARD
bl cache_operation
ldr r1, =COP_CTRL
mov r0, #SLEEP
/* sleep us (co-processor) while bootloader is copied */
str r0, [r1]
nop
nop
nop
/* branch to final physical load address */
ldr r2, =1f
and r4, r4, #0xfc000000
add pc, r2, r4
1:
/* wait for bootloader to finish */
str r0, [r1]
nop
nop
nop
/* branch to the address returned by main() */
adr r0, startup_loc
ldr pc, [r0]
cpu:
/* wait for COP to sleep */
ldr r1, =COP_STATUS
1:
ldr r0, [r1]
tst r0, #COP_SLEEPING
beq 1b
mov r0, #CACHE_OP_COMMIT_DISCARD
bl cache_operation
/* move bootloader to the correct load address if needed */
ldr r1, =_loadaddress
cmp r4, r1
ldrne r2, =_loadaddressend
movne r0, r4
sublo r3, r2, r1 /* size */
addlo r0, r0, r3 /* initial load end addr */
1: /* lower to higher move - copy up */
cmphi r2, r1
ldrhi r3, [r0], #4
strhi r3, [r1], #4
bhi 1b
1: /* higher to lower move - copy down */
cmplo r1, r2
ldrlo r3, [r0, #-4]!
strlo r3, [r2, #-4]!
blo 1b
mov r0, #CACHE_OP_COMMIT
bl cache_operation
and r4, r4, #0xfc000000
ldr r0, =MMAP_FLAGS
orr r0, r0, r4 /* adjust for execute address */
ldr r1, =MMAP_MASK
ldr r2, =MMAP_LOG
ldr r3, =MMAP_PHYS
str r1, [r2] /* MMAP_LOG = MMAP_MASK */
str r0, [r3] /* MMAP_PHYS = MMAP_FLAGS | SDRAM base addr */
/* wake the COP to jump it to the correct place */
ldr r1, =COP_CTRL
mov r0, #WAKE
str r0, [r1]
/* wait for COP to halt then loading may proceed */
ldr r1, =COP_STATUS
1:
ldr r0, [r1]
tst r0, #COP_SLEEPING
beq 1b
ldr r0, =start_stub_end
add pc, r0, r4
cache_operation: /* (bool commit_discard) */
ldr r2, =CACHE_CTRL
ldr r1, [r2]
tst r1, #CACHE_ENAB
bxeq lr
cmp r0, #CACHE_OP_COMMIT
ldr r0, =0xf000f044
ldr r1, [r0]
orrne r1, r1, #0x6
orreq r1, r1, #0x2
str r1, [r0]
1:
ldr r1, [r2]
tst r1, #0x8000
bne 1b
bx lr
.ltorg /* constants used in stub come with us to IRAM */
start_stub_end:
/* now executing from final physical address */
/* copy the vector addresses to the table */
ldr r0, =INT_VECT_TBL
adr r1, vectorsstart
adr r2, vectorsend
1:
cmp r2, r1
ldrhi r3, [r1], #4
strhi r3, [r0], #4
bhi 1b
/* Copy the IRAM */
ldr r0, =_iramcopy
ldr r1, =_iramstart
ldr r2, =_iramend
1:
cmp r2, r1
ldrhi r3, [r0], #4
strhi r3, [r1], #4
bhi 1b
mov r0, #0
/* Zero out IBSS */
ldr r1, =_iedata
ldr r2, =_iend
1:
cmp r2, r1
strhi r0, [r1], #4
bhi 1b
/* Initialise bss/ncbss sections to zero */
ldr r1, =_edata
ldr r2, =_end
1:
cmp r2, r1
strhi r0, [r1], #4
bhi 1b
/* Set up some stack and munge it with 0xdeadbeef */
ldr r0, =0xdeadbeef
ldr r1, =stackbegin
ldr sp, =stackend
1:
cmp sp, r1
strhi r0, [r1], #4
bhi 1b
/* Set up stack for IRQ mode */
msr cpsr_c, #0xd2 /* IRQ/FIQ disabled */
ldr sp, =irq_stack
/* Let abort and undefined modes use IRQ stack */
msr cpsr_c, #0xd7 /* IRQ/FIQ disabled */
ldr sp, =irq_stack
msr cpsr_c, #0xdb /* IRQ/FIQ disabled */
ldr sp, =irq_stack
/* Switch back to supervisor mode */
msr cpsr_c, #0xd3
/* execute the loader - this will load an image to 0x10000000 */
ldr r0, =main
mov lr, pc
bx r0
/* store actual startup location returned by main() */
ldr r1, =startup_loc
str r0, [r1]
/* write back anything loaded + startup_loc */
mov r0, #CACHE_OP_COMMIT
bl cache_operation
mov r0, #0
/* disable memory mapper */
ldr r1, =MMAP_LOG
ldr r2, =MMAP_PHYS
str r0, [r1]
str r0, [r2]
/* bring COP back to life */
ldr r1, =COP_CTRL
mov r0, #WAKE
str r0, [r1]
/* after this point, r0-r3 are reserved for OF magic */
#if defined(SANSA_C200) || defined(PHILIPS_HDD1630)
/* Magic for loading the c200 OF */
ldr r0, =0xb00d10ad
mov r1, #0x700
ldr r2, =0xfff0
mov r3, #0x7
#endif
#if defined(PHILIPS_HDD6330)
/* Magic for loading the HDD6XX0 OF */
ldr r0, =0xb00d10ad
mov r1, #0x800
ldr r2, =0xfff0
mov r3, #0x7
#endif
/* branch to the address returned by main() */
adr r4, startup_loc
ldr pc, [r4]
startup_loc:
.word 0x00000000
/* exception handlers: will be copied to local vector table */
vectorsstart:
.word newstart
.word undef_instr_handler
.word software_int_handler
.word prefetch_abort_handler
.word data_abort_handler
.word reserved_handler
.word irq_handler
.word fiq_handler
vectorsend:
.text
/* All illegal exceptions call into UIE with exception address as first
parameter. This is calculated differently depending on which exception
we're in. Second parameter is exception number, used for a string lookup
in UIE.
*/
undef_instr_handler:
sub r0, lr, #4
mov r1, #0
b UIE
/* We run supervisor mode most of the time, and should never see a software
exception being thrown. Perhaps make it illegal and call UIE?
*/
software_int_handler:
reserved_handler:
movs pc, lr
prefetch_abort_handler:
sub r0, lr, #4
mov r1, #1
b UIE
data_abort_handler:
sub r0, lr, #8
mov r1, #2
b UIE
/* should never happen in the bootloader */
fiq_handler:
subs pc, lr, #4
/* 256 words of IRQ stack */
.section .bss
.balign 16
.space 256*4
irq_stack:

View file

@ -22,7 +22,7 @@
#include "system.h"
#include "kernel.h"
#ifndef BOOTLOADER
#if !defined(BOOTLOADER) || defined(HAVE_BOOTLOADER_USB_MODE)
void TIMER1(void)
{
/* Run through the list of tick tasks (using main core) */
@ -42,7 +42,7 @@ void TIMER1(void)
/* Must be last function called init kernel/thread initialization */
void tick_start(unsigned int interval_in_ms)
{
#ifndef BOOTLOADER
#if !defined(BOOTLOADER) || defined(HAVE_BOOTLOADER_USB_MODE)
TIMER1_CFG = 0x0;
TIMER1_VAL;
/* enable timer */
@ -54,3 +54,11 @@ void tick_start(unsigned int interval_in_ms)
(void)interval_in_ms;
#endif
}
#ifdef HAVE_BOOTLOADER_USB_MODE
void tick_stop(void)
{
CPU_INT_DIS = TIMER1_MASK;
TIMER1_CFG = 0;
}
#endif

View file

@ -3,11 +3,12 @@
ENTRY(start)
OUTPUT_FORMAT(elf32-littlearm)
OUTPUT_ARCH(arm)
STARTUP(target/arm/crt0-pp-bl.o)
STARTUP(target/arm/crt0-pp502x-bl-usb.o)
#define DRAMSIZE (MEMORYSIZE * 0x100000)
#define DRAMORIG 0x10000000
#define DRAMORIG 0x01000000 /* Load at 16 MB */
#define DRAMSIZE 0x00100000 /* 1MB for bootloader */
#define MEMEND (MEMORYSIZE*0x100000) /* From virtual mapping at 0 */
#define NOCACHE_BASE 0x10000000
#ifndef IRAMORIG
#define IRAMORIG 0x40000000
#endif
@ -15,6 +16,8 @@ STARTUP(target/arm/crt0-pp-bl.o)
#define FLASHORIG 0x001f0000
#define FLASHSIZE 2M
#define CACHEALIGN_SIZE 16
MEMORY
{
DRAM : ORIGIN = DRAMORIG, LENGTH = DRAMSIZE
@ -23,44 +26,112 @@ MEMORY
SECTIONS
{
. = IRAMORIG;
. = DRAMORIG;
_loadaddress = . + NOCACHE_BASE;
.text : {
.text :
{
*(.init.text)
*(.text*)
*(.glue_7)
*(.glue_7t)
. = ALIGN(0x4);
} > DRAM
.rodata :
{
*(.rodata) /* problems without this, dunno why */
*(.rodata*)
*(.rodata.str1.1)
*(.rodata.str1.4)
. = ALIGN(0x4);
} > DRAM
.data :
{
*(.data*)
. = ALIGN(0x4);
} > DRAM
/* .ncdata section is placed at uncached physical alias address and is
* loaded at the proper cached virtual address - no copying is
* performed in the init code */
.ncdata . + NOCACHE_BASE :
{
. = ALIGN(CACHEALIGN_SIZE);
*(.ncdata*)
. = ALIGN(CACHEALIGN_SIZE);
} AT> DRAM
/DISCARD/ . - NOCACHE_BASE :
{
*(.eh_frame)
} > DRAM
_noloaddram = .;
.ibss IRAMORIG (NOLOAD) :
{
_iedata = .;
*(.qharray)
*(.ibss)
. = ALIGN(0x4);
_iend = .;
} > IRAM
.data : {
.iram _iend :
{
_iramstart = .;
*(.icode)
*(.irodata)
*(.idata)
*(.data*)
*(.ncdata*)
*(.rodata*)
_dataend = . ;
} > IRAM
_iramend = .;
} > IRAM AT> DRAM
.stack (NOLOAD) : {
_iramcopy = LOADADDR(.iram);
.loadaddressend :
{
_loadaddressend = . + NOCACHE_BASE;
} AT> DRAM
.stack (NOLOAD) :
{
. = ALIGN(8);
*(.stack)
_stackbegin = .;
stackbegin = .;
. += 0x2000;
_stackend = .;
stackend = .;
} > IRAM
/* The bss section is too large for IRAM - we just move it 16MB into the
DRAM */
. = DRAMORIG;
.bss . + (16*1024*1024) (NOLOAD) : {
/* .bss and .ncbss are treated as a single section to use one init loop
* to zero them - note "_edata" and "_end" */
.bss _noloaddram (NOLOAD) :
{
_edata = .;
*(.bss*);
*(.ibss);
*(.bss*)
*(COMMON)
*(.ncbss*);
} > DRAM
.ncbss . + NOCACHE_BASE (NOLOAD) :
{
. = ALIGN(CACHEALIGN_SIZE);
*(.ncbss*)
. = ALIGN(CACHEALIGN_SIZE);
} AT> DRAM
/* This will be aligned by preceding alignments */
.endaddr . - NOCACHE_BASE (NOLOAD) :
{
_end = .;
} > DRAM
/* Reference to all DRAM after loaded bootloader image */
.freebuffer _end (NOLOAD) :
{
. = ALIGN(4);
freebuffer = .;
. = MEMEND-1;
freebufferend = .;
}
}

View file

@ -119,6 +119,10 @@ void button_int(void)
void button_init_device(void)
{
}
void button_int(void)
{
}
#endif /* BOOTLOADER */
bool button_hold(void)

View file

@ -34,10 +34,7 @@
bool button_hold(void);
void button_init_device(void);
int button_read_device(void);
#ifndef BOOTLOADER
void button_int(void);
#endif
/* Main unit's buttons */
#define BUTTON_POWER 0x00000001

View file

@ -33,7 +33,7 @@
#include "lcd-remote-target.h"
#endif
#ifndef BOOTLOADER
#if !defined(BOOTLOADER) || defined(HAVE_BOOTLOADER_USB_MODE)
extern void TIMER1(void);
extern void TIMER2(void);
extern void SERIAL0(void);
@ -184,15 +184,33 @@ void __attribute__((interrupt("IRQ"))) irq_handler(void)
TIMER2();
}
}
#endif /* BOOTLOADER */
#endif /* BOOTLOADER || HAVE_BOOTLOADER_USB_MODE */
/* TODO: The following function has been lifted straight from IPL, and
hence has a lot of numeric addresses used straight. I'd like to use
#defines for these, but don't know what most of them are for or even what
they should be named. Because of this I also have no way of knowing how
to extend the funtions to do alternate cache configurations. */
#if !defined(BOOTLOADER) || defined(HAVE_BOOTLOADER_USB_MODE)
static void disable_all_interrupts(void)
{
COP_HI_INT_DIS = -1;
CPU_HI_INT_DIS = -1;
HI_INT_FORCED_CLR = -1;
COP_INT_DIS = -1;
CPU_INT_DIS = -1;
INT_FORCED_CLR = -1;
GPIOA_INT_EN = 0;
GPIOB_INT_EN = 0;
GPIOC_INT_EN = 0;
GPIOD_INT_EN = 0;
GPIOE_INT_EN = 0;
GPIOF_INT_EN = 0;
GPIOG_INT_EN = 0;
GPIOH_INT_EN = 0;
GPIOI_INT_EN = 0;
GPIOJ_INT_EN = 0;
GPIOK_INT_EN = 0;
GPIOL_INT_EN = 0;
}
#ifndef BOOTLOADER
void ICODE_ATTR cpucache_commit(void)
{
if (CACHE_CTL & CACHE_CTL_ENABLE)
@ -217,13 +235,17 @@ void cpucache_invalidate(void) __attribute__((alias("cpucache_commit_discard")))
static void init_cache(void)
{
/* Initialising the cache in the iPod bootloader prevents Rockbox from starting */
/* Initialising the cache in the iPod bootloader may prevent Rockbox from starting
* depending on the model */
/* cache init mode */
CACHE_CTL &= ~(CACHE_CTL_ENABLE | CACHE_CTL_RUN);
CACHE_CTL |= CACHE_CTL_INIT;
#ifndef BOOTLOADER
/* what's this do? */
CACHE_PRIORITY |= CURRENT_CORE == CPU ? 0x10 : 0x20;
#endif
/* Cache if (addr & mask) >> 16 == (mask & match) >> 16:
* yes: 0x00000000 - 0x03ffffff
@ -238,10 +260,11 @@ static void init_cache(void)
CACHE_CTL |= CACHE_CTL_INIT | CACHE_CTL_ENABLE | CACHE_CTL_RUN;
nop; nop; nop; nop;
}
#endif /* !BOOTLOADER */
#endif /* BOOTLOADER || HAVE_BOOTLOADER_USB_MODE*/
/* We need this for Sansas since we boost the cpu in their bootloader */
#if !defined(BOOTLOADER) || defined(SANSA_E200) || defined(SANSA_C200) || \
#if !defined(BOOTLOADER) || defined(HAVE_BOOTLOADER_USB_MODE) || \
defined(SANSA_E200) || defined(SANSA_C200) || \
defined(PHILIPS_SA9200)
void scale_suspend_core(bool suspend) ICODE_ATTR;
void scale_suspend_core(bool suspend)
@ -386,7 +409,8 @@ static void pp_set_cpu_frequency(long frequency)
corelock_unlock(&cpufreq_cl);
#endif
}
#endif /* !BOOTLOADER || SANSA_E200 || SANSA_C200 || PHILIPS_SA9200 */
#endif /* !BOOTLOADER || HAVE_BOOTLOADER_USB_MODE ||
SANSA_E200 || SANSA_C200 || PHILIPS_SA9200 */
void system_init(void)
{
@ -494,27 +518,7 @@ void system_init(void)
MMAP_PHYS_DATA_MASK | MMAP_PHYS_CODE_MASK;
#endif
/* disable all irqs */
COP_HI_INT_DIS = -1;
CPU_HI_INT_DIS = -1;
HI_INT_FORCED_CLR = -1;
COP_INT_DIS = -1;
CPU_INT_DIS = -1;
INT_FORCED_CLR = -1;
GPIOA_INT_EN = 0;
GPIOB_INT_EN = 0;
GPIOC_INT_EN = 0;
GPIOD_INT_EN = 0;
GPIOE_INT_EN = 0;
GPIOF_INT_EN = 0;
GPIOG_INT_EN = 0;
GPIOH_INT_EN = 0;
GPIOI_INT_EN = 0;
GPIOJ_INT_EN = 0;
GPIOK_INT_EN = 0;
GPIOL_INT_EN = 0;
disable_all_interrupts();
#ifdef HAVE_ADJUSTABLE_CPU_FREQ
#if NUM_CORES > 1
@ -534,13 +538,23 @@ void system_init(void)
}
init_cache();
#else /* BOOTLOADER */
if (CURRENT_CORE == CPU)
{
#else /* !BOOTLOADER */
/* Only the CPU gets here in the bootloader */
#ifdef HAVE_BOOTLOADER_USB_MODE
disable_all_interrupts();
init_cache();
/* Use the local vector map */
CACHE_CTL |= CACHE_CTL_VECT_REMAP;
#endif /* HAVE_BOOTLOADER_USB_MODE */
#if defined(SANSA_C200) || defined(SANSA_E200) || defined(PHILIPS_SA9200)
pp_set_cpu_frequency(CPUFREQ_MAX);
#endif
}
/* Else the frequency shot get changed upon USB connect -
* decide per-target */
#endif /* BOOTLOADER */
}
@ -582,3 +596,11 @@ int system_memory_guard(int newmode)
(void)newmode;
return 0;
}
#ifdef HAVE_BOOTLOADER_USB_MODE
void system_prepare_fw_start(void)
{
tick_stop();
disable_all_interrupts();
}
#endif

View file

@ -141,7 +141,7 @@ static inline void wake_core(int core)
}
#endif
#ifdef BOOTLOADER
#if defined(BOOTLOADER) && !defined(HAVE_BOOTLOADER_USB_MODE)
/* All addresses within rockbox are in IRAM in the bootloader so
are therefore uncached */
#define UNCACHED_ADDR(a) (a)
@ -163,7 +163,7 @@ static inline void wake_core(int core)
#endif
/** cache functions **/
#ifndef BOOTLOADER
#if !defined(BOOTLOADER) || defined(HAVE_BOOTLOADER_USB_MODE)
#define HAVE_CPUCACHE_COMMIT_DISCARD
#define HAVE_CPUCACHE_COMMIT
/* deprecated alias */
@ -175,6 +175,30 @@ static inline void wake_core(int core)
extern unsigned char probed_ramsize;
#endif
#ifdef BOOTLOADER
#if defined(TATUNG_TPJ1022)
/* Some targets don't like yielding in the bootloader - force
* yield() to return without a context switch. */
#define YIELD_KERNEL_HOOK() true
#endif
#ifdef HAVE_BOOTLOADER_USB_MODE
void tick_stop(void);
void system_prepare_fw_start(void);
#else /* !HAVE_BOOTLOADER_USB_MODE */
/* Busy "sleep" without a tick */
#define SLEEP_KERNEL_HOOK(ticks) \
({ unsigned _stop = USEC_TIMER + ((ticks) + 1) * (1000000/HZ); \
while (TIME_BEFORE(USEC_TIMER, _stop)) \
switch_thread(); \
true; })
#endif /* HAVE_BOOTLOADER_USB_MODE */
#endif /* BOOTLOADER */
#endif /* CPU_PP */
#endif /* SYSTEM_TARGET_H */

View file

@ -34,4 +34,13 @@ void udelay(int usec);
void dm320_set_io (char pin_num, bool input, bool invert, bool irq, bool irqany,
bool chat, char func_num );
#if defined(CREATIVE_ZVx) && defined(BOOTLOADER)
#define SLEEP_KERNEL_HOOK(ticks) \
({ \ /* hacky.. */
long _sleep_ticks = current_tick + ticks + 1; \
while (TIME_BEFORE(current_tick, _sleep_ticks)) \
switch_thread(); \
true; }) /* handled here */
#endif
#endif /* SYSTEM_TARGET_H */

View file

@ -27,7 +27,7 @@
#include "usb.h"
#include "usb-target.h"
void usb_init_device(void)
void usb_pin_init(void)
{
/* TODO: add USB init for iPod 3rd gen */
@ -38,6 +38,9 @@ void usb_init_device(void)
#endif
}
/* No different for now */
void usb_init_device(void) __attribute__((alias("usb_pin_init")));
void usb_enable(bool on)
{
/* This device specific code will eventually give way to proper USB
@ -70,3 +73,6 @@ int usb_detect(void)
return USB_EXTRACTED;
}
/* No different for now */
void usb_plugged(void) __attribute__((alias("usb_detect")));

View file

@ -106,6 +106,18 @@
#define USB_GPIO_INT_CLR GPIO_INT_CLR(USB_GPIO)
#define USB_GPIO_HI_INT_MASK GPIO_HI_INT_MASK(USB_GPIO)
/* Enable raw status pin read only - not interrupt */
void usb_pin_init(void)
{
GPIO_CLEAR_BITWISE(USB_GPIO_OUTPUT_EN, USB_GPIO_MASK);
GPIO_SET_BITWISE(USB_GPIO_ENABLE, USB_GPIO_MASK);
#ifdef USB_FIREWIRE_HANDLING
/* GPIO C bit 1 is firewire detect */
GPIO_CLEAR_BITWISE(GPIOC_OUTPUT_EN, 0x02);
GPIO_SET_BITWISE(GPIOC_ENABLE, 0x02);
#endif
}
void usb_init_device(void)
{
/* enable usb module */
@ -140,12 +152,12 @@ void usb_init_device(void)
DEV_INIT2 &= ~INIT_USB;
#endif
/* These set INV_LEV to the inserted level so it will fire if already
usb_pin_init();
/* These set INT_LEV to the inserted level so it will fire if already
* inserted at the time they are enabled. */
#ifdef USB_STATUS_BY_EVENT
GPIO_CLEAR_BITWISE(USB_GPIO_INT_EN, USB_GPIO_MASK);
GPIO_CLEAR_BITWISE(USB_GPIO_OUTPUT_EN, USB_GPIO_MASK);
GPIO_SET_BITWISE(USB_GPIO_ENABLE, USB_GPIO_MASK);
GPIO_WRITE_BITWISE(USB_GPIO_INT_LEV, USB_GPIO_VAL, USB_GPIO_MASK);
USB_GPIO_INT_CLR = USB_GPIO_MASK;
GPIO_SET_BITWISE(USB_GPIO_INT_EN, USB_GPIO_MASK);
@ -154,23 +166,12 @@ void usb_init_device(void)
#ifdef USB_FIREWIRE_HANDLING
/* GPIO C bit 1 is firewire detect */
GPIO_CLEAR_BITWISE(GPIOC_INT_EN, 0x02);
GPIO_CLEAR_BITWISE(GPIOC_OUTPUT_EN, 0x02);
GPIO_SET_BITWISE(GPIOC_ENABLE, 0x02);
GPIO_WRITE_BITWISE(GPIOC_INT_LEV, 0x00, 0x02);
GPIOC_INT_CLR = 0x02;
GPIO_SET_BITWISE(GPIOC_INT_EN, 0x02);
CPU_HI_INT_EN = GPIO0_MASK;
#endif
CPU_INT_EN = HI_MASK;
#else
/* No interrupt - setup pin read only (BOOTLOADER) */
GPIO_CLEAR_BITWISE(USB_GPIO_OUTPUT_EN, USB_GPIO_MASK);
GPIO_SET_BITWISE(USB_GPIO_ENABLE, USB_GPIO_MASK);
#ifdef USB_FIREWIRE_HANDLING
/* GPIO C bit 1 is firewire detect */
GPIO_CLEAR_BITWISE(GPIOC_OUTPUT_EN, 0x02);
GPIO_SET_BITWISE(GPIOC_ENABLE, 0x02);
#endif
#endif /* USB_STATUS_BY_EVENT */
}
@ -185,10 +186,12 @@ void usb_enable(bool on)
}
else {
usb_core_exit();
#ifndef BOOTLOADER
/* Disable USB devices */
DEV_EN &=~ DEV_USB0;
DEV_EN &=~ DEV_USB1;
DEV_INIT2 &=~ INIT_USB;
#endif
}
}
@ -197,7 +200,7 @@ void usb_attach(void)
usb_drv_attach();
}
static bool usb_pin_state(void)
bool usb_plugged(void)
{
return (USB_GPIO_INPUT_VAL & USB_GPIO_MASK) == USB_GPIO_VAL;
}
@ -226,12 +229,27 @@ void usb_insert_int(void)
* invalid bus reset when unplugging by checking the pin state. */
void usb_drv_usb_detect_event(void)
{
if(usb_pin_state()) {
if(usb_plugged()) {
usb_status_event(USB_INSERTED);
}
}
#endif /* USB_STATUS_BY_EVENT */
#ifdef HAVE_BOOTLOADER_USB_MODE
/* Replacement function that returns all unused memory after the bootloader
* because the storage driver uses the audio buffer */
extern unsigned char freebuffer[];
extern unsigned char freebufferend[];
unsigned char *audio_get_buffer(bool talk_buf, size_t *buffer_size)
{
if (buffer_size)
*buffer_size = freebufferend - freebuffer + 1;
return freebuffer;
(void)talk_buf;
}
#endif /* HAVE_BOOTLOADER_USB_MODE */
void usb_drv_int_enable(bool enable)
{
/* enable/disable USB IRQ in CPU */
@ -249,7 +267,7 @@ int usb_detect(void)
#ifdef USB_STATUS_BY_EVENT
return usb_status;
#else
return usb_pin_state() ? USB_INSERTED : USB_EXTRACTED;
return usb_plugged() ? USB_INSERTED : USB_EXTRACTED;
#endif
}

View file

@ -24,5 +24,11 @@
void usb_init_device(void);
void usb_insert_int(void);
void firewire_insert_int(void);
void usb_pin_init(void); /* Init the GPIO input only */
bool usb_plugged(void); /* Returns instantaneous state - always */
#ifdef HAVE_BOOTLOADER_USB_MODE
#define USB_DRIVER_CLOSE
#endif
#endif

View file

@ -46,7 +46,7 @@
/* Conditions under which we want the entire driver */
#if !defined(BOOTLOADER) || (CONFIG_CPU == SH7034) || \
(defined(TOSHIBA_GIGABEAT_S) && defined(USE_ROCKBOX_USB) && defined(USB_ENABLE_STORAGE)) || \
(defined(HAVE_USBSTACK) && defined(HAVE_BOOTLOADER_USB_MODE)) || \
(defined(HAVE_USBSTACK) && (defined(CREATIVE_ZVx))) || \
(defined(HAVE_USBSTACK) && (defined(OLYMPUS_MROBE_500))) || \
(defined(HAVE_USBSTACK) && (defined(IPOD_NANO2G))) || \

View file

@ -451,8 +451,8 @@ void usb_storage_init_connection(void)
/* prime rx endpoint. We only need room for commands */
state = WAITING_FOR_COMMAND;
#if CONFIG_CPU == IMX31L || defined(CPU_TCC77X) || defined(CPU_TCC780X) || \
defined(BOOTLOADER) || CONFIG_CPU == DM320
#if (CONFIG_CPU == IMX31L || defined(CPU_TCC77X) || defined(CPU_TCC780X) || \
defined(BOOTLOADER) || CONFIG_CPU == DM320) && !defined(CPU_PP502x)
static unsigned char _cbw_buffer[MAX_CBW_SIZE]
USB_DEVBSS_ATTR __attribute__((aligned(32)));
cbw_buffer = (void *)_cbw_buffer;