working version
This commit is contained in:
parent
fded24a803
commit
bd59d4924f
@ -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)
|
||||||
|
@ -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
|
||||||
@ -10,7 +10,7 @@
|
|||||||
#define TWI_ADDR_BL4 0x24
|
#define TWI_ADDR_BL4 0x24
|
||||||
#define TWI_ADDR_EEPROM 0x40
|
#define TWI_ADDR_EEPROM 0x40
|
||||||
|
|
||||||
/* TWIBOOT commands */
|
/* TWIBOOT commands */
|
||||||
#define CMD_WAIT 0x00
|
#define CMD_WAIT 0x00
|
||||||
#define CMD_GET_INFO 0x10
|
#define CMD_GET_INFO 0x10
|
||||||
#define CMD_GET_SIGNATURE 0x11
|
#define CMD_GET_SIGNATURE 0x11
|
||||||
@ -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 */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -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);
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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
143
src/dfu.c
@ -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:
|
||||||
|
Loading…
Reference in New Issue
Block a user