- we increase the DFU size from 4k to 16k size. This is mainly due to the

SAM7S128 and SAM7S256 being restricted to 16k lock region size.  If we want
  to lock the bootloader, it has to be 16k aligned.  This wastes a lot of
  memory, since a non-debug DFU implementation fits currently into less than
  4k. But anyway, we have lots of flexibility for the future given that amount
  of space.
- The DFU size change introduces also a change in dfu_api location to 0x103fd0
- Allow GETSTATE and GETSTATUS from runtime mode (optional in DFU spec)
- Make dfu_status a .data.shared variable, since it is used from GETSTATUS
  which we already support in runtime mode
- do some led switching while flashing via DFU
- disable all non-usb/dbgu interrupts when switching to DFU mode
- fix interrupt-storm problem when dbgu is used in DFU loader
- add missing linker script for SAM7S128


git-svn-id: https://svn.openpcd.org:2342/trunk@218 6dc7ffe9-61d6-0310-9af1-9938baff3ed1
This commit is contained in:
laforge 2006-09-22 21:29:57 +00:00
parent 238c6c3c0a
commit 1c2b1d2201
8 changed files with 159 additions and 29 deletions

View File

@ -0,0 +1,94 @@
/* Memory Definitions */
MEMORY
{
FLASH (rx) : ORIGIN = 0x00104000, LENGTH = (0x00020000 - 0x4000)
DATA (rw) : ORIGIN = 0x00200028, LENGTH = (0x00008000 - 0x28)
STACK (rw) : ORIGIN = 0x00208000, LENGTH = 0x00000000
}
/* Section Definitions */
SECTIONS
{
. = 0x00000000;
/* first section is .text which is used for code */
.text 0x00104000: AT ( 0x00000000 ) {
src/start/Cstartup_app.o (.text)
* (.text)
* (.rodata*)
. = ALIGN(4);
} >FLASH
_etext = . ;
PROVIDE (etext = .);
/* 0x00200000 ... */
.data 0x00200028: AT ( ADDR(.text) + SIZEOF(.text) - ADDR(.text) ) {
_data = . ;
* (.data)
. = ALIGN(4);
} >DATA
_edata = . ;
PROVIDE (edata = .);
/* .bss section which is used for uninitialized data */
.bss : {
__bss_start = . ;
__bss_start__ = . ;
*(.bss)
*(COMMON)
} >DATA
. = ALIGN(4);
__bss_end__ = . ;
__bss_end__ = . ;
PROVIDE (main = .);
_end = . ;
. = ALIGN(4);
.int_data : {
*(.internal_ram_top)
} >STACK
PROVIDE (end = .);
/* Stabs debugging sections. */
.stab 0 : { *(.stab) }
.stabstr 0 : { *(.stabstr) }
.stab.excl 0 : { *(.stab.excl) }
.stab.exclstr 0 : { *(.stab.exclstr) }
.stab.index 0 : { *(.stab.index) }
.stab.indexstr 0 : { *(.stab.indexstr) }
.comment 0 : { *(.comment) }
/* DWARF debug sections.
Symbols in the DWARF debugging sections are relative to the beginning
of the section so we begin them at 0. */
/* DWARF 1 */
.debug 0 : { *(.debug) }
.line 0 : { *(.line) }
/* GNU DWARF 1 extensions */
.debug_srcinfo 0 : { *(.debug_srcinfo) }
.debug_sfnames 0 : { *(.debug_sfnames) }
/* DWARF 1.1 and DWARF 2 */
.debug_aranges 0 : { *(.debug_aranges) }
.debug_pubnames 0 : { *(.debug_pubnames) }
/* DWARF 2 */
.debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) }
.debug_abbrev 0 : { *(.debug_abbrev) }
.debug_line 0 : { *(.debug_line) }
.debug_frame 0 : { *(.debug_frame) }
.debug_str 0 : { *(.debug_str) }
.debug_loc 0 : { *(.debug_loc) }
.debug_macinfo 0 : { *(.debug_macinfo) }
/* SGI/MIPS DWARF 2 extensions */
.debug_weaknames 0 : { *(.debug_weaknames) }
.debug_funcnames 0 : { *(.debug_funcnames) }
.debug_typenames 0 : { *(.debug_typenames) }
.debug_varnames 0 : { *(.debug_varnames) }
}

