working version

This commit is contained in:
Olaf Rempel 2008-03-03 22:32:38 +01:00
parent fded24a803
commit bd59d4924f
5 changed files with 155 additions and 34 deletions

View File

@ -18,6 +18,7 @@
***************************************************************************/ ***************************************************************************/
#include <stdint.h> #include <stdint.h>
#include "AT91SAM7S256.h" #include "AT91SAM7S256.h"
#include "board.h"
static void empty_isr(void) {} static void empty_isr(void) {}
@ -36,7 +37,7 @@ void at91_init1(void)
*AT91C_RSTC_RMR = (AT91C_RSTC_KEY & 0xA5 << 24) | AT91C_RSTC_URSTEN; *AT91C_RSTC_RMR = (AT91C_RSTC_KEY & 0xA5 << 24) | AT91C_RSTC_URSTEN;
/* Set Flash Waitstates */ /* Set Flash Waitstates */
*AT91C_MC_FMR = AT91C_MC_FWS_1FWS; *AT91C_MC_FMR = (AT91C_MC_FMCN & ((MCK / 666666) << 16)) | AT91C_MC_FWS_1FWS;
/* /*
* Enable main oscillator (MAINCK) * Enable main oscillator (MAINCK)

View File

@ -1,7 +1,7 @@
#ifndef AT91TWI_H_ #ifndef AT91TWI_H_
#define AT91TWI_H_ #define AT91TWI_H_
#include <list.h> #include <stdint.h>
/* TWI slave addresses */ /* TWI slave addresses */
#define TWI_ADDR_BL1 0x21 #define TWI_ADDR_BL1 0x21
@ -33,7 +33,7 @@
struct blmc_cmd { struct blmc_cmd {
uint32_t cmd; /* cmd byte(s) */ uint32_t cmd; /* cmd byte(s) */
uint8_t mode; /* read/write, cmdlen (1-3 bytes) */ uint8_t mode; /* read/write, cmdlen (1-3 bytes) */
uint8_t size; /* data size */ uint16_t size; /* data size */
uint8_t *data; /* read/write data */ uint8_t *data; /* read/write data */
}; };

View File

@ -210,8 +210,8 @@ void at91_twi_test(void)
cmd.cmd = CMD_GET_SIGNATURE; cmd.cmd = CMD_GET_SIGNATURE;
cmd.size = 4; cmd.size = 4;
ret = twi_cmd(i, &cmd); ret = twi_cmd(i, &cmd);
printf("sig(%ld):0x%02x%02x%02x ", ret, buf[0], buf[1], buf[2]); printf("sig(%ld):0x%02x%02x%02x\n\r", ret, buf[0], buf[1], buf[2]);
/*
cmd.cmd = CMD_BOOT_APPLICATION; cmd.cmd = CMD_BOOT_APPLICATION;
cmd.mode = BLMC_CMD_WRITE | BLMC_CMD_0_ARG; cmd.mode = BLMC_CMD_WRITE | BLMC_CMD_0_ARG;
cmd.size = 0; cmd.size = 0;
@ -225,6 +225,7 @@ void at91_twi_test(void)
cmd.data = buf, cmd.data = buf,
ret = twi_cmd(i, &cmd); ret = twi_cmd(i, &cmd);
printf("app(%ld):'%s'\n\r", ret, buf); printf("app(%ld):'%s'\n\r", ret, buf);
*/
} }
} }

View File

@ -182,13 +182,12 @@ static const struct usb_string_descriptor usb_string1 = {
}; };
static const struct usb_string_descriptor usb_string2 = { static const struct usb_string_descriptor usb_string2 = {
/* String 2 "device firmware upgrade" */ /* String 2 "sam7fc-dfu" */
.bLength = sizeof(struct usb_string_descriptor) + 23 * sizeof(uint16_t), .bLength = sizeof(struct usb_string_descriptor) + 10 * sizeof(uint16_t),
.bDescriptorType = USB_DT_STRING, .bDescriptorType = USB_DT_STRING,
.wData = { .wData = {
0x0064, 0x0065, 0x0076, 0x0069, 0x0063, 0x0065, 0x0020, 0x0066, 0x0073, 0x0061, 0x006d, 0x0037, 0x0066, 0x0063, 0x002d, 0x0064,
0x0069, 0x0072, 0x006d, 0x0077, 0x0061, 0x0072, 0x0065, 0x0020, 0x0066, 0x0075,
0x0075, 0x0070, 0x0067, 0x0072, 0x0061, 0x0064, 0x0065,
}, },
}; };
@ -262,7 +261,7 @@ void ep_transfer_send(uint32_t ep, char *data, uint32_t length,
void (*complete_cb)(void)) void (*complete_cb)(void))
{ {
struct ep_ctx *ctx = &ep_ctx[ep]; struct ep_ctx *ctx = &ep_ctx[ep];
// printf("ep_transfer_send(%ld) size=%ld flags=0x%x\n\r", ep, length, ctx->flags); // printf("ep_transfer_send(%ld) size=%ld(%d) flags=0x%x\n\r", ep, length, ctx->maxpktsize, ctx->flags);
if (!(ctx->flags & CTX_TRANSFER) || (ctx->flags & (CTX_IN | CTX_OUT))) if (!(ctx->flags & CTX_TRANSFER) || (ctx->flags & (CTX_IN | CTX_OUT)))
return; return;
@ -448,6 +447,10 @@ static void udp_handle_ep(uint32_t ep)
if (!(*csr & AT91C_UDP_EPEDS)) if (!(*csr & AT91C_UDP_EPEDS))
return; return;
/* clear STALLSENT interrupt */
if (*csr & AT91C_UDP_STALLSENT)
csr_clear_flags(*csr, (AT91C_UDP_STALLSENT | AT91C_UDP_FORCESTALL));
/* ctrl request packet? */ /* ctrl request packet? */
if (*csr & AT91C_UDP_RXSETUP) { if (*csr & AT91C_UDP_RXSETUP) {
struct usb_ctrlrequest req; struct usb_ctrlrequest req;
@ -455,6 +458,10 @@ static void udp_handle_ep(uint32_t ep)
for (p = (uint8_t *)&req; p < (uint8_t *)(&req +1); p++) for (p = (uint8_t *)&req; p < (uint8_t *)(&req +1); p++)
*p = AT91C_UDP_FDR[ep]; *p = AT91C_UDP_FDR[ep];
/* ack bank0 *now */
if (*csr & AT91C_UDP_RX_DATA_BK0)
csr_clear_flags(*csr, AT91C_UDP_RX_DATA_BK0);
/* set data phase transfer direction */ /* set data phase transfer direction */
if (req.bRequestType & USB_DIR_IN) if (req.bRequestType & USB_DIR_IN)
*csr |= AT91C_UDP_DIR; *csr |= AT91C_UDP_DIR;
@ -500,10 +507,6 @@ static void udp_handle_ep(uint32_t ep)
*csr &= ~(AT91C_UDP_TXCOMP); *csr &= ~(AT91C_UDP_TXCOMP);
} }
/* clear STALLSENT interrupt */
if (*csr & AT91C_UDP_STALLSENT)
csr_clear_flags(*csr, (AT91C_UDP_STALLSENT | AT91C_UDP_FORCESTALL));
/* data ready to read? */ /* data ready to read? */
if (*csr & (AT91C_UDP_RX_DATA_BK0 | AT91C_UDP_RX_DATA_BK1)) { if (*csr & (AT91C_UDP_RX_DATA_BK0 | AT91C_UDP_RX_DATA_BK1)) {
struct ep_ctx *ctx = &ep_ctx[ep]; struct ep_ctx *ctx = &ep_ctx[ep];
@ -517,6 +520,8 @@ static void udp_handle_ep(uint32_t ep)
ctx->transfer->curpos = 0; ctx->transfer->curpos = 0;
} }
void *exec_cb = NULL;
if (ctx->flags & CTX_FIFO) { if (ctx->flags & CTX_FIFO) {
fifo_rxudp(ctx->fifo, ep, len); fifo_rxudp(ctx->fifo, ep, len);
@ -534,8 +539,8 @@ static void udp_handle_ep(uint32_t ep)
if (transfer->length == transfer->curpos) { if (transfer->length == transfer->curpos) {
ctx->flags &= ~CTX_OUT; ctx->flags &= ~CTX_OUT;
if (transfer->complete_cb) /* exec callback after rxbank ack */
transfer->complete_cb(); exec_cb = transfer->complete_cb;
} }
} }
@ -553,6 +558,9 @@ static void udp_handle_ep(uint32_t ep)
ctx->flags = (ctx->flags & ~CTX_RXBANK1) | CTX_RXBANK0; ctx->flags = (ctx->flags & ~CTX_RXBANK1) | CTX_RXBANK0;
} }
if (exec_cb)
ctx->transfer->complete_cb();
} }
} }

