Skip to content

Commit

Permalink
Adding McHCK DFU Bootloader
Browse files Browse the repository at this point in the history
- Heavily modified, not compatible with McHCK images
- Uses 4k of Flash (rather than 3k)
- LED turns on when in firmware flash mode
- Changed the USB IDs
- Added CMake build system
- Updated linker script to be closer to what is used for the rest of the projects
- Removed a lot of unnecessary code
- Added a license header to each file (using the same license as the McHCK had)
- Updated the USB Vendor, Product and Serial strings
- Using the Kiibohd initialization sequence rather than the McHCK one
- Using Kiibohd interrupt vector table and other misc mk20dx setup
  • Loading branch information
haata committed Aug 15, 2014
1 parent eabb1c5 commit 4102512
Show file tree
Hide file tree
Showing 20 changed files with 3,742 additions and 0 deletions.
173 changes: 173 additions & 0 deletions Bootloader/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,173 @@
###| CMAKE Kiibohd Controller Bootloader |###
#
# Jacob Alexander 2011-2014
# Due to this file's usefulness:
#
# Released into the Public Domain
#
# This bootloader is based upon the MCHCK dfu-usb bootloader.
# DO NOT USE with Teensy based microcontrollers.
#
###



###
# Chip Selection
#

#| You _MUST_ set this to match the microcontroller you are trying to compile for
#| You _MUST_ clean the build directory if you change this value
#|
set( CHIP
"mk20dx128vlf5" # McHCK mk20dx128vlf5
)


###
# Bootloader Configuration
#
set ( BOOTLOADER 1 )



###
# Compiler Intialization
#
set ( CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_SOURCE_DIR}/../Lib/CMake )
include( initialize )



##
# Source Defines
#
set( SRCS
main.c
dfu.c
dfu.desc.c
flash.c
kinetis.c
usb.c
)

message( STATUS "Bootloader Source Files:" )
message( "${SRCS}" )

#| Add Lib sources to main list
foreach( SRC_FILE ${COMPILER_SRCS} )
set( SRCS ${SRCS} ${CMAKE_SOURCE_DIR}/../${SRC_FILE} )
endforeach()




###
# Directory Includes
#
include_directories( ${CMAKE_SOURCE_DIR}/../Lib )



###
# Project Description
#

#| Project
project( kiibohd_bootloader )

#| Target Name (output name)
set( TARGET kiibohd_bootloader )

#| General Settings
cmake_minimum_required( VERSION 2.8 )



###
# Generate Header Files
#
configure_file( _buildvars.h buildvars.h )
include_directories( ${CMAKE_BINARY_DIR} )



###
# CMake Module Checking
#
find_package( Git REQUIRED )
find_package( Ctags ) # Optional



###
# ctag Generation
#
if( CTAGS_EXECUTABLE )
# Generate the ctags
execute_process( COMMAND ctags ${SRCS}
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
)
endif()



###
# Build Targets
#

#| Create the .ELF file
set( TARGET_ELF ${TARGET}.elf )
add_executable( ${TARGET_ELF} ${SRCS} )


#| .ELF Properties
set_target_properties( ${TARGET_ELF} PROPERTIES
LINK_FLAGS ${LINKER_FLAGS}
SUFFIX "" # XXX Force Windows to keep the .exe off
)


#| Convert the .ELF into a .bin to load onto the McHCK
set( TARGET_BIN ${TARGET}.bin )
add_custom_command( TARGET ${TARGET_ELF} POST_BUILD
COMMAND ${CMAKE_OBJCOPY} ${BIN_FLAGS} ${TARGET_ELF} ${TARGET_BIN}
COMMENT "Creating binary file to load: ${TARGET_BIN}"
)


#| Generate the Extended .LSS
set( TARGET_LSS ${TARGET}.lss )
add_custom_command( TARGET ${TARGET_ELF} POST_BUILD
COMMAND ${CMAKE_OBJDUMP} ${LSS_FLAGS} ${TARGET_ELF} > ${TARGET_LSS}
COMMENT "Creating Extended Listing: ${TARGET_LSS}"
)


#| Generate the Symbol Table .SYM
set( TARGET_SYM ${TARGET}.sym )
add_custom_command( TARGET ${TARGET_ELF} POST_BUILD
COMMAND ${CMAKE_NM} -n ${TARGET_ELF} > ${TARGET_SYM}
COMMENT "Creating Symbol Table: ${TARGET_SYM}"
)


#| Compiler Selection Record
add_custom_command( TARGET ${TARGET_ELF} POST_BUILD
COMMAND ${CMAKE_SOURCE_DIR}/../Lib/CMake/writer compiler ${COMPILER_FAMILY}
)



###
# Size Information
#

#| After Changes Size Information
add_custom_target( SizeAfter ALL
COMMAND ${CMAKE_SOURCE_DIR}/../Lib/CMake/sizeCalculator ${CMAKE_SIZE} ram ${TARGET_ELF} ${SIZE_RAM} " SRAM"
COMMAND ${CMAKE_SOURCE_DIR}/../Lib/CMake/sizeCalculator ${CMAKE_SIZE} flash ${TARGET_ELF} ${SIZE_FLASH} "Flash"
DEPENDS ${TARGET_ELF}
COMMENT "Chip usage for ${CHIP}"
)

45 changes: 45 additions & 0 deletions Bootloader/_buildvars.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/* Copyright (C) 2013-2014 by Jacob Alexander
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/

#ifndef __buildvars_h
#define __buildvars_h

// ----- Includes -----



// ----- Defines -----

// You can change these to give your code its own name.
#define STR_MANUFACTURER u"@MANUFACTURER@"
#define STR_PRODUCT u"Kiibohd DFU Bootloader"
#define STR_SERIAL u"@CHIP@"


// Mac OS-X and Linux automatically load the correct drivers. On
// Windows, even though the driver is supplied by Microsoft, an
// INF file is needed to load the driver. These numbers need to
// match the INF file.
#define VENDOR_ID @BOOT_VENDOR_ID@
#define PRODUCT_ID @BOOT_PRODUCT_ID@

#endif

171 changes: 171 additions & 0 deletions Bootloader/dfu.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
/* Copyright (c) 2011,2012 Simon Schubert <[email protected]>.
* Modifications by Jacob Alexander 2014 <[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
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

// ----- Local Includes -----

#include "usb.h"
#include "dfu.h"



// ----- Functions -----

void dfu_write_done( enum dfu_status err, struct dfu_ctx *ctx )
{
ctx->status = err;
if (ctx->status == DFU_STATUS_OK) {
switch (ctx->state) {
case DFU_STATE_dfuDNBUSY:
ctx->state = DFU_STATE_dfuDNLOAD_IDLE;
break;
default:
break;
}
} else {
ctx->state = DFU_STATE_dfuERROR;
}
}

static void dfu_dnload_complete( void *buf, ssize_t len, void *cbdata )
{
struct dfu_ctx *ctx = cbdata;

if (len > 0)
ctx->state = DFU_STATE_dfuDNBUSY;
else
ctx->state = DFU_STATE_dfuMANIFEST;
ctx->status = ctx->finish_write(buf, ctx->off, len);
ctx->off += len;
ctx->len = len;

if (ctx->status != DFU_STATUS_async)
dfu_write_done(ctx->status, ctx);

usb_handle_control_status(ctx->state == DFU_STATE_dfuERROR);
}

static void dfu_reset_system( void *buf, ssize_t len, void *cbdata )
{
SOFTWARE_RESET();
}

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) {
case USB_CTRL_REQ_DFU_DNLOAD: {
void *buf;

switch (ctx->state) {
case DFU_STATE_dfuIDLE:
ctx->off = 0;
break;
case DFU_STATE_dfuDNLOAD_IDLE:
break;
default:
goto err;
}

/**
* XXX we are not allowed to STALL here, and we need to eat all transferred data.
* better not allow setup_write to break the protocol.
*/
ctx->status = ctx->setup_write(ctx->off, req->wLength, &buf);
if (ctx->status != DFU_STATUS_OK) {
ctx->state = DFU_STATE_dfuERROR;
goto err_have_status;
}

if (req->wLength > 0)
usb_ep0_rx(buf, req->wLength, dfu_dnload_complete, ctx);
else
dfu_dnload_complete(NULL, 0, ctx);
goto out_no_status;
}
case USB_CTRL_REQ_DFU_GETSTATUS: {
struct dfu_status_t st;

st.bState = ctx->state;
st.bStatus = ctx->status;
st.bwPollTimeout = 1000; /* XXX */
/**
* If we're in DFU_STATE_dfuMANIFEST, we just finished
* the download, and we're just about to send our last
* status report. Once the report has been sent, go
* and reset the system to put the new firmware into
* effect.
*/
usb_ep0_tx_cp(&st, sizeof(st), req->wLength, NULL, NULL);
if (ctx->state == DFU_STATE_dfuMANIFEST) {
usb_handle_control_status_cb(dfu_reset_system);
goto out_no_status;
}
break;
}
case USB_CTRL_REQ_DFU_CLRSTATUS:
ctx->state = DFU_STATE_dfuIDLE;
ctx->status = DFU_STATUS_OK;
break;
case USB_CTRL_REQ_DFU_GETSTATE: {
uint8_t st = ctx->state;
usb_ep0_tx_cp(&st, sizeof(st), req->wLength, NULL, NULL);
break;
}
case USB_CTRL_REQ_DFU_ABORT:
switch (ctx->state) {
case DFU_STATE_dfuIDLE:
case DFU_STATE_dfuDNLOAD_IDLE:
/* case DFU_STATE_dfuUPLOAD_IDLE: */
ctx->state = DFU_STATE_dfuIDLE;
break;
default:
goto err;
}
break;
/* case USB_CTRL_REQ_DFU_UPLOAD: */
default:
return (0);
}

fail = 0;
goto out;

err:
ctx->status = DFU_STATUS_errSTALLEDPKT;
err_have_status:
ctx->state = DFU_STATE_dfuERROR;
out:
usb_handle_control_status(fail);
out_no_status:
return (1);
}

void dfu_init( dfu_setup_write_t setup_write, dfu_finish_write_t finish_write, struct dfu_ctx *ctx )
{
ctx->state = DFU_STATE_dfuIDLE;
ctx->setup_write = setup_write;
ctx->finish_write = finish_write;
usb_attach_function(&dfu_function, &ctx->header);
}

const struct usbd_function dfu_function = {
.control = dfu_handle_control,
.interface_count = USB_FUNCTION_DFU_IFACE_COUNT,
};

Loading

0 comments on commit 4102512

Please sign in to comment.