- implement some more missing DFU bits
- add debugging support to DFU - introduce a auto-generated compile.h to add reviison number/... to firmware git-svn-id: https://svn.openpcd.org:2342/trunk@201 6dc7ffe9-61d6-0310-9af1-9938baff3ed1
This commit is contained in:
parent
3124bf3b44
commit
569d11d8a5
|
@ -563,6 +563,9 @@ clean_list :
|
|||
$(REMOVE) $(CPPSRCARM:.cpp=.d)
|
||||
$(REMOVE) .dep/*
|
||||
|
||||
.PHONY: include/compile.h
|
||||
include/compile.h:
|
||||
scripts/mkcompile_h > $@
|
||||
|
||||
# Include the dependency files.
|
||||
-include $(shell mkdir .dep 2>/dev/null) $(wildcard .dep/*)
|
||||
|
|
|
@ -76,7 +76,7 @@ SRC =
|
|||
# List C source files here which must be compiled in ARM-Mode.
|
||||
# use file-extension c for "c-only"-files
|
||||
|
||||
SRCARM = src/start/Cstartup_SAM7.c src/dfu/dfu.c
|
||||
SRCARM = src/start/Cstartup_SAM7.c src/dfu/dfu.c src/dfu/dbgu.c
|
||||
|
||||
# List C++ source files here.
|
||||
# use file-extension cpp for C++-files (use extension .cpp)
|
||||
|
@ -99,6 +99,11 @@ ASRC =
|
|||
# List Assembler source files here which must be assembled in ARM-Mode..
|
||||
ASRCARM = src/start/Cstartup.S
|
||||
|
||||
ifeq ($(DEBUG),1)
|
||||
SRCARM += lib/lib_AT91SAM7.c lib/vsprintf.c lib/ctype.c lib/string.c
|
||||
ASRCARM += lib/div64.S
|
||||
endif
|
||||
|
||||
## Output format. (can be ihex or binary)
|
||||
## (binary i.e. for openocd and SAM-BA, hex i.e. for lpc21isp and uVision)
|
||||
#FORMAT = ihex
|
||||
|
@ -526,6 +531,9 @@ clean_list :
|
|||
$(REMOVE) $(CPPSRCARM:.cpp=.d)
|
||||
$(REMOVE) .dep/*
|
||||
|
||||
.PHONY: include/compile.h
|
||||
include/compile.h:
|
||||
scripts/mkcompile_h > $@
|
||||
|
||||
# Include the dependency files.
|
||||
-include $(shell mkdir .dep 2>/dev/null) $(wildcard .dep/*)
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
#!/bin/sh
|
||||
|
||||
MAX_LEN=32
|
||||
TRUNCATE="sed -e s/\(.\{1,$MAX_LEN\}\).*/\1/"
|
||||
|
||||
DATE=`LC_ALL=C LANG=C date +%Y%m%d-%H%M%S`
|
||||
BY=`whoami`
|
||||
HOST=`hostname | $TRUNCATE`
|
||||
BYHOST=`echo ${BY}@${HOST} | $TRUNCATE`
|
||||
SVNREV=`svn info | grep \^Revision: | cut -c 11-`
|
||||
|
||||
svn st | grep \^M >/dev/null
|
||||
|
||||
[ "$?" -eq "0" ] && SVNREV=${SVNREV}-unclean
|
||||
|
||||
echo "#ifndef _COMPILE_H"
|
||||
echo "#define _COMPILE_H"
|
||||
echo
|
||||
echo /\* This file is auto generated \*/
|
||||
echo \#define COMPILE_DATE \"${DATE}\"
|
||||
echo \#define COMPILE_BY \"${BYHOST}\"
|
||||
echo \#define COMPILE_SVNREV \"${SVNREV}\"
|
||||
echo
|
||||
echo "#endif /* _COMPILE_H */"
|
|
@ -23,24 +23,29 @@
|
|||
#include <errno.h>
|
||||
#include <usb_ch9.h>
|
||||
#include <usb_dfu.h>
|
||||
#include <board.h>
|
||||
#include <lib_AT91SAM7.h>
|
||||
|
||||
#include <dfu/dfu.h>
|
||||
#include <dfu/dbgu.h>
|
||||
#include <os/pcd_enumerate.h>
|
||||
#include "../openpcd.h"
|
||||
|
||||
/* If debug is enabled, we need to access debug functions from flash
|
||||
* and therefore have to omit flashing */
|
||||
//#define DEBUG_DFU
|
||||
#define DEBUG_DFU
|
||||
|
||||
#ifdef DEBUG_DFU
|
||||
#define DEBUGE DEBUGP
|
||||
#define DEBUGI DEBUGP
|
||||
#else
|
||||
#define DEBUGE(x, args ...) do { } while (0)
|
||||
#define DEBUGI(x, args ...) do { } while (0)
|
||||
#endif
|
||||
|
||||
static 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);
|
||||
|
||||
}
|
||||
|
||||
static void __dfufunc udp_init(void)
|
||||
{
|
||||
|
@ -97,6 +102,32 @@ static void __dfufunc udp_ep0_send_data(const char *pData, u_int32_t length)
|
|||
}
|
||||
}
|
||||
|
||||
/* receive data from EP0 */
|
||||
static int __dfufunc udp_ep0_recv_data(char *data, u_int32_t len)
|
||||
{
|
||||
AT91PS_UDP pUdp = AT91C_BASE_UDP;
|
||||
u_int16_t i, num_rcv;
|
||||
u_int32_t num_rcv_total = 0;
|
||||
|
||||
do {
|
||||
/* FIXME: do we need to check whether we've been interrupted
|
||||
* by a RX SETUP stage? */
|
||||
while (!(pUdp->UDP_CSR[0] & AT91C_UDP_RX_DATA_BK0)) ;
|
||||
|
||||
num_rcv = pUdp->UDP_CSR[0] >> 16;
|
||||
for (i = 0; i < num_rcv; i++)
|
||||
*data++ = pUdp->UDP_FDR[0];
|
||||
pUdp->UDP_CSR[0] &= ~(AT91C_UDP_RX_DATA_BK0);
|
||||
|
||||
num_rcv_total += num_rcv;
|
||||
|
||||
/* we need to continue to pull data until we either receive
|
||||
* a packet < endpoint size or == 0 */
|
||||
} while (num_rcv == 8);
|
||||
|
||||
return num_rcv_total;
|
||||
}
|
||||
|
||||
/* Send zero length packet through the control endpoint */
|
||||
static void __dfufunc udp_ep0_send_zlp(void)
|
||||
{
|
||||
|
@ -119,12 +150,31 @@ static void __dfufunc udp_ep0_send_stall(void)
|
|||
|
||||
|
||||
static u_int8_t status;
|
||||
static u_int8_t *ptr;
|
||||
static u_int8_t *ptr = (u_int8_t *)0x00101000;
|
||||
static __dfudata u_int32_t dfu_state;
|
||||
static u_int8_t pagebuf[AT91C_IFLASH_PAGE_SIZE];
|
||||
|
||||
static u_int16_t page_from_ramaddr(const void *addr)
|
||||
{
|
||||
u_int32_t ramaddr = (u_int32_t) ptr;
|
||||
ramaddr -= (u_int32_t) AT91C_IFLASH;
|
||||
return (ramaddr >> AT91C_IFLASH_PAGE_SHIFT);
|
||||
}
|
||||
#define PAGES_PER_LOCKREGION (AT91C_IFLASH_LOCK_REGION_SIZE>>AT91C_IFLASH_PAGE_SHIFT)
|
||||
#define IS_FIRST_PAGE_OF_LOCKREGION(x) ((x % PAGES_PER_LOCKREGION) == 0)
|
||||
#define LOCKREGION_FROM_PAGE(x) (x / PAGES_PER_LOCKREGION)
|
||||
|
||||
static int is_page_locked(u_int16_t page)
|
||||
{
|
||||
u_int16_t lockregion = LOCKREGION_FROM_PAGE(page);
|
||||
|
||||
return (AT91C_BASE_MC->MC_FSR & (lockregion << 16));
|
||||
}
|
||||
|
||||
static int __dfufunc handle_dnload(u_int16_t val, u_int16_t len)
|
||||
{
|
||||
volatile u_int32_t *p = (volatile u_int32_t *)ptr;
|
||||
u_int16_t page = page_from_ramaddr(ptr);
|
||||
|
||||
DEBUGE("download ");
|
||||
|
||||
|
@ -136,6 +186,7 @@ static int __dfufunc handle_dnload(u_int16_t val, u_int16_t len)
|
|||
return -EINVAL;
|
||||
}
|
||||
if (len & 0x3) {
|
||||
/* reject non-four-byte-aligned writes */
|
||||
dfu_state = DFU_STATE_dfuERROR;
|
||||
status = DFU_STATUS_errADDRESS;
|
||||
udp_ep0_send_stall();
|
||||
|
@ -145,14 +196,27 @@ static int __dfufunc handle_dnload(u_int16_t val, u_int16_t len)
|
|||
dfu_state = DFU_STATE_dfuMANIFEST_SYNC;
|
||||
return 0;
|
||||
}
|
||||
|
||||
udp_ep0_recv_data(pagebuf, sizeof(pagebuf));
|
||||
|
||||
DEBUGP(hexdump(pagebuf, len));
|
||||
|
||||
/* we can only access the write buffer with correctly aligned
|
||||
* 32bit writes ! */
|
||||
#if 0
|
||||
for (i = 0; i < len/4; i++)
|
||||
p[i] =
|
||||
#endif
|
||||
|
||||
/* FIXME: get data packet from FIFO, (erase+)write flash */
|
||||
#ifndef DEBUG_DFU
|
||||
|
||||
/* unlock, (erase+)write flash */
|
||||
#ifndef DEBUG_DFU
|
||||
if (is_page_locked(page))
|
||||
AT91F_MC_EFC_PerformCmd(AT91C_BASE_MC, AT91C_MC_FCMD_UNLOCK |
|
||||
AT91C_MC_CORRECT_KEY | page);
|
||||
|
||||
AT91F_MC_EFC_PerformCmd(AT91C_BASE_MC, AT91C_MC_FCMD_START_PROG |
|
||||
AT91C_MC_CORRECT_KEY | page);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
|
@ -182,13 +246,34 @@ static __dfufunc int handle_upload(u_int16_t val, u_int16_t len)
|
|||
static __dfufunc void handle_getstatus(void)
|
||||
{
|
||||
struct dfu_status dstat;
|
||||
u_int32_t fsr = AT91F_MC_EFC_GetStatus(AT91C_BASE_MC);
|
||||
|
||||
DEBUGE("getstatus ");
|
||||
|
||||
switch (dfu_state) {
|
||||
case DFU_STATE_dfuDNLOAD_SYNC:
|
||||
case DFU_STATE_dfuDNBUSY:
|
||||
if (fsr & AT91C_MC_PROGE) {
|
||||
status = DFU_STATUS_errPROG;
|
||||
dfu_state = DFU_STATE_dfuERROR;
|
||||
} else if (fsr & AT91C_MC_LOCKE) {
|
||||
status = DFU_STATUS_errWRITE;
|
||||
dfu_state = DFU_STATE_dfuERROR;
|
||||
} else if (fsr & AT91C_MC_FRDY)
|
||||
dfu_state = DFU_STATE_dfuDNLOAD_IDLE;
|
||||
else
|
||||
dfu_state = DFU_STATE_dfuDNBUSY;
|
||||
break;
|
||||
case DFU_STATE_dfuMANIFEST_SYNC:
|
||||
dfu_state = DFU_STATE_dfuMANIFEST;
|
||||
break;
|
||||
}
|
||||
|
||||
/* send status response */
|
||||
dstat.bStatus = status;
|
||||
dstat.bState = dfu_state;
|
||||
dstat.iString = 0;
|
||||
|
||||
udp_ep0_send_data((char *)&dstat, sizeof(dstat));
|
||||
}
|
||||
|
||||
|
@ -196,6 +281,7 @@ static void __dfufunc handle_getstate(void)
|
|||
{
|
||||
u_int8_t u8 = dfu_state;
|
||||
DEBUGE("getstate ");
|
||||
|
||||
udp_ep0_send_data((char *)&u8, sizeof(u8));
|
||||
}
|
||||
|
||||
|
@ -237,6 +323,7 @@ int __dfufunc dfu_ep0_handler(u_int8_t req_type, u_int8_t req,
|
|||
goto send_stall;
|
||||
}
|
||||
handle_dnload(val, len);
|
||||
dfu_state = DFU_STATE_dfuDNLOAD_SYNC;
|
||||
break;
|
||||
case USB_REQ_DFU_UPLOAD:
|
||||
ptr = 0x00101000; /* Flash base address for app */
|
||||
|
@ -280,8 +367,7 @@ int __dfufunc dfu_ep0_handler(u_int8_t req_type, u_int8_t req,
|
|||
case DFU_STATE_dfuDNLOAD_IDLE:
|
||||
switch (req) {
|
||||
case USB_REQ_DFU_DNLOAD:
|
||||
if (handle_dnload(val, len))
|
||||
/* FIXME: state transition */
|
||||
handle_dnload(val, len);
|
||||
break;
|
||||
case USB_REQ_DFU_ABORT:
|
||||
dfu_state = DFU_STATE_dfuIDLE;
|
||||
|
@ -302,6 +388,7 @@ int __dfufunc dfu_ep0_handler(u_int8_t req_type, u_int8_t req,
|
|||
case DFU_STATE_dfuMANIFEST_SYNC:
|
||||
switch (req) {
|
||||
case USB_REQ_DFU_GETSTATUS:
|
||||
handle_getstatus();
|
||||
break;
|
||||
case USB_REQ_DFU_GETSTATE:
|
||||
handle_getstate();
|
||||
|
@ -516,6 +603,11 @@ static __dfufunc void dfu_udp_ep0_handler(void)
|
|||
MIN(sizeof(dfu_if_descriptor),
|
||||
wLength));
|
||||
#endif
|
||||
} else if (wValue == 0x2100) {
|
||||
/* Return Function descriptor */
|
||||
udp_ep0_send_data((const char *) &dfu_cfg_descriptor.func_dfu,
|
||||
MIN(sizeof(dfu_cfg_descriptor.func_dfu),
|
||||
wLength));
|
||||
} else
|
||||
udp_ep0_send_stall();
|
||||
break;
|
||||
|
@ -654,6 +746,8 @@ static void dfu_switch(void)
|
|||
|
||||
void __dfufunc dfu_main(void)
|
||||
{
|
||||
AT91F_DBGU_Init();
|
||||
|
||||
udp_init();
|
||||
|
||||
/* This implements
|
||||
|
@ -675,6 +769,8 @@ void __dfufunc dfu_main(void)
|
|||
/* Clear for set the Pull up resistor */
|
||||
AT91F_PIO_SetOutput(AT91C_BASE_PIOA, OPENPCD_PIO_UDP_PUP);
|
||||
|
||||
flash_init();
|
||||
|
||||
/* do nothing, since all of DFU is interrupt driven */
|
||||
while (1) ;
|
||||
}
|
||||
|
|
|
@ -54,19 +54,8 @@
|
|||
#define __dfudata __attribute__ ((section (".data.shared")))
|
||||
#define __dfufunc
|
||||
#define __dfustruct const
|
||||
|
||||
#if 0
|
||||
extern void __dfufunc udp_ep0_send_data(const char *data, u_int32_t length);
|
||||
extern void __dfufunc udp_ep0_send_zlp(void);
|
||||
extern void __dfufunc udp_ep0_send_stall(void);
|
||||
extern __dfustruct struct usb_device_descriptor dfu_dev_descriptor;
|
||||
extern __dfustruct struct _dfu_desc dfu_cfg_descriptor;
|
||||
extern void dfu_switch(void);
|
||||
extern int __dfufunc dfu_ep0_handler(u_int8_t req_type, u_int8_t req,
|
||||
u_int16_t val, u_int16_t len);
|
||||
extern static u_int8_t dfu_state;
|
||||
struct udp_pcd;
|
||||
#endif
|
||||
|
||||
#define DFU_API_LOCATION ((const struct dfuapi *) 0x00100fd0)
|
||||
|
||||
struct _dfu_desc {
|
||||
struct usb_config_descriptor ucfg;
|
||||
|
|
|
@ -32,14 +32,4 @@ int flash_sector(unsigned int sector, const u_int8_t *data, unsigned int len)
|
|||
}
|
||||
|
||||
|
||||
void flash_init(void)
|
||||
{
|
||||
unsigned int fmcn = AT91F_MC_EFC_ComputerFMCN(48000000);
|
||||
|
||||
AT91F_MC_EFC_CfgModeReg(ff, fmcn << 16 | AT91C_MC_FWS_3FWS |
|
||||
AT91C_MC_FRDY | AT91C_MC_LOCKE |
|
||||
AT91C_MC_PROGE);
|
||||
|
||||
AT91F_AIC_EnableIt();
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue