@@ -60,6 +60,7 @@ include( initialize ) | |||
# | |||
set( SRCS | |||
main.c | |||
debug.c # TODO only compile in if necessary | |||
dfu.c | |||
dfu.desc.c | |||
flash.c |
@@ -19,6 +19,7 @@ | |||
#include "usb.h" | |||
#include "dfu.h" | |||
#include "debug.h" | |||
@@ -68,7 +69,8 @@ static int dfu_handle_control( struct usb_ctrl_req_t *req, void *data ) | |||
struct dfu_ctx *ctx = data; | |||
int fail = 1; | |||
switch ((enum dfu_ctrl_req_code)req->bRequest) { | |||
switch ((enum dfu_ctrl_req_code)req->bRequest) | |||
{ | |||
case USB_CTRL_REQ_DFU_DNLOAD: { | |||
void *buf; | |||
@@ -99,13 +101,12 @@ static int dfu_handle_control( struct usb_ctrl_req_t *req, void *data ) | |||
goto out_no_status; | |||
} | |||
case USB_CTRL_REQ_DFU_UPLOAD: { | |||
return (0); // TODO | |||
/* | |||
void *buf; | |||
size_t len = 0; | |||
switch (ctx->state) { | |||
switch ( ctx->state ) | |||
{ | |||
case DFU_STATE_dfuIDLE: | |||
ctx->off = 0; | |||
break; | |||
case DFU_STATE_dfuUPLOAD_IDLE: | |||
break; | |||
@@ -113,20 +114,33 @@ static int dfu_handle_control( struct usb_ctrl_req_t *req, void *data ) | |||
goto err; | |||
} | |||
// XXX Don't STALL? -HaaTa | |||
// TODO | |||
ctx->status = ctx->setup_write(ctx->off, req->wLength, &buf); | |||
if (ctx->status != DFU_STATUS_OK) { | |||
// Find which sector to read | |||
ctx->status = ctx->setup_read(ctx->off, &len, &buf); | |||
print("UPLOAD off:"); | |||
printHex( ctx->off ); | |||
print(" len:"); | |||
printHex( len ); | |||
print(" addr:"); | |||
printHex( (uint32_t)buf ); | |||
print( NL ); | |||
if ( ctx->status != DFU_STATUS_OK || len > req->wLength ) | |||
{ | |||
ctx->state = DFU_STATE_dfuERROR; | |||
goto err_have_status; | |||
} | |||
if (req->wLength > 0) | |||
usb_ep0_rx(buf, req->wLength, dfu_dnload_complete, ctx); | |||
// Send bytes to Host | |||
if ( len > 0 ) | |||
{ | |||
usb_ep0_rx( buf, len, NULL, NULL ); | |||
} | |||
else | |||
dfu_dnload_complete(NULL, 0, ctx); | |||
{ | |||
ctx->state = DFU_STATE_dfuIDLE; | |||
} | |||
goto out_no_status; | |||
*/ | |||
} | |||
case USB_CTRL_REQ_DFU_GETSTATUS: { | |||
struct dfu_status_t st; | |||
@@ -223,9 +237,10 @@ out_no_status: | |||
return (1); | |||
} | |||
void dfu_init( dfu_setup_write_t setup_write, dfu_finish_write_t finish_write, struct dfu_ctx *ctx ) | |||
void dfu_init( dfu_setup_read_t setup_read, dfu_setup_write_t setup_write, dfu_finish_write_t finish_write, struct dfu_ctx *ctx ) | |||
{ | |||
ctx->state = DFU_STATE_dfuIDLE; | |||
ctx->setup_read = setup_read; | |||
ctx->setup_write = setup_write; | |||
ctx->finish_write = finish_write; | |||
usb_attach_function(&dfu_function, &ctx->header); |
@@ -1,5 +1,5 @@ | |||
/* Copyright (c) 2011,2012 Simon Schubert <[email protected]>. | |||
* Modifications by Jacob Alexander 2014 <[email protected]> | |||
* Modifications by Jacob Alexander 2014-2015 <[email protected]> | |||
* | |||
* 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 | |||
@@ -42,39 +42,6 @@ | |||
// ----- Macros ----- | |||
#define USB_FUNCTION_DESC_DFU(state...) \ | |||
{ \ | |||
.iface = { \ | |||
.bLength = sizeof(struct usb_desc_iface_t), \ | |||
.bDescriptorType = USB_DESC_IFACE, \ | |||
.bInterfaceNumber = USB_FUNCTION_IFACE(0, state), \ | |||
.bAlternateSetting = 0, \ | |||
.bNumEndpoints = 0, \ | |||
.bInterfaceClass = USB_DEV_CLASS_APP, \ | |||
.bInterfaceSubClass = USB_DEV_SUBCLASS_APP_DFU, \ | |||
.bInterfaceProtocol = USB_DEV_PROTO_DFU_DFU, \ | |||
.iInterface = 0, \ | |||
}, \ | |||
.dfu = { \ | |||
.bLength = sizeof(struct dfu_desc_functional), \ | |||
.bDescriptorType = { \ | |||
.id = 0x1, \ | |||
.type_type = USB_DESC_TYPE_CLASS \ | |||
}, \ | |||
.will_detach = 1, \ | |||
.manifestation_tolerant = 0, \ | |||
.can_upload = 0, \ | |||
.can_download = 1, \ | |||
.wDetachTimeOut = 0, \ | |||
.wTransferSize = USB_DFU_TRANSFER_SIZE, \ | |||
.bcdDFUVersion = { .maj = 1, .min = 1 } \ | |||
} \ | |||
} | |||
// ----- Enumerations ----- | |||
enum dfu_dev_subclass { | |||
@@ -143,6 +110,7 @@ struct dfu_status_t { | |||
CTASSERT_SIZE_BYTE(struct dfu_status_t, 6); | |||
typedef enum dfu_status (*dfu_setup_read_t)(size_t off, size_t *len, void **buf); | |||
typedef enum dfu_status (*dfu_setup_write_t)(size_t off, size_t len, void **buf); | |||
typedef enum dfu_status (*dfu_finish_write_t)(void *, size_t off, size_t len); | |||
typedef void (*dfu_detach_t)(void); | |||
@@ -151,6 +119,7 @@ struct dfu_ctx { | |||
struct usbd_function_ctx_header header; | |||
enum dfu_state state; | |||
enum dfu_status status; | |||
dfu_setup_read_t setup_read; | |||
dfu_setup_write_t setup_write; | |||
dfu_finish_write_t finish_write; | |||
size_t off; | |||
@@ -190,8 +159,8 @@ extern const struct usbd_function dfu_app_function; | |||
// ----- Functions ----- | |||
void dfu_write_done(enum dfu_status, struct dfu_ctx *ctx); | |||
void dfu_init(dfu_setup_write_t setup_write, dfu_finish_write_t finish_write, struct dfu_ctx *ctx); | |||
void dfu_app_init(dfu_detach_t detachcb); | |||
void dfu_write_done( enum dfu_status, struct dfu_ctx *ctx ); | |||
void dfu_init( dfu_setup_read_t setup_read, dfu_setup_write_t setup_write, dfu_finish_write_t finish_write, struct dfu_ctx *ctx ); | |||
void dfu_app_init( dfu_detach_t detachcb ); | |||
#endif |
@@ -21,6 +21,8 @@ | |||
#include "mchck.h" | |||
#include "dfu.desc.h" | |||
#include "debug.h" | |||
// ----- Variables ----- | |||
@@ -34,9 +36,60 @@ static char staging[ FLASH_SECTOR_SIZE ]; | |||
// ----- Functions ----- | |||
void sector_print( void* buf, size_t sector, size_t chunks ) | |||
{ | |||
uint8_t* start = (uint8_t*)buf + sector * USB_DFU_TRANSFER_SIZE; | |||
uint8_t* end = (uint8_t*)buf + (sector + 1) * USB_DFU_TRANSFER_SIZE; | |||
uint8_t* pos = start; | |||
print( NL ); | |||
print("Block "); | |||
printHex( sector ); | |||
print(" "); | |||
printHex( (size_t)start ); | |||
print(" -> "); | |||
printHex( (size_t)end ); | |||
print( NL ); | |||
// Display sector | |||
for ( size_t line = 0; pos < end - 24; line++ ) | |||
{ | |||
// Each Line | |||
printHex_op( (size_t)pos, 4 ); | |||
print(" "); | |||
// Each 2 byte chunk | |||
for ( size_t chunk = 0; chunk < chunks; chunk++ ) | |||
{ | |||
// Print out the two bytes (second one first) | |||
printHex_op( *(pos + 1), 2 ); | |||
printHex_op( *pos, 2 ); | |||
print(" "); | |||
pos += 2; | |||
} | |||
print( NL ); | |||
} | |||
} | |||
static enum dfu_status setup_read( size_t off, size_t *len, void **buf ) | |||
{ | |||
// Calculate starting address from offset | |||
*buf = (void*)&_app_rom + (USB_DFU_TRANSFER_SIZE / 4) * off; | |||
// Calculate length of transfer | |||
*len = *buf > (void*)(&_app_rom_end) - USB_DFU_TRANSFER_SIZE | |||
? 0 : USB_DFU_TRANSFER_SIZE; | |||
// Check for error | |||
if ( *buf > (void*)&_app_rom_end ) | |||
return (DFU_STATUS_errADDRESS); | |||
return (DFU_STATUS_OK); | |||
} | |||
static enum dfu_status setup_write( size_t off, size_t len, void **buf ) | |||
{ | |||
GPIOA_PCOR |= (1<<5); | |||
static int last = 0; | |||
if ( len > sizeof(staging) ) | |||
@@ -67,6 +120,9 @@ static enum dfu_status finish_write( void *buf, size_t off, size_t len ) | |||
if ( !target ) | |||
return (DFU_STATUS_errADDRESS); | |||
memcpy( target, buf, len ); | |||
print("BUF: "); | |||
printHex( off ); | |||
sector_print( target, 0, 16 ); | |||
// Depending on the error return a different status | |||
switch ( flash_program_sector(off + (uintptr_t)&_app_rom, FLASH_SECTOR_SIZE) ) | |||
@@ -91,7 +147,7 @@ static struct dfu_ctx dfu_ctx; | |||
void init_usb_bootloader( int config ) | |||
{ | |||
dfu_init(setup_write, finish_write, &dfu_ctx); | |||
dfu_init( setup_read, setup_write, finish_write, &dfu_ctx ); | |||
} | |||
void main() | |||
@@ -115,26 +171,25 @@ void main() | |||
#error "Incompatible chip for bootloader" | |||
#endif | |||
//for (uint8_t c = 0; c < 20; c++) | |||
/* | |||
while( 1 ) | |||
{ | |||
GPIOA_PTOR |= (1<<5); | |||
for (uint32_t d = 0; d < 7200000; d++ ); | |||
} | |||
*/ | |||
uart_serial_setup(); | |||
printNL( NL "Bootloader DFU-Mode" ); | |||
// TODO REMOVEME | |||
for ( uint8_t sector = 0; sector < 3; sector++ ) | |||
sector_print( &_app_rom, sector, 16 ); | |||
print( NL ); | |||
// XXX REMOVEME | |||
/* | |||
GPIOB_PDDR |= (1<<16); | |||
PORTB_PCR16 = PORT_PCR_SRE | PORT_PCR_DSE | PORT_PCR_MUX(1); | |||
GPIOB_PSOR |= (1<<16); | |||
*/ | |||
// RST | |||
GPIOC_PDDR |= (1<<8); | |||
PORTC_PCR8 = PORT_PCR_SRE | PORT_PCR_DSE | PORT_PCR_MUX(1); | |||
GPIOC_PSOR |= (1<<8); | |||
/* | |||
// CS1B | |||
GPIOC_PDDR |= (1<<4); | |||
PORTC_PCR4 = PORT_PCR_SRE | PORT_PCR_DSE | PORT_PCR_MUX(1); | |||
@@ -151,31 +206,14 @@ void main() | |||
PORTC_PCR3 = PORT_PCR_SRE | PORT_PCR_DSE | PORT_PCR_MUX(1); | |||
GPIOC_PCOR |= (1<<3); | |||
flash_prepare_flashing(); | |||
uint32_t *position = &_app_rom; | |||
//uint32_t *position = &_app_rom; | |||
usb_init( &dfu_device ); | |||
for (;;) | |||
{ | |||
usb_poll(); | |||
/* | |||
for ( ; position < &_app_rom + 0x201; position++ ) | |||
//for ( ; position < &_app_rom + 0x800; position++ ) | |||
{ | |||
if ( *position != 0xFFFFFFFF ) | |||
{ | |||
while( 1 ) | |||
{ | |||
GPIOA_PTOR |= (1<<5); | |||
for (uint32_t d = 0; d < 7200000; d++ ); | |||
} | |||
} | |||
} | |||
*/ | |||
} | |||
} | |||
@@ -1,5 +1,5 @@ | |||
/* Copyright (c) 2011,2012 Simon Schubert <[email protected]>. | |||
* Modifications by Jacob Alexander 2014 <[email protected]> | |||
* Modifications by Jacob Alexander 2014=2015 <[email protected]> | |||
* | |||
* 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 | |||
@@ -37,7 +37,7 @@ | |||
#include "mchck-cdefs.h" | |||
extern uint32_t _sidata, _sdata, _edata, _sbss, _ebss, _app_rom; | |||
extern uint32_t _sidata, _sdata, _edata, _sbss, _ebss, _app_rom, _app_rom_end; | |||
#include "ftfl.h" | |||
#include "usbotg.h" |
@@ -33,11 +33,13 @@ MEMORY | |||
{ | |||
FLASH (rx) : ORIGIN = 0x0, LENGTH = 256K | |||
FLASH_APP (rx) : ORIGIN = 8K, LENGTH = 256K-8K | |||
FLASH_END (r) : ORIGIN = 256K, LENGTH = 32 | |||
RAM (rwx) : ORIGIN = 0x20000000 - 64K / 2, LENGTH = 64K | |||
} | |||
/* Starting Address of the application ROM */ | |||
_app_rom = ORIGIN( FLASH_APP ); | |||
_app_rom_end = ORIGIN( FLASH_END ); | |||
FlexRAM = 0x14000000; | |||
FTFL = 0x40020000; |
@@ -53,11 +53,13 @@ | |||
#define TX_TIMEOUT_MSEC 50 | |||
#if F_CPU == 96000000 | |||
#define TX_TIMEOUT (TX_TIMEOUT_MSEC * 596) | |||
#define TX_TIMEOUT (TX_TIMEOUT_MSEC * 596) | |||
#elif F_CPU == 72000000 | |||
#define TX_TIMEOUT (TX_TIMEOUT_MSEC * 512) // XXX Correct? | |||
#elif F_CPU == 48000000 | |||
#define TX_TIMEOUT (TX_TIMEOUT_MSEC * 428) | |||
#define TX_TIMEOUT (TX_TIMEOUT_MSEC * 428) | |||
#elif F_CPU == 24000000 | |||
#define TX_TIMEOUT (TX_TIMEOUT_MSEC * 262) | |||
#define TX_TIMEOUT (TX_TIMEOUT_MSEC * 262) | |||
#endif | |||
@@ -1,7 +1,7 @@ | |||
/* Teensyduino Core Library | |||
* http://www.pjrc.com/teensy/ | |||
* Copyright (c) 2013 PJRC.COM, LLC. | |||
* Modified by Jacob Alexander 2013-2014 | |||
* Modified by Jacob Alexander 2013-2015 | |||
* | |||
* Permission is hereby granted, free of charge, to any person obtaining | |||
* a copy of this software and associated documentation files (the | |||
@@ -56,11 +56,13 @@ | |||
#define TX_TIMEOUT_MSEC 70 | |||
#if F_CPU == 96000000 | |||
#define TX_TIMEOUT (TX_TIMEOUT_MSEC * 596) | |||
#define TX_TIMEOUT (TX_TIMEOUT_MSEC * 596) | |||
#elif F_CPU == 72000000 | |||
#define TX_TIMEOUT (TX_TIMEOUT_MSEC * 512) // XXX Correct? | |||
#elif F_CPU == 48000000 | |||
#define TX_TIMEOUT (TX_TIMEOUT_MSEC * 428) | |||
#define TX_TIMEOUT (TX_TIMEOUT_MSEC * 428) | |||
#elif F_CPU == 24000000 | |||
#define TX_TIMEOUT (TX_TIMEOUT_MSEC * 262) | |||
#define TX_TIMEOUT (TX_TIMEOUT_MSEC * 262) | |||
#endif | |||
@@ -192,14 +192,14 @@ void uart_serial_setup() | |||
#elif defined(_mk20dx256vlh7_) // UART2 Debug | |||
// Setup baud rate - 115200 Baud | |||
// Uses Bus Clock | |||
// 24 MHz / ( 16 * Baud ) = BDH/L | |||
// Baud: 115200 -> 24 MHz / ( 16 * 115200 ) = 13.021 | |||
// Thus baud setting = 13 | |||
// 36 MHz / ( 16 * Baud ) = BDH/L | |||
// Baud: 115200 -> 36 MHz / ( 16 * 115200 ) = 19.53125 | |||
// Thus baud setting = 19 | |||
// NOTE: If finer baud adjustment is needed see UARTx_C4 -> BRFA in the datasheet | |||
uint16_t baud = 13; // Max setting of 8191 | |||
uint16_t baud = 19; // Max setting of 8191 | |||
UART_BDH = (uint8_t)(baud >> 8); | |||
UART_BDL = (uint8_t)baud; | |||
UART_C4 = 0x01; | |||
UART_C4 = 0x11; | |||
#endif | |||