View File

@ -49,7 +49,7 @@ SECTIONS
/* dfu.functab addresses are valid as long as DFU is in flash, i.e.
* only while application calls those functions. Once executing in
* DFU mode, we are re-located to ram */
.dfu.functab 0x00000fd0: AT ( ADDR(.dfu.functab) - ADDR(.text) ) {
.dfu.functab 0x00003fd0: AT ( ADDR(.dfu.functab) - ADDR(.text) ) {
*(.dfu.functab)
. = ALIGN(4096);
} >FLASH

View File

@ -2,8 +2,8 @@
MEMORY
{
FLASH (rx) : ORIGIN = 0x00101000, LENGTH = (0x00040000 - 0x1000)
DATA (rw) : ORIGIN = 0x00200024, LENGTH = (0x00010000 - 0x24)
FLASH (rx) : ORIGIN = 0x00104000, LENGTH = (0x00040000 - 0x4000)
DATA (rw) : ORIGIN = 0x00200028, LENGTH = (0x00010000 - 0x28)
STACK (rw) : ORIGIN = 0x00210000, LENGTH = 0x00000000
}
@ -14,7 +14,7 @@ SECTIONS
{
. = 0x00000000;
/* first section is .text which is used for code */
.text 0x00101000: AT ( 0x00000000 ) {
.text 0x00104000: AT ( 0x00000000 ) {
src/start/Cstartup_app.o (.text)
* (.text)
* (.rodata*)
@ -25,7 +25,7 @@ SECTIONS
PROVIDE (etext = .);
/* 0x00200000 ... */
.data 0x00200024: AT ( ADDR(.text) + SIZEOF(.text) - ADDR(.text) ) {
.data 0x00200028: AT ( ADDR(.text) + SIZEOF(.text) - ADDR(.text) ) {
_data = . ;
* (.data)
. = ALIGN(4);

View File

@ -48,7 +48,7 @@ SECTIONS
/* dfu.functab addresses are valid as long as DFU is in flash, i.e.
* only while application calls those functions. Once executing in
* DFU mode, we are re-located to ram */
.dfu.functab 0x00010fd0: AT ( ADDR(.dfu.functab) - ADDR(.text) ) {
.dfu.functab 0x00003fd0: AT ( ADDR(.dfu.functab) - ADDR(.text) ) {
*(.dfu.functab)
. = ALIGN(4096);
} >FLASH

View File

@ -65,11 +65,8 @@ void AT91F_DBGU_Init(void)
/* open interrupt */
/* FIXME: This should be HIGH_LEVEL, but somehow this triggers an
* interrupt storm. no idea why it's working in 'os' but not in 'dfu'
* */
AT91F_AIC_ConfigureIt(AT91C_BASE_AIC, AT91C_ID_SYS, USART_SYS_LEVEL,
AT91C_AIC_SRCTYPE_INT_POSITIVE_EDGE,
AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL,
DBGU_irq_handler);
AT91F_AIC_EnableIt(AT91C_BASE_AIC, AT91C_ID_SYS);

View File

@ -32,7 +32,9 @@
#include <os/pcd_enumerate.h>
#include "../openpcd.h"
#define SAM7DFU_SIZE 0x1000
#include <compile.h>
#define SAM7DFU_SIZE 0x4000
/* If debug is enabled, we need to access debug functions from flash
* and therefore have to omit flashing */
@ -57,6 +59,12 @@
#define RET_ZLP 1
#define RET_STALL 2
#define led1on() AT91F_PIO_ClearOutput(AT91C_BASE_PIOA, OPENPCD_PIO_LED1)
#define led1off() AT91F_PIO_SetOutput(AT91C_BASE_PIOA, OPENPCD_PIO_LED1)
#define led2on() AT91F_PIO_ClearOutput(AT91C_BASE_PIOA, OPENPCD_PIO_LED2)
#define led2off() AT91F_PIO_SetOutput(AT91C_BASE_PIOA, OPENPCD_PIO_LED2)
static void __dfufunc udp_init(void)
{
/* Set the PLL USB Divider */
@ -185,8 +193,8 @@ static void __dfufunc udp_ep0_send_stall(void)
}
static u_int8_t status;
static u_int8_t *ptr = (u_int8_t *) AT91C_IFLASH + SAM7DFU_SIZE;
static __dfudata u_int8_t dfu_status;
static __dfudata u_int32_t dfu_state = DFU_STATE_appIDLE;
static u_int32_t pagebuf32[AT91C_IFLASH_PAGE_SIZE/4];
@ -203,14 +211,14 @@ static int __dfufunc handle_dnload(u_int16_t val, u_int16_t len)
* DFU protocol violation */
DEBUGP("length exceeds flash page size ");
dfu_state = DFU_STATE_dfuERROR;
status = DFU_STATUS_errADDRESS;
dfu_status = DFU_STATUS_errADDRESS;
return RET_STALL;
}
if (len & 0x3) {
/* reject non-four-byte-aligned writes */
DEBUGP("not four-byte-aligned length ");
dfu_state = DFU_STATE_dfuERROR;
status = DFU_STATUS_errADDRESS;
dfu_status = DFU_STATUS_errADDRESS;
return RET_STALL;
}
if (len == 0) {
@ -222,7 +230,7 @@ static int __dfufunc handle_dnload(u_int16_t val, u_int16_t len)
if (ptr + len > (u_int8_t *) AT91C_IFLASH + AT91C_IFLASH_SIZE) {
DEBUGP("end of write exceeds flash end ");
dfu_state = DFU_STATE_dfuERROR;
status = DFU_STATUS_errADDRESS;
dfu_status = DFU_STATUS_errADDRESS;
return RET_STALL;
}
@ -256,7 +264,7 @@ static __dfufunc int handle_upload(u_int16_t val, u_int16_t len)
if (len > AT91C_IFLASH_PAGE_SIZE) {
/* Too big */
dfu_state = DFU_STATE_dfuERROR;
status = DFU_STATUS_errADDRESS;
dfu_status = DFU_STATUS_errADDRESS;
udp_ep0_send_stall();
return -EINVAL;
}
@ -282,11 +290,11 @@ static __dfufunc void handle_getstatus(void)
case DFU_STATE_dfuDNBUSY:
if (fsr & AT91C_MC_PROGE) {
DEBUGE("errPROG ");
status = DFU_STATUS_errPROG;
dfu_status = DFU_STATUS_errPROG;
dfu_state = DFU_STATE_dfuERROR;
} else if (fsr & AT91C_MC_LOCKE) {
DEBUGE("errWRITE ");
status = DFU_STATUS_errWRITE;
dfu_status = DFU_STATUS_errWRITE;
dfu_state = DFU_STATE_dfuERROR;
} else if (fsr & AT91C_MC_FRDY) {
DEBUGE("DNLOAD_IDLE ");
@ -302,7 +310,7 @@ static __dfufunc void handle_getstatus(void)
}
/* send status response */
dstat.bStatus = status;
dstat.bStatus = dfu_status;
dstat.bState = dfu_state;
dstat.iString = 0;
/* FIXME: set dstat.bwPollTimeout */
@ -328,12 +336,21 @@ int __dfufunc dfu_ep0_handler(u_int8_t req_type, u_int8_t req,
switch (dfu_state) {
case DFU_STATE_appIDLE:
if (req != USB_REQ_DFU_DETACH) {
ret = RET_STALL;
switch (req) {
case USB_REQ_DFU_GETSTATUS:
handle_getstatus();
break;
case USB_REQ_DFU_GETSTATE:
handle_getstate();
break;
case USB_REQ_DFU_DETACH:
dfu_state = DFU_STATE_appDETACH;
ret = RET_ZLP;
goto out;
break;
default:
ret = RET_STALL;
}
dfu_state = DFU_STATE_appDETACH;
ret = RET_ZLP;
break;
case DFU_STATE_appDETACH:
switch (req) {
@ -491,7 +508,7 @@ int __dfufunc dfu_ep0_handler(u_int8_t req_type, u_int8_t req,
break;
case USB_REQ_DFU_CLRSTATUS:
dfu_state = DFU_STATE_dfuIDLE;
status = DFU_STATUS_OK;
dfu_status = DFU_STATUS_OK;
/* no zlp? */
ret = RET_ZLP;
break;
@ -768,8 +785,10 @@ static __dfufunc void dfu_udp_irq(void)
{
AT91PS_UDP pUDP = AT91C_BASE_UDP;
AT91_REG isr = pUDP->UDP_ISR;
led1on();
if (isr & AT91C_UDP_ENDBUSRES) {
led2on();
pUDP->UDP_IER = AT91C_UDP_EPINT0;
/* reset all endpoints */
pUDP->UDP_RSTEP = (unsigned int)-1;
@ -788,6 +807,9 @@ static __dfufunc void dfu_udp_irq(void)
pUDP->UDP_ICR = isr;
AT91F_AIC_ClearIt(AT91C_BASE_AIC, AT91C_ID_UDP);
{ volatile int i; for (i=0; i< 0x3ff; i++) ; }
led1off();
}
/* this is only called once before DFU mode, no __dfufunc required */
@ -795,17 +817,35 @@ static void dfu_switch(void)
{
AT91PS_AIC pAic = AT91C_BASE_AIC;
DEBUGE("Switching to DFU mode ");
AT91F_PIO_CfgOutput(AT91C_BASE_PIOA, OPENPCD_PIO_LED1);
AT91F_PIO_CfgOutput(AT91C_BASE_PIOA, OPENPCD_PIO_LED2);
led1off();
led2off();
flash_init();
/* disable all non-usb (and non-dbgu) interrupts */
pAic->AIC_IDCR = ~((1 << AT91C_ID_UDP)|(1 << AT91C_ID_SYS));
pAic->AIC_SVR[AT91C_ID_UDP] = (unsigned int) &dfu_udp_irq;
dfu_state = DFU_STATE_dfuIDLE;
dfu_status = DFU_STATUS_OK;
}
void __dfufunc dfu_main(void)
{
AT91F_PIO_CfgOutput(AT91C_BASE_PIOA, OPENPCD_PIO_LED1);
AT91F_PIO_CfgOutput(AT91C_BASE_PIOA, OPENPCD_PIO_LED2);
led1off();
led2off();
AT91F_DBGU_Init();
DEBUGE("sam7dfu startup\r\n");
AT91F_DBGU_Printk("\n\r");
AT91F_DBGU_Printk(COMPILE_DATE " " COMPILE_BY " " COMPILE_SVNREV);
AT91F_DBGU_Printk("\n\r");
udp_init();
dfu_state = DFU_STATE_dfuIDLE;

View File

@ -55,7 +55,7 @@
#define __dfufunc
#define __dfustruct const
#define DFU_API_LOCATION ((const struct dfuapi *) 0x00100fd0)
#define DFU_API_LOCATION ((const struct dfuapi *) 0x00103fd0)
struct _dfu_desc {
struct usb_config_descriptor ucfg;

View File

@ -65,7 +65,6 @@ void flash_init(void)
{
unsigned int fmcn = AT91F_MC_EFC_ComputeFMCN(MCK);
AT91F_MC_EFC_CfgModeReg(AT91C_BASE_MC, fmcn << 16 | AT91C_MC_FWS_3FWS |
AT91C_MC_FRDY | AT91C_MC_LOCKE |
AT91C_MC_PROGE);
AT91F_MC_EFC_CfgModeReg(AT91C_BASE_MC, (fmcn&0xff) << 16 |
AT91C_MC_FWS_3FWS);
}