143
src/dfu.c
View File

@ -20,6 +20,7 @@
#include "AT91SAM7S256.h" #include "AT91SAM7S256.h"
#include "board.h" #include "board.h"
#include "at91_twi.h"
#include "at91_udp.h" #include "at91_udp.h"
#include "usb_ch9.h" #include "usb_ch9.h"
@ -36,7 +37,7 @@ static void handle_getstatus(void)
{ {
struct dfu_status dstat; struct dfu_status dstat;
uint32_t fmr = *AT91C_MC_FMR; uint32_t fmr = *AT91C_MC_FSR;
switch (dfu_state) { switch (dfu_state) {
case DFU_STATE_dfuDNLOAD_SYNC: case DFU_STATE_dfuDNLOAD_SYNC:
@ -53,8 +54,7 @@ static void handle_getstatus(void)
dfu_state = DFU_STATE_dfuDNLOAD_IDLE; dfu_state = DFU_STATE_dfuDNLOAD_IDLE;
} else { } else {
// dfu_state = DFU_STATE_dfuDNBUSY; dfu_state = DFU_STATE_dfuDNBUSY;
dfu_state = DFU_STATE_dfuDNLOAD_IDLE;
} }
break; break;
} }
@ -73,36 +73,149 @@ static void handle_getstate(void)
ep_transfer_send(0, (char *)&dfu_state, sizeof(dfu_state), NULL); ep_transfer_send(0, (char *)&dfu_state, sizeof(dfu_state), NULL);
} }
static uint8_t buf[256]; static uint16_t prog_iface;
static uint16_t prog_block;
static uint16_t prog_length;
static uint32_t prog_buf[AT91C_IFLASH_PAGE_SIZE /4];
static void handle_dnload_cb(void) static void handle_dnload_flash(void)
{ {
uint32_t *ptr = (uint32_t *)((uint8_t *)0x100000 + (prog_block * 0x100));
uint32_t i;
prog_length += 3;
for (i = 0; i < prog_length /4; i++)
*ptr++ = prog_buf[i];
if (!(*AT91C_MC_FSR & AT91C_MC_FRDY)) {
printf("flash not ready!\n\r");
return;
}
*AT91C_MC_FCR = (AT91C_MC_KEY & (0x5A << 24)) |
(((uint32_t)ptr - 0x100004) & AT91C_MC_PAGEN) |
AT91C_MC_FCMD_START_PROG;
ep_transfer_send(0, NULL, 0, NULL); ep_transfer_send(0, NULL, 0, NULL);
} }
static uint32_t handle_dnload(uint16_t index, uint16_t value, uint16_t length) static void handle_dnload_eeprom(void)
{ {
printf("down:%x-%x-%x\n\r", index, value, length); /*
* TODO: write buf to onboard eeprom @ address
* inc. address
*/
ep_transfer_send(0, NULL, 0, NULL);
}
static void handle_dnload_blctrl(void)
{
/*
* TODO: write buf to blctrl#iface @ address
* inc. address
*/
ep_transfer_send(0, NULL, 0, NULL);
}
static uint32_t handle_dnload(uint16_t iface, uint16_t block, uint16_t length)
{
printf("down:%x-%x-%x\n\r", iface, block, length);
if (length == 0) { if (length == 0) {
dfu_state = DFU_STATE_dfuMANIFEST_SYNC; dfu_state = DFU_STATE_dfuMANIFEST_SYNC;
return RET_ZLP; return RET_ZLP;
} }
ep_transfer_receive(0, (char *)&buf, length, handle_dnload_cb); prog_iface = iface;
prog_block = block;
prog_length = length;
void *callback = NULL;
switch (iface) {
case 0: /* internal flash */
if (block >= 0x3C0) {
dfu_state = DFU_STATE_dfuERROR;
dfu_status = DFU_STATUS_errADDRESS;
return RET_STALL;
}
callback = handle_dnload_flash;
break;
case 1: /* onboard i2c-eeprom */
callback = handle_dnload_eeprom;
break;
case 2:
case 3:
case 4:
case 5: /* blctrl 1-4 */
callback = handle_dnload_blctrl;
break;
}
ep_transfer_receive(0, (char *)&prog_buf, length, callback);
return RET_NOTHING; return RET_NOTHING;
} }
static uint32_t handle_upload(uint16_t index, uint16_t value, uint16_t length) static void handle_upload(uint16_t iface, uint16_t block, uint16_t length)
{ {
printf("up:%x-%x-%x\n\r", index, value, length); printf("up:%x-%x-%x\n\r", iface, block, length);
return 0;
char *ptr = (char *)&prog_buf;
switch (iface) {
case 0: /* internal flash */
if (block >= 0x400) {
length = 0;
break;
}
ptr = (char *)0x100000 + (block * 0x100);
break;
case 1: /* onboard i2c-eeprom */
if (block >= 0x80) {
length = 0;
break;
}
/* TODO */
break;
case 2:
case 3:
case 4:
case 5: /* blctrl 1-4 */
if (block >= 0x20) {
length = 0;
dfu_state = DFU_STATE_dfuIDLE;
break;
}
uint32_t i2c_dev = TWI_ADDR_BL1 + (iface -2);
struct blmc_cmd cmd = {
.cmd = (CMD_READ_FLASH << 16) | (block * 0x100),
.mode = BLMC_CMD_READ | BLMC_CMD_2_ARG,
.size = length,
.data = (uint8_t *)&prog_buf,
};
if (twi_cmd(i2c_dev, &cmd) != 0) {
length = 0;
dfu_state = DFU_STATE_dfuERROR;
dfu_status = DFU_STATUS_errUNKNOWN;
}
break;
}
ep_transfer_send(0, ptr, length, NULL);
} }
void ep0_handle_dfu(struct usb_ctrlrequest *req) void ep0_handle_dfu(struct usb_ctrlrequest *req)
{ {
uint32_t rc, ret = RET_NOTHING; uint32_t ret = RET_NOTHING;
// printf("state:%x\n\r", dfu_state);
switch (dfu_state) { switch (dfu_state) {
case DFU_STATE_appIDLE: case DFU_STATE_appIDLE:
@ -272,9 +385,7 @@ void ep0_handle_dfu(struct usb_ctrlrequest *req)
switch (req->bRequest) { switch (req->bRequest) {
case USB_REQ_DFU_UPLOAD: case USB_REQ_DFU_UPLOAD:
/* state transition if less data then requested */ /* state transition if less data then requested */
rc = handle_upload(req->wIndex, req->wValue, req->wLength); handle_upload(req->wIndex, req->wValue, req->wLength);
if (rc >= 0 && rc < req->wLength)
dfu_state = DFU_STATE_dfuIDLE;
break; break;
case USB_REQ_DFU_GETSTATUS: case USB_REQ_DFU_GETSTATUS: