Adding McHCK DFU Bootloader
- 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
This commit is contained in:
		
							parent
							
								
									eabb1c546a
								
							
						
					
					
						commit
						4102512579
					
				
					 20 changed files with 3742 additions and 0 deletions
				
			
		
							
								
								
									
										173
									
								
								Bootloader/CMakeLists.txt
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										173
									
								
								Bootloader/CMakeLists.txt
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -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
									
								
								Bootloader/_buildvars.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										45
									
								
								Bootloader/_buildvars.h
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -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
									
								
								Bootloader/dfu.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										171
									
								
								Bootloader/dfu.c
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,171 @@
 | 
				
			||||||
 | 
					/* Copyright (c) 2011,2012 Simon Schubert <2@0x2c.org>.
 | 
				
			||||||
 | 
					 * Modifications by Jacob Alexander 2014 <haata@kiibohd.com>
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * 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,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							
								
								
									
										115
									
								
								Bootloader/dfu.desc.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										115
									
								
								Bootloader/dfu.desc.c
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,115 @@
 | 
				
			||||||
 | 
					// Originally Generated from MCHCK Toolkit
 | 
				
			||||||
 | 
					/* Copyright (c) Jacob Alexander 2014 <haata@kiibohd.com>
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * 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 "dfu.desc.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ----- Generated Includes -----
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <buildvars.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ----- Structs -----
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static const struct usb_config_1 usb_config_1 = {
 | 
				
			||||||
 | 
						.config = {
 | 
				
			||||||
 | 
							.bLength = sizeof(struct usb_desc_config_t),
 | 
				
			||||||
 | 
							.bDescriptorType = USB_DESC_CONFIG,
 | 
				
			||||||
 | 
							.wTotalLength = sizeof(struct usb_config_1),
 | 
				
			||||||
 | 
							.bNumInterfaces = 1,
 | 
				
			||||||
 | 
							.bConfigurationValue = 1,
 | 
				
			||||||
 | 
							.iConfiguration = 0,
 | 
				
			||||||
 | 
							.one = 1,
 | 
				
			||||||
 | 
							.bMaxPower = 100
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						.usb_function_0 = {
 | 
				
			||||||
 | 
							.iface = {
 | 
				
			||||||
 | 
								.bLength = sizeof(struct usb_desc_iface_t),
 | 
				
			||||||
 | 
								.bDescriptorType = USB_DESC_IFACE,
 | 
				
			||||||
 | 
								.bInterfaceNumber = 0,
 | 
				
			||||||
 | 
								.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 }
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static const struct usbd_config usbd_config_1 = {
 | 
				
			||||||
 | 
						.init = init_usb_bootloader,
 | 
				
			||||||
 | 
						.suspend = NULL,
 | 
				
			||||||
 | 
						.resume = NULL,
 | 
				
			||||||
 | 
						.desc = &usb_config_1.config,
 | 
				
			||||||
 | 
						.function = {&dfu_function},
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static const struct usb_desc_dev_t dfu_device_dev_desc = {
 | 
				
			||||||
 | 
						.bLength = sizeof(struct usb_desc_dev_t),
 | 
				
			||||||
 | 
						.bDescriptorType = USB_DESC_DEV,
 | 
				
			||||||
 | 
						.bcdUSB = { .maj = 2 },
 | 
				
			||||||
 | 
						.bDeviceClass = USB_DEV_CLASS_SEE_IFACE,
 | 
				
			||||||
 | 
						.bDeviceSubClass = USB_DEV_SUBCLASS_SEE_IFACE,
 | 
				
			||||||
 | 
						.bDeviceProtocol = USB_DEV_PROTO_SEE_IFACE,
 | 
				
			||||||
 | 
						.bMaxPacketSize0 = EP0_BUFSIZE,
 | 
				
			||||||
 | 
						.idVendor = VENDOR_ID,
 | 
				
			||||||
 | 
						.idProduct = PRODUCT_ID,
 | 
				
			||||||
 | 
						.bcdDevice = { .raw = 0 },
 | 
				
			||||||
 | 
						.iManufacturer = 1,
 | 
				
			||||||
 | 
						.iProduct = 2,
 | 
				
			||||||
 | 
						.iSerialNumber = 3,
 | 
				
			||||||
 | 
						.bNumConfigurations = 1,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static const struct usb_desc_string_t * const dfu_device_str_desc[] = {
 | 
				
			||||||
 | 
						USB_DESC_STRING_LANG_ENUS,
 | 
				
			||||||
 | 
						USB_DESC_STRING(STR_MANUFACTURER),
 | 
				
			||||||
 | 
						USB_DESC_STRING(STR_PRODUCT),
 | 
				
			||||||
 | 
						USB_DESC_STRING(STR_SERIAL),
 | 
				
			||||||
 | 
						NULL
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const struct usbd_device dfu_device = {
 | 
				
			||||||
 | 
						.dev_desc = &dfu_device_dev_desc,
 | 
				
			||||||
 | 
						.string_descs = dfu_device_str_desc,
 | 
				
			||||||
 | 
						.configs = {
 | 
				
			||||||
 | 
							&usbd_config_1,
 | 
				
			||||||
 | 
							NULL
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							
								
								
									
										43
									
								
								Bootloader/dfu.desc.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										43
									
								
								Bootloader/dfu.desc.h
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,43 @@
 | 
				
			||||||
 | 
					// Originally Generated from MCHCK Toolkit
 | 
				
			||||||
 | 
					/* Copyright (c) Jacob Alexander 2014 <haata@kiibohd.com>
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * 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/>.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef __DFU_DESC_H
 | 
				
			||||||
 | 
					#define __DFU_DESC_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ----- Local Includes -----
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "mchck.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ----- Variables -----
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const struct usbd_device dfu_device;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					usbd_init_fun_t init_usb_bootloader;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ----- Structs -----
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct usb_config_1 {
 | 
				
			||||||
 | 
						struct usb_desc_config_t config;
 | 
				
			||||||
 | 
						struct dfu_function_desc usb_function_0;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							
								
								
									
										197
									
								
								Bootloader/dfu.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										197
									
								
								Bootloader/dfu.h
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,197 @@
 | 
				
			||||||
 | 
					/* Copyright (c) 2011,2012 Simon Schubert <2@0x2c.org>.
 | 
				
			||||||
 | 
					 * Modifications by Jacob Alexander 2014 <haata@kiibohd.com>
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * 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/>.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef _USB_DFU_H
 | 
				
			||||||
 | 
					#define _USB_DFU_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ----- Compiler Includes -----
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <sys/types.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ----- Defines -----
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define USB_FUNCTION_DFU_IFACE_COUNT 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef USB_DFU_TRANSFER_SIZE
 | 
				
			||||||
 | 
					#define USB_DFU_TRANSFER_SIZE	FLASH_SECTOR_SIZE
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define USB_FUNCTION_DESC_DFU_DECL                         \
 | 
				
			||||||
 | 
					        struct dfu_function_desc
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define USB_FUNCTION_DFU_IFACE_COUNT	1
 | 
				
			||||||
 | 
					#define USB_FUNCTION_DFU_RX_EP_COUNT	0
 | 
				
			||||||
 | 
					#define USB_FUNCTION_DFU_TX_EP_COUNT	0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ----- 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 {
 | 
				
			||||||
 | 
					        USB_DEV_SUBCLASS_APP_DFU = 0x01
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					enum dfu_dev_proto {
 | 
				
			||||||
 | 
					        USB_DEV_PROTO_DFU_APP = 0x01,
 | 
				
			||||||
 | 
					        USB_DEV_PROTO_DFU_DFU = 0x02
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					enum dfu_ctrl_req_code {
 | 
				
			||||||
 | 
					        USB_CTRL_REQ_DFU_DETACH = 0,
 | 
				
			||||||
 | 
					        USB_CTRL_REQ_DFU_DNLOAD = 1,
 | 
				
			||||||
 | 
					        USB_CTRL_REQ_DFU_UPLOAD = 2,
 | 
				
			||||||
 | 
					        USB_CTRL_REQ_DFU_GETSTATUS = 3,
 | 
				
			||||||
 | 
					        USB_CTRL_REQ_DFU_CLRSTATUS = 4,
 | 
				
			||||||
 | 
					        USB_CTRL_REQ_DFU_GETSTATE = 5,
 | 
				
			||||||
 | 
					        USB_CTRL_REQ_DFU_ABORT = 6
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					enum dfu_status {
 | 
				
			||||||
 | 
					        DFU_STATUS_async = 0xff,
 | 
				
			||||||
 | 
					        DFU_STATUS_OK = 0x00,
 | 
				
			||||||
 | 
					        DFU_STATUS_errTARGET = 0x01,
 | 
				
			||||||
 | 
					        DFU_STATUS_errFILE = 0x02,
 | 
				
			||||||
 | 
					        DFU_STATUS_errWRITE = 0x03,
 | 
				
			||||||
 | 
					        DFU_STATUS_errERASE = 0x04,
 | 
				
			||||||
 | 
					        DFU_STATUS_errCHECK_ERASED = 0x05,
 | 
				
			||||||
 | 
					        DFU_STATUS_errPROG = 0x06,
 | 
				
			||||||
 | 
					        DFU_STATUS_errVERIFY = 0x07,
 | 
				
			||||||
 | 
					        DFU_STATUS_errADDRESS = 0x08,
 | 
				
			||||||
 | 
					        DFU_STATUS_errNOTDONE = 0x09,
 | 
				
			||||||
 | 
					        DFU_STATUS_errFIRMWARE = 0x0a,
 | 
				
			||||||
 | 
					        DFU_STATUS_errVENDOR = 0x0b,
 | 
				
			||||||
 | 
					        DFU_STATUS_errUSBR = 0x0c,
 | 
				
			||||||
 | 
					        DFU_STATUS_errPOR = 0x0d,
 | 
				
			||||||
 | 
					        DFU_STATUS_errUNKNOWN = 0x0e,
 | 
				
			||||||
 | 
					        DFU_STATUS_errSTALLEDPKT = 0x0f
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					enum dfu_state {
 | 
				
			||||||
 | 
					        DFU_STATE_appIDLE = 0,
 | 
				
			||||||
 | 
					        DFU_STATE_appDETACH = 1,
 | 
				
			||||||
 | 
					        DFU_STATE_dfuIDLE = 2,
 | 
				
			||||||
 | 
					        DFU_STATE_dfuDNLOAD_SYNC = 3,
 | 
				
			||||||
 | 
					        DFU_STATE_dfuDNBUSY = 4,
 | 
				
			||||||
 | 
					        DFU_STATE_dfuDNLOAD_IDLE = 5,
 | 
				
			||||||
 | 
					        DFU_STATE_dfuMANIFEST_SYNC = 6,
 | 
				
			||||||
 | 
					        DFU_STATE_dfuMANIFEST = 7,
 | 
				
			||||||
 | 
					        DFU_STATE_dfuMANIFEST_WAIT_RESET = 8,
 | 
				
			||||||
 | 
					        DFU_STATE_dfuUPLOAD_IDLE = 9,
 | 
				
			||||||
 | 
					        DFU_STATE_dfuERROR = 10
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ----- Structs -----
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct dfu_status_t {
 | 
				
			||||||
 | 
					        enum dfu_status bStatus : 8;
 | 
				
			||||||
 | 
					        uint32_t bwPollTimeout : 24;
 | 
				
			||||||
 | 
					        enum dfu_state bState : 8;
 | 
				
			||||||
 | 
					        uint8_t iString;
 | 
				
			||||||
 | 
					} __packed;
 | 
				
			||||||
 | 
					CTASSERT_SIZE_BYTE(struct dfu_status_t, 6);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					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);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct dfu_ctx {
 | 
				
			||||||
 | 
					        struct usbd_function_ctx_header header;
 | 
				
			||||||
 | 
					        enum dfu_state state;
 | 
				
			||||||
 | 
					        enum dfu_status status;
 | 
				
			||||||
 | 
					        dfu_setup_write_t setup_write;
 | 
				
			||||||
 | 
					        dfu_finish_write_t finish_write;
 | 
				
			||||||
 | 
					        size_t off;
 | 
				
			||||||
 | 
					        size_t len;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct dfu_desc_functional {
 | 
				
			||||||
 | 
					        uint8_t bLength;
 | 
				
			||||||
 | 
					        struct usb_desc_type_t bDescriptorType; /* = class DFU/0x1 FUNCTIONAL */
 | 
				
			||||||
 | 
					        union {
 | 
				
			||||||
 | 
					                struct {
 | 
				
			||||||
 | 
					                        uint8_t can_download : 1;
 | 
				
			||||||
 | 
					                        uint8_t can_upload : 1;
 | 
				
			||||||
 | 
					                        uint8_t manifestation_tolerant : 1;
 | 
				
			||||||
 | 
					                        uint8_t will_detach : 1;
 | 
				
			||||||
 | 
					                        uint8_t _rsvd0 : 4;
 | 
				
			||||||
 | 
					                };
 | 
				
			||||||
 | 
					                uint8_t bmAttributes;
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					        uint16_t wDetachTimeOut;
 | 
				
			||||||
 | 
					        uint16_t wTransferSize;
 | 
				
			||||||
 | 
					        struct usb_bcd_t bcdDFUVersion;
 | 
				
			||||||
 | 
					} __packed;
 | 
				
			||||||
 | 
					CTASSERT_SIZE_BYTE(struct dfu_desc_functional, 9);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct dfu_function_desc {
 | 
				
			||||||
 | 
					        struct usb_desc_iface_t iface;
 | 
				
			||||||
 | 
					        struct dfu_desc_functional dfu;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					extern const struct usbd_function dfu_function;
 | 
				
			||||||
 | 
					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);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
							
								
								
									
										93
									
								
								Bootloader/flash.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										93
									
								
								Bootloader/flash.c
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,93 @@
 | 
				
			||||||
 | 
					/* Copyright (c) 2011,2012 Simon Schubert <2@0x2c.org>.
 | 
				
			||||||
 | 
					 * Modifications by Jacob Alexander 2014 <haata@kiibohd.com>
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * 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 "mchck.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ----- Variables -----
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					uint32_t flash_ALLOW_BRICKABLE_ADDRESSES;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ----- Functions -----
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* This will have to live in SRAM. */
 | 
				
			||||||
 | 
					__attribute__((section(".ramtext.ftfl_submit_cmd"), long_call))
 | 
				
			||||||
 | 
					int ftfl_submit_cmd(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					        FTFL.fstat.raw = ((struct FTFL_FSTAT_t){
 | 
				
			||||||
 | 
					                        .ccif = 1,
 | 
				
			||||||
 | 
					                                .rdcolerr = 1,
 | 
				
			||||||
 | 
					                                .accerr = 1,
 | 
				
			||||||
 | 
					                                .fpviol = 1
 | 
				
			||||||
 | 
					                                }).raw;
 | 
				
			||||||
 | 
					        struct FTFL_FSTAT_t stat;
 | 
				
			||||||
 | 
					        while (!(stat = FTFL.fstat).ccif)
 | 
				
			||||||
 | 
					                /* NOTHING */; /* XXX maybe WFI? */
 | 
				
			||||||
 | 
					        return (!!stat.mgstat0);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int flash_prepare_flashing(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					        /* switch to FlexRAM */
 | 
				
			||||||
 | 
					        if (!FTFL.fcnfg.ramrdy) {
 | 
				
			||||||
 | 
					                FTFL.fccob.set_flexram.fcmd = FTFL_FCMD_SET_FLEXRAM;
 | 
				
			||||||
 | 
					                FTFL.fccob.set_flexram.flexram_function = FTFL_FLEXRAM_RAM;
 | 
				
			||||||
 | 
					                return (ftfl_submit_cmd());
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return (0);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int flash_erase_sector(uintptr_t addr)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					        if (addr < (uintptr_t)&_app_rom &&
 | 
				
			||||||
 | 
					                flash_ALLOW_BRICKABLE_ADDRESSES != 0x00023420)
 | 
				
			||||||
 | 
					                return (-1);
 | 
				
			||||||
 | 
					        FTFL.fccob.erase.fcmd = FTFL_FCMD_ERASE_SECTOR;
 | 
				
			||||||
 | 
					        FTFL.fccob.erase.addr = addr;
 | 
				
			||||||
 | 
					        return (ftfl_submit_cmd());
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int flash_program_section(uintptr_t addr, size_t num_words)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						GPIOA_PSOR |= (1<<19);
 | 
				
			||||||
 | 
					        FTFL.fccob.program_section.fcmd = FTFL_FCMD_PROGRAM_SECTION;
 | 
				
			||||||
 | 
					        FTFL.fccob.program_section.addr = addr;
 | 
				
			||||||
 | 
					        FTFL.fccob.program_section.num_words = num_words;
 | 
				
			||||||
 | 
					        return (ftfl_submit_cmd());
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int flash_program_sector(uintptr_t addr, size_t len)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					        return (len != FLASH_SECTOR_SIZE ||
 | 
				
			||||||
 | 
					                (addr & (FLASH_SECTOR_SIZE - 1)) != 0 ||
 | 
				
			||||||
 | 
					                flash_erase_sector(addr) ||
 | 
				
			||||||
 | 
					                flash_program_section(addr, FLASH_SECTOR_SIZE/4));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void *flash_get_staging_area(uintptr_t addr, size_t len)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					        if ((addr & (FLASH_SECTOR_SIZE - 1)) != 0 ||
 | 
				
			||||||
 | 
					            len != FLASH_SECTOR_SIZE)
 | 
				
			||||||
 | 
					                return (NULL);
 | 
				
			||||||
 | 
					        return (FlexRAM);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							
								
								
									
										38
									
								
								Bootloader/flash.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								Bootloader/flash.h
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,38 @@
 | 
				
			||||||
 | 
					/* Copyright (c) 2011,2012 Simon Schubert <2@0x2c.org>.
 | 
				
			||||||
 | 
					 * Modifications by Jacob Alexander 2014 <haata@kiibohd.com>
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * 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/>.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef __FLASH_H
 | 
				
			||||||
 | 
					#define __FLASH_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ----- Defines -----
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define FLASH_SECTOR_SIZE 1024
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ----- Functions -----
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					__attribute__((section(".ramtext.ftfl_submit_cmd"), long_call))
 | 
				
			||||||
 | 
					int ftfl_submit_cmd(void);
 | 
				
			||||||
 | 
					int flash_prepare_flashing(void);
 | 
				
			||||||
 | 
					int flash_erase_sector(uintptr_t);
 | 
				
			||||||
 | 
					int flash_program_section(uintptr_t, size_t);
 | 
				
			||||||
 | 
					int flash_program_sector(uintptr_t, size_t);
 | 
				
			||||||
 | 
					void *flash_get_staging_area(uintptr_t, size_t);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							
								
								
									
										246
									
								
								Bootloader/ftfl.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										246
									
								
								Bootloader/ftfl.h
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,246 @@
 | 
				
			||||||
 | 
					/* Copyright (c) 2011,2012 Simon Schubert <2@0x2c.org>.
 | 
				
			||||||
 | 
					 * Modifications by Jacob Alexander 2014 <haata@kiibohd.com>
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * 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/>.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef __FTFL_H
 | 
				
			||||||
 | 
					#define __FTFL_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ----- Local Includes -----
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "mchck-cdefs.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ----- Structs -----
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct FTFL_FSTAT_t {
 | 
				
			||||||
 | 
					        UNION_STRUCT_START(8);
 | 
				
			||||||
 | 
					        uint8_t mgstat0 : 1;
 | 
				
			||||||
 | 
					        uint8_t _rsvd0 : 3;
 | 
				
			||||||
 | 
					        uint8_t fpviol : 1;
 | 
				
			||||||
 | 
					        uint8_t accerr : 1;
 | 
				
			||||||
 | 
					        uint8_t rdcolerr : 1;
 | 
				
			||||||
 | 
					        uint8_t ccif : 1;
 | 
				
			||||||
 | 
					        UNION_STRUCT_END;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					CTASSERT_SIZE_BIT(struct FTFL_FSTAT_t, 8);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct FTFL_FCNFG_t {
 | 
				
			||||||
 | 
					        UNION_STRUCT_START(8);
 | 
				
			||||||
 | 
					        uint8_t eeerdy : 1;
 | 
				
			||||||
 | 
					        uint8_t ramrdy : 1;
 | 
				
			||||||
 | 
					        uint8_t pflsh : 1;
 | 
				
			||||||
 | 
					        uint8_t _rsvd0 : 1;
 | 
				
			||||||
 | 
					        uint8_t erssusp : 1;
 | 
				
			||||||
 | 
					        uint8_t ersareq : 1;
 | 
				
			||||||
 | 
					        uint8_t rdcollie : 1;
 | 
				
			||||||
 | 
					        uint8_t ccie : 1;
 | 
				
			||||||
 | 
					        UNION_STRUCT_END;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					CTASSERT_SIZE_BIT(struct FTFL_FCNFG_t, 8);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct FTFL_FSEC_t {
 | 
				
			||||||
 | 
					        UNION_STRUCT_START(8);
 | 
				
			||||||
 | 
					        enum {
 | 
				
			||||||
 | 
					                FTFL_FSEC_SEC_UNSECURE = 2,
 | 
				
			||||||
 | 
					                FTFL_FSEC_SEC_SECURE = 3
 | 
				
			||||||
 | 
					        } sec : 2;
 | 
				
			||||||
 | 
					        enum {
 | 
				
			||||||
 | 
					                FTFL_FSEC_FSLACC_DENY = 1,
 | 
				
			||||||
 | 
					                FTFL_FSEC_FSLACC_GRANT = 3
 | 
				
			||||||
 | 
					        } fslacc : 2;
 | 
				
			||||||
 | 
					        enum {
 | 
				
			||||||
 | 
					                FTFL_FSEC_MEEN_DISABLE = 2,
 | 
				
			||||||
 | 
					                FTFL_FSEC_MEEN_ENABLE = 3
 | 
				
			||||||
 | 
					        } meen : 2;
 | 
				
			||||||
 | 
					        enum {
 | 
				
			||||||
 | 
					                FTFL_FSEC_KEYEN_DISABLE = 1,
 | 
				
			||||||
 | 
					                FTFL_FSEC_KEYEN_ENABLE = 2
 | 
				
			||||||
 | 
					        } keyen : 2;
 | 
				
			||||||
 | 
					        UNION_STRUCT_END;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					CTASSERT_SIZE_BIT(struct FTFL_FSEC_t, 8);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct FTFL_FOPT_t {
 | 
				
			||||||
 | 
					        UNION_STRUCT_START(8);
 | 
				
			||||||
 | 
					        uint8_t lpboot : 1;
 | 
				
			||||||
 | 
					        uint8_t ezport_dis : 1;
 | 
				
			||||||
 | 
					        uint8_t nmi_dis : 1;
 | 
				
			||||||
 | 
					        uint8_t _rsvd0 : 5;
 | 
				
			||||||
 | 
					        UNION_STRUCT_END;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					CTASSERT_SIZE_BIT(struct FTFL_FOPT_t, 8);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * The FCOOB is a weird register file, because it is double big endian,
 | 
				
			||||||
 | 
					 * which makes for odd gaps and for some data that is big endian, and for
 | 
				
			||||||
 | 
					 * some that is little endian.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					union FTFL_FCCOB_t {
 | 
				
			||||||
 | 
					        struct ftfl_generic {
 | 
				
			||||||
 | 
					                uint32_t addr : 24;
 | 
				
			||||||
 | 
					                enum FTFL_FCMD {
 | 
				
			||||||
 | 
					                        FTFL_FCMD_READ_1s_BLOCK = 0x00,
 | 
				
			||||||
 | 
					                        FTFL_FCMD_READ_1s_SECTION = 0x01,
 | 
				
			||||||
 | 
					                        FTFL_FCMD_PROGRAM_CHECK = 0x02,
 | 
				
			||||||
 | 
					                        FTFL_FCMD_READ_RESOURCE = 0x03,
 | 
				
			||||||
 | 
					                        FTFL_FCMD_PROGRAM_LONGWORD = 0x06,
 | 
				
			||||||
 | 
					                        FTFL_FCMD_ERASE_BLOCK = 0x08,
 | 
				
			||||||
 | 
					                        FTFL_FCMD_ERASE_SECTOR = 0x09,
 | 
				
			||||||
 | 
					                        FTFL_FCMD_PROGRAM_SECTION = 0x0b,
 | 
				
			||||||
 | 
					                        FTFL_FCMD_READ_1s_ALL_BLOCKS = 0x40,
 | 
				
			||||||
 | 
					                        FTFL_FCMD_READ_ONCE = 0x41,
 | 
				
			||||||
 | 
					                        FTFL_FCMD_PROGRAM_ONCE = 0x43,
 | 
				
			||||||
 | 
					                        FTFL_FCMD_ERASE_ALL_BLOCKS = 0x44,
 | 
				
			||||||
 | 
					                        FTFL_FCMD_VERIFY_KEY = 0x45,
 | 
				
			||||||
 | 
					                        FTFL_FCMD_PROGRAM_PARTITION = 0x80,
 | 
				
			||||||
 | 
					                        FTFL_FCMD_SET_FLEXRAM = 0x81
 | 
				
			||||||
 | 
					                } fcmd : 8;
 | 
				
			||||||
 | 
					                uint8_t data_be[8];
 | 
				
			||||||
 | 
					        } generic;
 | 
				
			||||||
 | 
					        struct {
 | 
				
			||||||
 | 
					                uint32_t addr : 24;
 | 
				
			||||||
 | 
					                enum FTFL_FCMD fcmd : 8;
 | 
				
			||||||
 | 
					                uint8_t _rsvd0[3];
 | 
				
			||||||
 | 
					                enum FTFL_MARGIN_CHOICE {
 | 
				
			||||||
 | 
					                        FTFL_MARGIN_NORMAL = 0x00,
 | 
				
			||||||
 | 
					                        FTFL_MARGIN_USER = 0x01,
 | 
				
			||||||
 | 
					                        FTFL_MARGIN_FACTORY = 0x02
 | 
				
			||||||
 | 
					                } margin : 8;
 | 
				
			||||||
 | 
					        } read_1s_block;
 | 
				
			||||||
 | 
					        struct ftfl_data_num_words {
 | 
				
			||||||
 | 
					                uint32_t addr : 24;
 | 
				
			||||||
 | 
					                enum FTFL_FCMD fcmd : 8;
 | 
				
			||||||
 | 
					                uint8_t _rsvd0;
 | 
				
			||||||
 | 
					                enum FTFL_MARGIN_CHOICE margin : 8;
 | 
				
			||||||
 | 
					                uint16_t num_words;
 | 
				
			||||||
 | 
					        } read_1s_section;
 | 
				
			||||||
 | 
					        struct {
 | 
				
			||||||
 | 
					                uint32_t addr : 24;
 | 
				
			||||||
 | 
					                enum FTFL_FCMD fcmd : 8;
 | 
				
			||||||
 | 
					                uint8_t _rsvd0[3];
 | 
				
			||||||
 | 
					                enum FTFL_MARGIN_CHOICE margin : 8;
 | 
				
			||||||
 | 
					                uint8_t data_be[4];
 | 
				
			||||||
 | 
					        } program_check;
 | 
				
			||||||
 | 
					        struct {
 | 
				
			||||||
 | 
					                uint32_t addr : 24;
 | 
				
			||||||
 | 
					                enum FTFL_FCMD fcmd : 8;
 | 
				
			||||||
 | 
					                uint32_t data;
 | 
				
			||||||
 | 
					                uint8_t _rsvd0[3];
 | 
				
			||||||
 | 
					                enum FTFL_RESOURCE_SELECT {
 | 
				
			||||||
 | 
					                        FTFL_RESOURCE_IFR = 0x00,
 | 
				
			||||||
 | 
					                        FTFL_RESOURCE_VERSION = 0x01
 | 
				
			||||||
 | 
					                } resource_select : 8;
 | 
				
			||||||
 | 
					        } read_resource;
 | 
				
			||||||
 | 
					        struct {
 | 
				
			||||||
 | 
					                uint32_t addr : 24;
 | 
				
			||||||
 | 
					                enum FTFL_FCMD fcmd : 8;
 | 
				
			||||||
 | 
					                uint8_t data_be[4];
 | 
				
			||||||
 | 
					        } program_longword;
 | 
				
			||||||
 | 
					        struct {
 | 
				
			||||||
 | 
					                uint32_t addr : 24;
 | 
				
			||||||
 | 
					                enum FTFL_FCMD fcmd : 8;
 | 
				
			||||||
 | 
					        } erase;
 | 
				
			||||||
 | 
					        struct ftfl_data_num_words program_section;
 | 
				
			||||||
 | 
					        struct {
 | 
				
			||||||
 | 
					                uint8_t _rsvd0[2];
 | 
				
			||||||
 | 
					                enum FTFL_MARGIN_CHOICE margin : 8;
 | 
				
			||||||
 | 
					                enum FTFL_FCMD fcmd : 8;
 | 
				
			||||||
 | 
					        } read_1s_all_blocks;
 | 
				
			||||||
 | 
					        struct ftfl_cmd_once {
 | 
				
			||||||
 | 
					                uint8_t _rsvd0[2];
 | 
				
			||||||
 | 
					                uint8_t idx;
 | 
				
			||||||
 | 
					                enum FTFL_FCMD fcmd : 8;
 | 
				
			||||||
 | 
					                uint8_t data_be[4];
 | 
				
			||||||
 | 
					        } read_once;
 | 
				
			||||||
 | 
					        struct ftfl_cmd_once program_once;
 | 
				
			||||||
 | 
					        struct {
 | 
				
			||||||
 | 
					                uint8_t _rsvd0[3];
 | 
				
			||||||
 | 
					                enum FTFL_FCMD fcmd : 8;
 | 
				
			||||||
 | 
					        } erase_all;
 | 
				
			||||||
 | 
					        struct {
 | 
				
			||||||
 | 
					                uint8_t _rsvd0[3];
 | 
				
			||||||
 | 
					                enum FTFL_FCMD fcmd : 8;
 | 
				
			||||||
 | 
					                uint8_t key_be[8];
 | 
				
			||||||
 | 
					        } verify_key;
 | 
				
			||||||
 | 
					        struct {
 | 
				
			||||||
 | 
					                uint8_t _rsvd0[3];
 | 
				
			||||||
 | 
					                enum FTFL_FCMD fcmd : 8;
 | 
				
			||||||
 | 
					                uint8_t _rsvd1[2];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                /* the following enum is analogous to enum
 | 
				
			||||||
 | 
					                 * SIM_FLEXNVM_PARTITION in sim.h, but this one is padded
 | 
				
			||||||
 | 
					                 * with four 1-bits to make an 8-bit value.
 | 
				
			||||||
 | 
					                 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                enum FTFL_FLEXNVM_PARTITION {
 | 
				
			||||||
 | 
					                        FTFL_FLEXNVM_DATA_32_EEPROM_0 = 0xF0,
 | 
				
			||||||
 | 
					                        FTFL_FLEXNVM_DATA_24_EEPROM_8 = 0xF1,
 | 
				
			||||||
 | 
					                        FTFL_FLEXNVM_DATA_16_EEPROM_16 = 0xF2,
 | 
				
			||||||
 | 
					                        FTFL_FLEXNVM_DATA_8_EEPROM_24 = 0xF9,
 | 
				
			||||||
 | 
					                        FTFL_FLEXNVM_DATA_0_EEPROM_32 = 0xF3
 | 
				
			||||||
 | 
					                } flexnvm_partition : 8;
 | 
				
			||||||
 | 
					                enum FTFL_EEPROM_SIZE {
 | 
				
			||||||
 | 
					                        FTFL_EEPROM_SIZE_0 = 0x3f,
 | 
				
			||||||
 | 
					                        FTFL_EEPROM_SIZE_32 = 0x39,
 | 
				
			||||||
 | 
					                        FTFL_EEPROM_SIZE_64 = 0x38,
 | 
				
			||||||
 | 
					                        FTFL_EEPROM_SIZE_128 = 0x37,
 | 
				
			||||||
 | 
					                        FTFL_EEPROM_SIZE_256 = 0x36,
 | 
				
			||||||
 | 
					                        FTFL_EEPROM_SIZE_512 = 0x35,
 | 
				
			||||||
 | 
					                        FTFL_EEPROM_SIZE_1024 = 0x34,
 | 
				
			||||||
 | 
					                        FTFL_EEPROM_SIZE_2048 = 0x33
 | 
				
			||||||
 | 
					                } eeprom_size : 8;
 | 
				
			||||||
 | 
					        } program_partition;
 | 
				
			||||||
 | 
					        struct {
 | 
				
			||||||
 | 
					                uint8_t _rsvd0[2];
 | 
				
			||||||
 | 
					                enum FTFL_FLEXRAM_FUNCTION {
 | 
				
			||||||
 | 
					                        FTFL_FLEXRAM_EEPROM = 0x00,
 | 
				
			||||||
 | 
					                        FTFL_FLEXRAM_RAM = 0xff
 | 
				
			||||||
 | 
					                } flexram_function : 8;
 | 
				
			||||||
 | 
					                enum FTFL_FCMD fcmd : 8;
 | 
				
			||||||
 | 
					        } set_flexram;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					CTASSERT_SIZE_BYTE(union FTFL_FCCOB_t, 12);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct FTFL_t {
 | 
				
			||||||
 | 
					        struct FTFL_FSTAT_t fstat;
 | 
				
			||||||
 | 
					        struct FTFL_FCNFG_t fcnfg;
 | 
				
			||||||
 | 
					        struct FTFL_FSEC_t fsec;
 | 
				
			||||||
 | 
					        struct FTFL_FOPT_t fopt;
 | 
				
			||||||
 | 
					        union FTFL_FCCOB_t fccob;
 | 
				
			||||||
 | 
					        uint8_t fprot_be[4];
 | 
				
			||||||
 | 
					        uint8_t feprot;
 | 
				
			||||||
 | 
					        uint8_t fdprot;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					CTASSERT_SIZE_BYTE(struct FTFL_t, 0x18);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Flash Configuration Field, see Sub-Family Reference Manual, section 28.3.1 */
 | 
				
			||||||
 | 
					struct FTFL_CONFIG_t {
 | 
				
			||||||
 | 
					        uint8_t key[8];
 | 
				
			||||||
 | 
					        uint8_t fprot[4];
 | 
				
			||||||
 | 
					        struct FTFL_FSEC_t fsec;
 | 
				
			||||||
 | 
					        struct FTFL_FOPT_t fopt;
 | 
				
			||||||
 | 
					        uint8_t feprot;
 | 
				
			||||||
 | 
					        uint8_t fdprot;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					CTASSERT_SIZE_BYTE(struct FTFL_CONFIG_t, 16);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					extern volatile struct FTFL_t FTFL;
 | 
				
			||||||
 | 
					extern char FlexRAM[];
 | 
				
			||||||
 | 
					extern struct FTFL_CONFIG_t FTFL_CONFIG;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							
								
								
									
										326
									
								
								Bootloader/kinetis.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										326
									
								
								Bootloader/kinetis.c
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,326 @@
 | 
				
			||||||
 | 
					/* Copyright (c) 2011,2012 Simon Schubert <2@0x2c.org>.
 | 
				
			||||||
 | 
					 * Modifications by Jacob Alexander 2014 <haata@kiibohd.com>
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * 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/>.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ----- Defines -----
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define usb_xfer_info USB_STAT_t
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ----- Local Includes -----
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "mchck.h"
 | 
				
			||||||
 | 
					#include "usb-internal.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ----- Functions -----
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Kinetis USB driver notes:
 | 
				
			||||||
 | 
					 * We need to manually maintain the DATA0/1 toggling for the SIE.
 | 
				
			||||||
 | 
					 * SETUP transactions always start with a DATA0.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * The SIE internally uses pingpong (double) buffering, which is
 | 
				
			||||||
 | 
					 * easily confused with DATA0/DATA1 toggling, and I think even the
 | 
				
			||||||
 | 
					 * Freescale docs confuse the two notions.  When BD->DTS is set,
 | 
				
			||||||
 | 
					 * BD->DATA01 will be used to verify/discard incoming DATAx and it
 | 
				
			||||||
 | 
					 * will set the DATAx PID for outgoing tokens.  This is not described
 | 
				
			||||||
 | 
					 * as such in the Freescale Kinetis docs, but the Microchip PIC32 OTG
 | 
				
			||||||
 | 
					 * docs are more clear on this;  it seems that both Freescale and
 | 
				
			||||||
 | 
					 * Microchip use different versions of the same USB OTG IP core.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * http://ww1.microchip.com/downloads/en/DeviceDoc/61126F.pdf
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Clear CTL->TOKEN_BUSY after SETUP tokens.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static struct USB_BD_t bdt[USB_MAX_EP * 2 *2] __attribute__((section(".usbdescriptortable")));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static struct USB_BD_t *
 | 
				
			||||||
 | 
					usb_get_bd(struct usbd_ep_pipe_state_t *s)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					        return (&bdt[(s->ep_num << 2) | (s->ep_dir << 1) | s->pingpong]);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static struct USB_BD_t *
 | 
				
			||||||
 | 
					usb_get_bd_stat(struct USB_STAT_t *stat)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					        return (((void *)(uintptr_t)bdt + (stat->raw << 1)));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void *usb_get_xfer_data(struct usb_xfer_info *i)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					        return (usb_get_bd_stat(i)->addr);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					enum usb_tok_pid usb_get_xfer_pid(struct usb_xfer_info *i)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					        return (usb_get_bd_stat(i)->tok_pid);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int usb_get_xfer_ep(struct usb_xfer_info *i)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					        return (i->ep);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					enum usb_ep_dir usb_get_xfer_dir(struct usb_xfer_info *i)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					        return (i->dir);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void usb_enable_xfers(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					        USB0.ctl.raw = ((struct USB_CTL_t){
 | 
				
			||||||
 | 
					                        .txd_suspend = 0,
 | 
				
			||||||
 | 
					                                .usben = 1
 | 
				
			||||||
 | 
					                                }).raw;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void usb_set_addr(int addr)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					        USB0.addr.raw = addr;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void usb_pipe_stall(struct usbd_ep_pipe_state_t *s)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					        volatile struct USB_BD_t *bd = usb_get_bd(s);
 | 
				
			||||||
 | 
					        bd->raw = ((struct USB_BD_BITS_t){
 | 
				
			||||||
 | 
					                        .stall = 1,
 | 
				
			||||||
 | 
					                                .own = 1
 | 
				
			||||||
 | 
					                                }).raw;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void usb_pipe_unstall(struct usbd_ep_pipe_state_t *s)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					        volatile struct USB_BD_t *bd = usb_get_bd(s);
 | 
				
			||||||
 | 
					        struct USB_BD_BITS_t state = { .raw = bd->raw };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (state.own && state.stall)
 | 
				
			||||||
 | 
					                bd->raw = 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void usb_pipe_enable(struct usbd_ep_pipe_state_t *s)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					        USB0.endpt[s->ep_num].raw |= ((struct USB_ENDPT_t){
 | 
				
			||||||
 | 
					                        .eptxen = s->ep_dir == USB_EP_TX,
 | 
				
			||||||
 | 
					                                .eprxen = s->ep_dir == USB_EP_RX,
 | 
				
			||||||
 | 
					                                .ephshk = 1, /* XXX ISO */
 | 
				
			||||||
 | 
					                                .epctldis = s->ep_num != 0
 | 
				
			||||||
 | 
					                                }).raw;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void usb_pipe_disable(struct usbd_ep_pipe_state_t *s)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					        USB0.endpt[s->ep_num].raw &= ~((struct USB_ENDPT_t){
 | 
				
			||||||
 | 
					                        .eptxen = s->ep_dir == USB_EP_TX,
 | 
				
			||||||
 | 
					                                .eprxen = s->ep_dir == USB_EP_RX,
 | 
				
			||||||
 | 
					                                .epctldis = 1
 | 
				
			||||||
 | 
					                                }).raw;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					size_t usb_ep_get_transfer_size(struct usbd_ep_pipe_state_t *s)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					        struct USB_BD_t *bd = usb_get_bd(s);
 | 
				
			||||||
 | 
					        return (bd->bc);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void usb_queue_next(struct usbd_ep_pipe_state_t *s, void *addr, size_t len)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					        volatile struct USB_BD_t *bd = usb_get_bd(s);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        bd->addr = addr;
 | 
				
			||||||
 | 
					        /* damn you bitfield problems */
 | 
				
			||||||
 | 
					        bd->raw = ((struct USB_BD_BITS_t){
 | 
				
			||||||
 | 
					                        .dts = 1,
 | 
				
			||||||
 | 
					                                .own = 1,
 | 
				
			||||||
 | 
					                                .data01 = s->data01,
 | 
				
			||||||
 | 
					                                .bc = len,
 | 
				
			||||||
 | 
					                                }).raw;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void usb_reset(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					        /* reset pingpong state */
 | 
				
			||||||
 | 
					        /* For some obscure reason, we need to use or here. */
 | 
				
			||||||
 | 
					        USB0.ctl.raw |= ((struct USB_CTL_t){
 | 
				
			||||||
 | 
					                        .txd_suspend = 1,
 | 
				
			||||||
 | 
					                                .oddrst = 1,
 | 
				
			||||||
 | 
					                                }).raw;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /* clear all interrupt bits - not sure if needed */
 | 
				
			||||||
 | 
					        USB0.istat.raw = 0xff;
 | 
				
			||||||
 | 
					        USB0.errstat.raw = 0xff;
 | 
				
			||||||
 | 
					        USB0.otgistat.raw = 0xff;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /* zap also BDT pingpong & queued transactions */
 | 
				
			||||||
 | 
					        memset(bdt, 0, sizeof(bdt));
 | 
				
			||||||
 | 
					        USB0.addr.raw = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        usb_restart();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        USB0.ctl.raw = ((struct USB_CTL_t){
 | 
				
			||||||
 | 
					                        	.txd_suspend = 0,
 | 
				
			||||||
 | 
					                                .usben = 1
 | 
				
			||||||
 | 
					                                }).raw;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /* we're only interested in reset and transfers */
 | 
				
			||||||
 | 
					        USB0.inten.raw = ((struct USB_ISTAT_t){
 | 
				
			||||||
 | 
					                        	.tokdne = 1,
 | 
				
			||||||
 | 
					                                .usbrst = 1,
 | 
				
			||||||
 | 
					                                .stall = 1,
 | 
				
			||||||
 | 
					                                .sleep = 1,
 | 
				
			||||||
 | 
					                                }).raw;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        USB0.usbtrc0.usbresmen = 0;
 | 
				
			||||||
 | 
					        USB0.usbctrl.susp = 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void usb_enable(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					        SIM.sopt2.usbsrc = 1;   /* usb from mcg */
 | 
				
			||||||
 | 
					        SIM.scgc4.usbotg = 1;   /* enable usb clock */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /* reset module - not sure if needed */
 | 
				
			||||||
 | 
					        USB0.usbtrc0.raw = ((struct USB_USBTRC0_t){
 | 
				
			||||||
 | 
					                        	.usbreset = 1,
 | 
				
			||||||
 | 
					                                .usbresmen = 1
 | 
				
			||||||
 | 
					                                }).raw;
 | 
				
			||||||
 | 
					        while (USB0.usbtrc0.usbreset)
 | 
				
			||||||
 | 
					                /* NOTHING */;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        USB0.bdtpage1 = (uintptr_t)bdt >> 8;
 | 
				
			||||||
 | 
					        USB0.bdtpage2 = (uintptr_t)bdt >> 16;
 | 
				
			||||||
 | 
					        USB0.bdtpage3 = (uintptr_t)bdt >> 24;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        USB0.control.raw = ((struct USB_CONTROL_t){
 | 
				
			||||||
 | 
					                        	.dppullupnonotg = 1 /* enable pullup */
 | 
				
			||||||
 | 
					                                }).raw;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        USB0.usbctrl.raw = 0; /* resume peripheral & disable pulldowns */
 | 
				
			||||||
 | 
					        usb_reset();          /* this will start usb processing */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /* really only one thing we want */
 | 
				
			||||||
 | 
					        USB0.inten.raw = ((struct USB_ISTAT_t){
 | 
				
			||||||
 | 
					                                .usbrst = 1,
 | 
				
			||||||
 | 
					                                }).raw;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /**
 | 
				
			||||||
 | 
					         * Suspend transceiver now - we'll wake up at reset again.
 | 
				
			||||||
 | 
					         */
 | 
				
			||||||
 | 
						// TODO - Possible removal
 | 
				
			||||||
 | 
					        USB0.usbctrl.susp = 1;
 | 
				
			||||||
 | 
					        USB0.usbtrc0.usbresmen = 1;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void USB0_Handler(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					        struct USB_ISTAT_t stat = {.raw = USB0.istat.raw };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (stat.usbrst) {
 | 
				
			||||||
 | 
					                usb_reset();
 | 
				
			||||||
 | 
					                return;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        if (stat.stall) {
 | 
				
			||||||
 | 
					                /* XXX need more work for non-0 ep */
 | 
				
			||||||
 | 
					                volatile struct USB_BD_t *bd = usb_get_bd(&usb.ep_state[0].rx);
 | 
				
			||||||
 | 
					                if (bd->stall)
 | 
				
			||||||
 | 
					                        usb_setup_control();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        if (stat.tokdne) {
 | 
				
			||||||
 | 
					                struct usb_xfer_info stat = USB0.stat;
 | 
				
			||||||
 | 
					                usb_handle_transaction(&stat);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        if (stat.sleep) {
 | 
				
			||||||
 | 
					                USB0.inten.sleep = 0;
 | 
				
			||||||
 | 
					                USB0.inten.resume = 1;
 | 
				
			||||||
 | 
					                USB0.usbctrl.susp = 1;
 | 
				
			||||||
 | 
					                USB0.usbtrc0.usbresmen = 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                /**
 | 
				
			||||||
 | 
					                 * Clear interrupts now so that we can detect a fresh
 | 
				
			||||||
 | 
					                 * resume later on.
 | 
				
			||||||
 | 
					                 */
 | 
				
			||||||
 | 
					                USB0.istat.raw = stat.raw;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                const struct usbd_config *c = usb_get_config_data(-1);
 | 
				
			||||||
 | 
					                if (c && c->suspend)
 | 
				
			||||||
 | 
					                        c->suspend();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        /**
 | 
				
			||||||
 | 
					         * XXX it is unclear whether we will receive a synchronous
 | 
				
			||||||
 | 
					         * resume interrupt if we were in sleep.  This code assumes we
 | 
				
			||||||
 | 
					         * do.
 | 
				
			||||||
 | 
					         */
 | 
				
			||||||
 | 
					        if (stat.resume || USB0.usbtrc0.usb_resume_int) {
 | 
				
			||||||
 | 
					                USB0.inten.resume = 0;
 | 
				
			||||||
 | 
					                USB0.inten.sleep = 1;
 | 
				
			||||||
 | 
					                USB0.usbtrc0.usbresmen = 0;
 | 
				
			||||||
 | 
					                USB0.usbctrl.susp = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                const struct usbd_config *c = usb_get_config_data(-1);
 | 
				
			||||||
 | 
					                if (c && c->resume)
 | 
				
			||||||
 | 
					                        c->resume();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                stat.resume = 1; /* always clear bit */
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        USB0.istat.raw = stat.raw;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void usb_poll(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					        USB0_Handler();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int usb_tx_serialno(size_t reqlen)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					        struct usb_desc_string_t *d;
 | 
				
			||||||
 | 
					        const size_t nregs = 3;
 | 
				
			||||||
 | 
					        /**
 | 
				
			||||||
 | 
					         * actually 4, but UIDH is 0xffffffff.  Also our output buffer
 | 
				
			||||||
 | 
					         * is only 64 bytes, and 128 bit + desc header exceeds this by
 | 
				
			||||||
 | 
					         * 2 bytes.
 | 
				
			||||||
 | 
					         */
 | 
				
			||||||
 | 
					        const size_t len = nregs * 4 * 2 * 2 + sizeof(*d);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        d = usb_ep0_tx_inplace_prepare(len);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (d == NULL)
 | 
				
			||||||
 | 
					                return (-1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        d->bLength = len;
 | 
				
			||||||
 | 
					        d->bDescriptorType = USB_DESC_STRING;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        size_t bufpos = 0;
 | 
				
			||||||
 | 
					        for (size_t reg = 0; reg < nregs; ++reg) {
 | 
				
			||||||
 | 
					                /* registers run MSW first */
 | 
				
			||||||
 | 
					                uint32_t val = (&SIM.uidmh)[reg];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                for (size_t bits = 32; bits > 0; bits -= 4, val <<= 4) {
 | 
				
			||||||
 | 
					                        int nibble = val >> 28;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                        if (nibble > 9)
 | 
				
			||||||
 | 
					                                nibble += 'a' - '9' - 1;
 | 
				
			||||||
 | 
					                        ((char16_t *)d->bString)[bufpos++] = nibble + '0';
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        usb_ep0_tx(d, len, reqlen, NULL, NULL);
 | 
				
			||||||
 | 
					        return (0);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							
								
								
									
										96
									
								
								Bootloader/main.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										96
									
								
								Bootloader/main.c
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,96 @@
 | 
				
			||||||
 | 
					/* Copyright (c) 2011,2012 Simon Schubert <2@0x2c.org>.
 | 
				
			||||||
 | 
					 * Modifications by Jacob Alexander 2014 <haata@kiibohd.com>
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * 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 "mchck.h"
 | 
				
			||||||
 | 
					#include "dfu.desc.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ----- Variables -----
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Unfortunately we can't DMA directly to FlexRAM, so we'll have to stage here.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static char staging[FLASH_SECTOR_SIZE];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ----- Functions -----
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static enum dfu_status setup_write(size_t off, size_t len, void **buf)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					        static int last = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (len > sizeof(staging))
 | 
				
			||||||
 | 
					                return (DFU_STATUS_errADDRESS);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // We only allow the last write to be less than one sector size.
 | 
				
			||||||
 | 
					        if (off == 0)
 | 
				
			||||||
 | 
					                last = 0;
 | 
				
			||||||
 | 
					        if (last && len != 0)
 | 
				
			||||||
 | 
					                return (DFU_STATUS_errADDRESS);
 | 
				
			||||||
 | 
					        if (len != FLASH_SECTOR_SIZE) {
 | 
				
			||||||
 | 
					                last = 1;
 | 
				
			||||||
 | 
					                memset(staging, 0xff, sizeof(staging));
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        *buf = staging;
 | 
				
			||||||
 | 
					        return (DFU_STATUS_OK);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static enum dfu_status finish_write( void *buf, size_t off, size_t len )
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					        void *target;
 | 
				
			||||||
 | 
					        if (len == 0)
 | 
				
			||||||
 | 
					                return (DFU_STATUS_OK);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        target = flash_get_staging_area(off + (uintptr_t)&_app_rom, FLASH_SECTOR_SIZE);
 | 
				
			||||||
 | 
					        if (!target)
 | 
				
			||||||
 | 
					                return (DFU_STATUS_errADDRESS);
 | 
				
			||||||
 | 
					        memcpy(target, buf, len);
 | 
				
			||||||
 | 
					        if (flash_program_sector(off + (uintptr_t)&_app_rom, FLASH_SECTOR_SIZE) != 0)
 | 
				
			||||||
 | 
					                return (DFU_STATUS_errADDRESS);
 | 
				
			||||||
 | 
					        return (DFU_STATUS_OK);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static struct dfu_ctx dfu_ctx;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void init_usb_bootloader( int config )
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					        dfu_init(setup_write, finish_write, &dfu_ctx);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void main()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						// Enabling LED to indicate we are in the bootloader
 | 
				
			||||||
 | 
						GPIOA_PDDR |= (1<<19);
 | 
				
			||||||
 | 
						// Setup pin - A19 - See Lib/pin_map.mchck for more details on pins
 | 
				
			||||||
 | 
						PORTA_PCR19 = PORT_PCR_SRE | PORT_PCR_DSE | PORT_PCR_MUX(1);
 | 
				
			||||||
 | 
						GPIOA_PSOR |= (1<<19);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        flash_prepare_flashing();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        usb_init( &dfu_device );
 | 
				
			||||||
 | 
					        for (;;)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
					                usb_poll();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							
								
								
									
										138
									
								
								Bootloader/mchck-cdefs.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										138
									
								
								Bootloader/mchck-cdefs.h
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,138 @@
 | 
				
			||||||
 | 
					/* Copyright (c) 2011,2012 Simon Schubert <2@0x2c.org>.
 | 
				
			||||||
 | 
					 * Modifications by Jacob Alexander 2014 <haata@kiibohd.com>
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * 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/>.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef _MCHCK_CDEFS_H
 | 
				
			||||||
 | 
					#define _MCHCK_CDEFS_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ----- Compiler Includes -----
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <sys/param.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ----- Defines & Macros -----
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define _CONCAT(x,y) _CONCAT1(x,y)
 | 
				
			||||||
 | 
					#define _CONCAT1(x,y) x ## y
 | 
				
			||||||
 | 
					#define _STR(a) #a
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef __CHAR16_TYPE__ char16_t;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define __packed __attribute__((__packed__))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* From FreeBSD: compile-time asserts */
 | 
				
			||||||
 | 
					#define CTASSERT(x)             _Static_assert(x, _STR(x))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define CTASSERT_SIZE_BYTE(t, s)     CTASSERT(sizeof(t) == (s))
 | 
				
			||||||
 | 
					#define CTASSERT_SIZE_BIT(t, s)     CTASSERT(sizeof(t) * 8 == (s))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define UNION_STRUCT_START(size)                                \
 | 
				
			||||||
 | 
					        union {                                                 \
 | 
				
			||||||
 | 
					        _CONCAT(_CONCAT(uint, size), _t) raw;                 \
 | 
				
			||||||
 | 
					        struct {                                                \
 | 
				
			||||||
 | 
					        /* just to swallow the following semicolon */           \
 | 
				
			||||||
 | 
					        struct _CONCAT(_CONCAT(__dummy_, __COUNTER__), _t) {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define UNION_STRUCT_END                        \
 | 
				
			||||||
 | 
					        }; /* struct */                         \
 | 
				
			||||||
 | 
					        }; /* union */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * From <news:dqgm2f$ije$1@sunnews.cern.ch>,
 | 
				
			||||||
 | 
					 * <https://groups.google.com/forum/#!topic/comp.std.c/d-6Mj5Lko_s>
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					#define __PP_NARG(...)                          \
 | 
				
			||||||
 | 
					        __PP_NARG_(__0, ## __VA_ARGS__, __PP_RSEQ_N())
 | 
				
			||||||
 | 
					#define __PP_NARG_(...)                         \
 | 
				
			||||||
 | 
					        __PP_ARG_N(__VA_ARGS__)
 | 
				
			||||||
 | 
					#define __PP_ARG_N(                                     \
 | 
				
			||||||
 | 
					        _1, _2, _3, _4, _5, _6, _7, _8, _9,_10,         \
 | 
				
			||||||
 | 
					        _11,_12,_13,_14,_15,_16,_17,_18,_19,_20,        \
 | 
				
			||||||
 | 
					        _21,_22,_23,_24,_25,_26,_27,_28,_29,_30,        \
 | 
				
			||||||
 | 
					        _31,_32,_33,_34,_35,_36,_37,_38,_39,_40,        \
 | 
				
			||||||
 | 
					        _41,_42,_43,_44,_45,_46,_47,_48,_49,_50,        \
 | 
				
			||||||
 | 
					        _51,_52,_53,_54,_55,_56,_57,_58,_59,_60,        \
 | 
				
			||||||
 | 
					        _61,_62,_63,N,...) N
 | 
				
			||||||
 | 
					#define __PP_RSEQ_N()                           \
 | 
				
			||||||
 | 
					        62,61,60,                               \
 | 
				
			||||||
 | 
					                59,58,57,56,55,54,53,52,51,50,  \
 | 
				
			||||||
 | 
					                49,48,47,46,45,44,43,42,41,40,  \
 | 
				
			||||||
 | 
					                39,38,37,36,35,34,33,32,31,30,  \
 | 
				
			||||||
 | 
					                29,28,27,26,25,24,23,22,21,20,  \
 | 
				
			||||||
 | 
					                19,18,17,16,15,14,13,12,11,10,  \
 | 
				
			||||||
 | 
					                9,8,7,6,5,4,3,2,1,0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * From <https://github.com/pfultz2/Cloak/wiki/C-Preprocessor-tricks,-tips,-and-idioms>
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					#define __CAT(a, ...) __PRIMITIVE_CAT(a, __VA_ARGS__)
 | 
				
			||||||
 | 
					#define __PRIMITIVE_CAT(a, ...) a ## __VA_ARGS__
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define __IIF(c) __PRIMITIVE_CAT(__IIF_, c)
 | 
				
			||||||
 | 
					#define __IIF_0(t, ...) __VA_ARGS__
 | 
				
			||||||
 | 
					#define __IIF_1(t, ...) t
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define __COMPL(b) __PRIMITIVE_CAT(__COMPL_, b)
 | 
				
			||||||
 | 
					#define __COMPL_0 1
 | 
				
			||||||
 | 
					#define __COMPL_1 0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define __CHECK_N(x, n, ...) n
 | 
				
			||||||
 | 
					#define __CHECK(...) __CHECK_N(__VA_ARGS__, 0,)
 | 
				
			||||||
 | 
					#define __PROBE(x) x, 1,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define __NOT(x) __CHECK(__PRIMITIVE_CAT(__NOT_, x))
 | 
				
			||||||
 | 
					#define __NOT_0 __PROBE(~)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define __BOOL(x) __COMPL(__NOT(x))
 | 
				
			||||||
 | 
					#define __IF(c) __IIF(__BOOL(c))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define __EAT(...)
 | 
				
			||||||
 | 
					#define __EXPAND(...) __VA_ARGS__
 | 
				
			||||||
 | 
					#define __WHEN(c) __IF(c)(__EXPAND, __EAT)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define __HEAD(h, ...) h
 | 
				
			||||||
 | 
					#define __TAIL(h, ...) __VA_ARGS__
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define __EVAL(...)  __EVAL1(__EVAL1(__EVAL1(__VA_ARGS__)))
 | 
				
			||||||
 | 
					#define __EVAL1(...) __EVAL2(__EVAL2(__EVAL2(__VA_ARGS__)))
 | 
				
			||||||
 | 
					#define __EVAL2(...) __EVAL3(__EVAL3(__EVAL3(__VA_ARGS__)))
 | 
				
			||||||
 | 
					#define __EVAL3(...) __EVAL4(__EVAL4(__EVAL4(__VA_ARGS__)))
 | 
				
			||||||
 | 
					#define __EVAL4(...) __EVAL5(__EVAL5(__EVAL5(__VA_ARGS__)))
 | 
				
			||||||
 | 
					#define __EVAL5(...) __EVAL6(__EVAL6(__EVAL6(__VA_ARGS__)))
 | 
				
			||||||
 | 
					#define __EVAL6(...) __VA_ARGS__
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define __EMPTY()
 | 
				
			||||||
 | 
					#define __DEFER(id) id __EMPTY()
 | 
				
			||||||
 | 
					#define __OBSTRUCT(...) __VA_ARGS__ __DEFER(__EMPTY)()
 | 
				
			||||||
 | 
					#define __CAT_ARG(f, a) __OBSTRUCT(f) a
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define __REPEAT(...) __EVAL(__REPEAT_(__VA_ARGS__))
 | 
				
			||||||
 | 
					#define __REPEAT_INNER(...) __OBSTRUCT(__REPEAT_INDIRECT) () (__VA_ARGS__)
 | 
				
			||||||
 | 
					#define __REPEAT_INDIRECT() __REPEAT_
 | 
				
			||||||
 | 
					#define __REPEAT_(iter, itermacro, macro, a, ...)                       \
 | 
				
			||||||
 | 
					        __OBSTRUCT(macro)(iter, a)                                      \
 | 
				
			||||||
 | 
					        __WHEN(__PP_NARG(__VA_ARGS__))                                  \
 | 
				
			||||||
 | 
					                (                                                       \
 | 
				
			||||||
 | 
					                        __OBSTRUCT(__REPEAT_INDIRECT) () (              \
 | 
				
			||||||
 | 
					                                itermacro(iter, a), itermacro, macro, __VA_ARGS__ \
 | 
				
			||||||
 | 
					                                )                                       \
 | 
				
			||||||
 | 
					                        )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							
								
								
									
										49
									
								
								Bootloader/mchck.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								Bootloader/mchck.h
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,49 @@
 | 
				
			||||||
 | 
					/* Copyright (c) 2011,2012 Simon Schubert <2@0x2c.org>.
 | 
				
			||||||
 | 
					 * Modifications by Jacob Alexander 2014 <haata@kiibohd.com>
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * 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/>.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef __MCHCK_H
 | 
				
			||||||
 | 
					#define __MCHCK_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ----- Compiler Includes -----
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <sys/types.h>
 | 
				
			||||||
 | 
					#include <sys/cdefs.h>
 | 
				
			||||||
 | 
					#include <stdfix.h>
 | 
				
			||||||
 | 
					#include <stdarg.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ----- Project Includes -----
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <mk20dx.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ----- Local Includes -----
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "mchck-cdefs.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					extern uint32_t _sidata, _sdata, _edata, _sbss, _ebss, _app_rom;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "ftfl.h"
 | 
				
			||||||
 | 
					#include "usbotg.h"
 | 
				
			||||||
 | 
					#include "sim.h"
 | 
				
			||||||
 | 
					#include "flash.h"
 | 
				
			||||||
 | 
					#include "usb.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							
								
								
									
										332
									
								
								Bootloader/sim.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										332
									
								
								Bootloader/sim.h
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,332 @@
 | 
				
			||||||
 | 
					/* Copyright (c) 2011,2012 Simon Schubert <2@0x2c.org>.
 | 
				
			||||||
 | 
					 * Modifications by Jacob Alexander 2014 <haata@kiibohd.com>
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * 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/>.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef __SIM_H
 | 
				
			||||||
 | 
					#define __SIM_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ----- Local Includes -----
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "mchck.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ----- Structs -----
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct SIM_t {
 | 
				
			||||||
 | 
					        struct SIM_SOPT1_t {
 | 
				
			||||||
 | 
					                UNION_STRUCT_START(32);
 | 
				
			||||||
 | 
					                uint32_t _rsvd0 : 12;
 | 
				
			||||||
 | 
					                enum {
 | 
				
			||||||
 | 
					                        SIM_RAMSIZE_8KB = 1,
 | 
				
			||||||
 | 
					                        SIM_RAMSIZE_16KB = 3
 | 
				
			||||||
 | 
					                } ramsize : 4;
 | 
				
			||||||
 | 
					                uint32_t _rsvd1 : 2;
 | 
				
			||||||
 | 
					                enum {
 | 
				
			||||||
 | 
					                        SIM_OSC32KSEL_SYSTEM = 0,
 | 
				
			||||||
 | 
					                        SIM_OSC32KSEL_RTC = 2,
 | 
				
			||||||
 | 
					                        SIM_OSC32KSEL_LPO = 3
 | 
				
			||||||
 | 
					                } osc32ksel : 2;
 | 
				
			||||||
 | 
					                uint32_t _rsvd2 : 9;
 | 
				
			||||||
 | 
					                uint32_t usbvstby : 1;
 | 
				
			||||||
 | 
					                uint32_t usbsstby : 1;
 | 
				
			||||||
 | 
					                uint32_t usbregen : 1;
 | 
				
			||||||
 | 
					                UNION_STRUCT_END;
 | 
				
			||||||
 | 
					        } sopt1;
 | 
				
			||||||
 | 
					        struct SIM_SOPT1CFG_t {
 | 
				
			||||||
 | 
					                UNION_STRUCT_START(32);
 | 
				
			||||||
 | 
					                uint32_t _rsvd0 : 24;
 | 
				
			||||||
 | 
					                uint32_t urwe : 1;
 | 
				
			||||||
 | 
					                uint32_t uvswe : 1;
 | 
				
			||||||
 | 
					                uint32_t usswe : 1;
 | 
				
			||||||
 | 
					                uint32_t _rsvd1 : 5;
 | 
				
			||||||
 | 
					                UNION_STRUCT_END;
 | 
				
			||||||
 | 
					        } sopt1cfg;
 | 
				
			||||||
 | 
					        uint32_t _pad0[(0x1004 - 0x8) / 4];
 | 
				
			||||||
 | 
					        struct SIM_SOPT2_t {
 | 
				
			||||||
 | 
					                UNION_STRUCT_START(32);
 | 
				
			||||||
 | 
					                uint32_t _rsvd0 : 4;
 | 
				
			||||||
 | 
					                enum {
 | 
				
			||||||
 | 
					                        SIM_RTCCLKOUTSEL_1HZ = 0,
 | 
				
			||||||
 | 
					                        SIM_RTCCLKOUTSEL_32KHZ = 1
 | 
				
			||||||
 | 
					                } rtcclkoutsel : 1;
 | 
				
			||||||
 | 
					                enum {
 | 
				
			||||||
 | 
					                        SIM_CLKOUTSEL_FLASH = 2,
 | 
				
			||||||
 | 
					                        SIM_CLKOUTSEL_LPO = 3,
 | 
				
			||||||
 | 
					                        SIM_CLKOUTSEL_MCG = 4,
 | 
				
			||||||
 | 
					                        SIM_CLKOUTSEL_RTC = 5,
 | 
				
			||||||
 | 
					                        SIM_CLKOUTSEL_OSC = 6
 | 
				
			||||||
 | 
					                } clkoutsel : 3;
 | 
				
			||||||
 | 
					                uint32_t _rsvd1 : 3;
 | 
				
			||||||
 | 
					                enum {
 | 
				
			||||||
 | 
					                        SIM_PTD7PAD_SINGLE = 0,
 | 
				
			||||||
 | 
					                        SIM_PTD7PAD_DOUBLE = 1
 | 
				
			||||||
 | 
					                } ptd7pad : 1;
 | 
				
			||||||
 | 
					                enum {
 | 
				
			||||||
 | 
					                        SIM_TRACECLKSEL_MCG = 0,
 | 
				
			||||||
 | 
					                        SIM_TRACECLKSEL_CORE = 1
 | 
				
			||||||
 | 
					                } traceclksel : 1;
 | 
				
			||||||
 | 
					                uint32_t _rsvd2 : 3;
 | 
				
			||||||
 | 
					                enum {
 | 
				
			||||||
 | 
					                        SIM_PLLFLLSEL_FLL = 0,
 | 
				
			||||||
 | 
					                        SIM_PLLFLLSEL_PLL = 1
 | 
				
			||||||
 | 
					                } pllfllsel : 1;
 | 
				
			||||||
 | 
					                uint32_t _rsvd3 : 1;
 | 
				
			||||||
 | 
					                enum {
 | 
				
			||||||
 | 
					                        SIM_USBSRC_EXTERNAL = 0,
 | 
				
			||||||
 | 
					                        SIM_USBSRC_MCG = 1
 | 
				
			||||||
 | 
					                } usbsrc : 1;
 | 
				
			||||||
 | 
					                uint32_t _rsvd4 : 13;
 | 
				
			||||||
 | 
					                UNION_STRUCT_END;
 | 
				
			||||||
 | 
					        } sopt2;
 | 
				
			||||||
 | 
					        uint32_t _pad1;
 | 
				
			||||||
 | 
					        struct SIM_SOPT4_t {
 | 
				
			||||||
 | 
					                UNION_STRUCT_START(32);
 | 
				
			||||||
 | 
					                enum sim_ftmflt {
 | 
				
			||||||
 | 
					                        SIM_FTMFLT_FTM = 0,
 | 
				
			||||||
 | 
					                        SIM_FTMFLT_CMP = 1
 | 
				
			||||||
 | 
					                } ftm0flt0 : 1;
 | 
				
			||||||
 | 
					                enum sim_ftmflt ftm0flt1 : 1;
 | 
				
			||||||
 | 
					                uint32_t _rsvd0 : 2;
 | 
				
			||||||
 | 
					                enum sim_ftmflt ftm1flt0 : 1;
 | 
				
			||||||
 | 
					                uint32_t _rsvd1 : 13;
 | 
				
			||||||
 | 
					                enum {
 | 
				
			||||||
 | 
					                        SIM_FTMCHSRC_FTM = 0,
 | 
				
			||||||
 | 
					                        SIM_FTMCHSRC_CMP0 = 1,
 | 
				
			||||||
 | 
					                        SIM_FTMCHSRC_CMP1 = 2,
 | 
				
			||||||
 | 
					                        SIM_FTMCHSRC_USBSOF = 3
 | 
				
			||||||
 | 
					                } ftm1ch0src : 2;
 | 
				
			||||||
 | 
					                uint32_t _rsvd2 : 4;
 | 
				
			||||||
 | 
					                enum sim_ftmclksel {
 | 
				
			||||||
 | 
					                        SIM_FTMCLKSEL_CLK0 = 0,
 | 
				
			||||||
 | 
					                        SIM_FTMCLKSEL_CLK1 = 1
 | 
				
			||||||
 | 
					                } ftm0clksel : 1;
 | 
				
			||||||
 | 
					                enum sim_ftmclksel ftm1clksel : 1;
 | 
				
			||||||
 | 
					                uint32_t _rsvd3 : 2;
 | 
				
			||||||
 | 
					                enum {
 | 
				
			||||||
 | 
					                        SIM_FTMTRGSRC_HSCMP0 = 0,
 | 
				
			||||||
 | 
					                        SIM_FTMTRGSRC_FTM1 = 1
 | 
				
			||||||
 | 
					                } ftm0trg0src : 1;
 | 
				
			||||||
 | 
					                uint32_t _rsvd4 : 3;
 | 
				
			||||||
 | 
					                UNION_STRUCT_END;
 | 
				
			||||||
 | 
					        } sopt4;
 | 
				
			||||||
 | 
					        struct SIM_SOPT5_t {
 | 
				
			||||||
 | 
					                UNION_STRUCT_START(32);
 | 
				
			||||||
 | 
					                enum sim_uarttxsrc {
 | 
				
			||||||
 | 
					                        SIM_UARTTXSRC_UART = 0,
 | 
				
			||||||
 | 
					                        SIM_UARTTXSRC_FTM = 1
 | 
				
			||||||
 | 
					                } uart0txsrc : 1;
 | 
				
			||||||
 | 
					                uint32_t _rsvd0 : 1;
 | 
				
			||||||
 | 
					                enum sim_uartrxsrc {
 | 
				
			||||||
 | 
					                        SIM_UARTRXSRC_UART = 0,
 | 
				
			||||||
 | 
					                        SIM_UARTRXSRC_CMP0 = 1,
 | 
				
			||||||
 | 
					                        SIM_UARTRXSRC_CMP1 = 2
 | 
				
			||||||
 | 
					                } uart0rxsrc : 2;
 | 
				
			||||||
 | 
					                enum sim_uarttxsrc uart1txsrc : 1;
 | 
				
			||||||
 | 
					                uint32_t _rsvd1 : 1;
 | 
				
			||||||
 | 
					                enum sim_uartrxsrc uart1rxsrc : 2;
 | 
				
			||||||
 | 
					                uint32_t _rsvd2 : 24;
 | 
				
			||||||
 | 
					                UNION_STRUCT_END;
 | 
				
			||||||
 | 
					        } sopt5;
 | 
				
			||||||
 | 
					        uint32_t _pad2;
 | 
				
			||||||
 | 
					        struct SIM_SOPT7_t {
 | 
				
			||||||
 | 
					                UNION_STRUCT_START(32);
 | 
				
			||||||
 | 
					                enum {
 | 
				
			||||||
 | 
					                        SIM_ADCTRGSEL_PDB = 0,
 | 
				
			||||||
 | 
					                        SIM_ADCTRGSEL_HSCMP0 = 1,
 | 
				
			||||||
 | 
					                        SIM_ADCTRGSEL_HSCMP1 = 2,
 | 
				
			||||||
 | 
					                        SIM_ADCTRGSEL_PIT0 = 4,
 | 
				
			||||||
 | 
					                        SIM_ADCTRGSEL_PIT1 = 5,
 | 
				
			||||||
 | 
					                        SIM_ADCTRGSEL_PIT2 = 6,
 | 
				
			||||||
 | 
					                        SIM_ADCTRGSEL_PIT3 = 7,
 | 
				
			||||||
 | 
					                        SIM_ADCTRGSEL_FTM0 = 8,
 | 
				
			||||||
 | 
					                        SIM_ADCTRGSEL_FTM1 = 9,
 | 
				
			||||||
 | 
					                        SIM_ADCTRGSEL_RTCALARM = 12,
 | 
				
			||||||
 | 
					                        SIM_ADCTRGSEL_RTCSECS = 13,
 | 
				
			||||||
 | 
					                        SIM_ADCTRGSEL_LPTIMER = 14
 | 
				
			||||||
 | 
					                } adc0trgsel : 4;
 | 
				
			||||||
 | 
					                enum {
 | 
				
			||||||
 | 
					                        SIM_ADCPRETRGSEL_A = 0,
 | 
				
			||||||
 | 
					                        SIM_ADCPRETRGSEL_B = 1
 | 
				
			||||||
 | 
					                } adc0pretrgsel : 1;
 | 
				
			||||||
 | 
					                uint32_t _rsvd0 : 2;
 | 
				
			||||||
 | 
					                enum {
 | 
				
			||||||
 | 
					                        SIM_ADCALTTRGEN_PDB = 0,
 | 
				
			||||||
 | 
					                        SIM_ADCALTTRGEN_ALT = 1
 | 
				
			||||||
 | 
					                } adc0alttrgen : 1;
 | 
				
			||||||
 | 
					                uint32_t _rsvd1 : 24;
 | 
				
			||||||
 | 
					                UNION_STRUCT_END;
 | 
				
			||||||
 | 
					        } sopt7;
 | 
				
			||||||
 | 
					        uint32_t _pad3[(0x1024 - 0x101c) / 4];
 | 
				
			||||||
 | 
					        struct SIM_SDID_t {
 | 
				
			||||||
 | 
					                UNION_STRUCT_START(32);
 | 
				
			||||||
 | 
					                enum {
 | 
				
			||||||
 | 
					                        SIM_PINID_32 = 2,
 | 
				
			||||||
 | 
					                        SIM_PINID_48 = 4,
 | 
				
			||||||
 | 
					                        SIM_PINID_64 = 5
 | 
				
			||||||
 | 
					                } pinid : 4;
 | 
				
			||||||
 | 
					                enum {
 | 
				
			||||||
 | 
					                        SIM_FAMID_K10 = 0,
 | 
				
			||||||
 | 
					                        SIM_FAMID_K20 = 1
 | 
				
			||||||
 | 
					                } famid : 3;
 | 
				
			||||||
 | 
					                uint32_t _rsvd1 : 5;
 | 
				
			||||||
 | 
					                uint32_t revid : 4;
 | 
				
			||||||
 | 
					                uint32_t _rsvd2 : 16;
 | 
				
			||||||
 | 
					                UNION_STRUCT_END;
 | 
				
			||||||
 | 
					        } sdid;
 | 
				
			||||||
 | 
					        uint32_t _pad4[(0x1034 - 0x1028) / 4];
 | 
				
			||||||
 | 
					        struct SIM_SCGC4_t {
 | 
				
			||||||
 | 
					                UNION_STRUCT_START(32);
 | 
				
			||||||
 | 
					                uint32_t _rsvd0 : 1;
 | 
				
			||||||
 | 
					                uint32_t ewm : 1;
 | 
				
			||||||
 | 
					                uint32_t cmt : 1;
 | 
				
			||||||
 | 
					                uint32_t _rsvd1 : 3;
 | 
				
			||||||
 | 
					                uint32_t i2c0 : 1;
 | 
				
			||||||
 | 
					                uint32_t _rsvd2 : 3;
 | 
				
			||||||
 | 
					                uint32_t uart0 : 1;
 | 
				
			||||||
 | 
					                uint32_t uart1 : 1;
 | 
				
			||||||
 | 
					                uint32_t uart2 : 1;
 | 
				
			||||||
 | 
					                uint32_t _rsvd3 : 5;
 | 
				
			||||||
 | 
					                uint32_t usbotg : 1;
 | 
				
			||||||
 | 
					                uint32_t cmp : 1;
 | 
				
			||||||
 | 
					                uint32_t vref : 1;
 | 
				
			||||||
 | 
					                uint32_t _rsvd4 : 11;
 | 
				
			||||||
 | 
					                UNION_STRUCT_END;
 | 
				
			||||||
 | 
					        } scgc4;
 | 
				
			||||||
 | 
					        struct SIM_SCGC5_t {
 | 
				
			||||||
 | 
					                UNION_STRUCT_START(32);
 | 
				
			||||||
 | 
					                uint32_t lptimer : 1;
 | 
				
			||||||
 | 
					                uint32_t _rsvd0 : 4;
 | 
				
			||||||
 | 
					                uint32_t tsi : 1;
 | 
				
			||||||
 | 
					                uint32_t _rsvd1 : 3;
 | 
				
			||||||
 | 
					                uint32_t porta : 1;
 | 
				
			||||||
 | 
					                uint32_t portb : 1;
 | 
				
			||||||
 | 
					                uint32_t portc : 1;
 | 
				
			||||||
 | 
					                uint32_t portd : 1;
 | 
				
			||||||
 | 
					                uint32_t porte : 1;
 | 
				
			||||||
 | 
					                uint32_t _rsvd2 : 18;
 | 
				
			||||||
 | 
					                UNION_STRUCT_END;
 | 
				
			||||||
 | 
					        } scgc5;
 | 
				
			||||||
 | 
					        struct SIM_SCGC6_t {
 | 
				
			||||||
 | 
					                UNION_STRUCT_START(32);
 | 
				
			||||||
 | 
					                uint32_t ftfl : 1;
 | 
				
			||||||
 | 
					                uint32_t dmamux : 1;
 | 
				
			||||||
 | 
					                uint32_t _rsvd0 : 10;
 | 
				
			||||||
 | 
					                uint32_t spi0 : 1;
 | 
				
			||||||
 | 
					                uint32_t _rsvd1 : 2;
 | 
				
			||||||
 | 
					                uint32_t i2s : 1;
 | 
				
			||||||
 | 
					                uint32_t _rsvd2 : 2;
 | 
				
			||||||
 | 
					                uint32_t crc : 1;
 | 
				
			||||||
 | 
					                uint32_t _rsvd3 : 2;
 | 
				
			||||||
 | 
					                uint32_t usbdcd : 1;
 | 
				
			||||||
 | 
					                uint32_t pdb : 1;
 | 
				
			||||||
 | 
					                uint32_t pit : 1;
 | 
				
			||||||
 | 
					                uint32_t ftm0 : 1;
 | 
				
			||||||
 | 
					                uint32_t ftm1 : 1;
 | 
				
			||||||
 | 
					                uint32_t _rsvd4 : 1;
 | 
				
			||||||
 | 
					                uint32_t adc0 : 1;
 | 
				
			||||||
 | 
					                uint32_t _rsvd5 : 1;
 | 
				
			||||||
 | 
					                uint32_t rtc : 1;
 | 
				
			||||||
 | 
					                uint32_t _rsvd6 : 2;
 | 
				
			||||||
 | 
					                UNION_STRUCT_END;
 | 
				
			||||||
 | 
					        } scgc6;
 | 
				
			||||||
 | 
					        struct SIM_SCGC7_t {
 | 
				
			||||||
 | 
					                UNION_STRUCT_START(32);
 | 
				
			||||||
 | 
					                uint32_t _rsvd0 : 1;
 | 
				
			||||||
 | 
					                uint32_t dma : 1;
 | 
				
			||||||
 | 
					                uint32_t _rsvd1 : 30;
 | 
				
			||||||
 | 
					                UNION_STRUCT_END;
 | 
				
			||||||
 | 
					        } scgc7;
 | 
				
			||||||
 | 
					        struct SIM_CLKDIV1_t {
 | 
				
			||||||
 | 
					                UNION_STRUCT_START(32);
 | 
				
			||||||
 | 
					                uint32_t _rsvd0 : 16;
 | 
				
			||||||
 | 
					                uint32_t outdiv4 : 4;
 | 
				
			||||||
 | 
					                uint32_t _rsvd1 : 4;
 | 
				
			||||||
 | 
					                uint32_t outdiv2 : 4;
 | 
				
			||||||
 | 
					                uint32_t outdiv1 : 4;
 | 
				
			||||||
 | 
					                UNION_STRUCT_END;
 | 
				
			||||||
 | 
					        } clkdiv1;
 | 
				
			||||||
 | 
					        struct SIM_CLKDIV2_t {
 | 
				
			||||||
 | 
					                UNION_STRUCT_START(32);
 | 
				
			||||||
 | 
					                uint32_t usbfrac : 1;
 | 
				
			||||||
 | 
					                uint32_t usbdiv : 3;
 | 
				
			||||||
 | 
					                uint32_t _rsvd0 : 28;
 | 
				
			||||||
 | 
					                UNION_STRUCT_END;
 | 
				
			||||||
 | 
					        } clkdiv2;
 | 
				
			||||||
 | 
					        struct SIM_FCFG1_t {
 | 
				
			||||||
 | 
					                UNION_STRUCT_START(32);
 | 
				
			||||||
 | 
					                uint32_t flashdis : 1;
 | 
				
			||||||
 | 
					                uint32_t flashdoze : 1;
 | 
				
			||||||
 | 
					                uint32_t _rsvd0 : 6;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                /* the following enum is analogous to enum
 | 
				
			||||||
 | 
					                 * FTFL_FLEXNVM_PARTITION in ftfl.h, but that one is padded
 | 
				
			||||||
 | 
					                 * with four 1-bits to make an 8-bit value.
 | 
				
			||||||
 | 
					                 */
 | 
				
			||||||
 | 
					                enum SIM_FLEXNVM_PARTITION {
 | 
				
			||||||
 | 
					                        SIM_FLEXNVM_DATA_32_EEPROM_0  = 0x0,
 | 
				
			||||||
 | 
					                        SIM_FLEXNVM_DATA_24_EEPROM_8  = 0x1,
 | 
				
			||||||
 | 
					                        SIM_FLEXNVM_DATA_16_EEPROM_16 = 0x2,
 | 
				
			||||||
 | 
					                        SIM_FLEXNVM_DATA_8_EEPROM_24  = 0x9,
 | 
				
			||||||
 | 
					                        SIM_FLEXNVM_DATA_0_EEPROM_32  = 0x3
 | 
				
			||||||
 | 
					                } depart : 4;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                uint32_t _rsvd1 : 4;
 | 
				
			||||||
 | 
					                enum {
 | 
				
			||||||
 | 
					                        SIM_EESIZE_2KB = 3,
 | 
				
			||||||
 | 
					                        SIM_EESIZE_1KB = 4,
 | 
				
			||||||
 | 
					                        SIM_EESIZE_512B = 5,
 | 
				
			||||||
 | 
					                        SIM_EESIZE_256B = 6,
 | 
				
			||||||
 | 
					                        SIM_EESIZE_128B = 7,
 | 
				
			||||||
 | 
					                        SIM_EESIZE_64B = 8,
 | 
				
			||||||
 | 
					                        SIM_EESIZE_32B = 9,
 | 
				
			||||||
 | 
					                        SIM_EESIZE_0B = 15
 | 
				
			||||||
 | 
					                } eesize : 4;
 | 
				
			||||||
 | 
					                uint32_t _rsvd2 : 4;
 | 
				
			||||||
 | 
					                enum {
 | 
				
			||||||
 | 
					                        SIM_PFSIZE_32KB = 3,
 | 
				
			||||||
 | 
					                        SIM_PFSIZE_64KB = 5,
 | 
				
			||||||
 | 
					                        SIM_PFSIZE_128KB = 7
 | 
				
			||||||
 | 
					                } pfsize : 4;
 | 
				
			||||||
 | 
					                enum {
 | 
				
			||||||
 | 
					                        SIM_NVMSIZE_0KB = 0,
 | 
				
			||||||
 | 
					                        SIM_NVMSIZE_32KB = 3
 | 
				
			||||||
 | 
					                } nvmsize : 4;
 | 
				
			||||||
 | 
					                UNION_STRUCT_END;
 | 
				
			||||||
 | 
					        } fcfg1;
 | 
				
			||||||
 | 
					        struct SIM_FCFG2_t {
 | 
				
			||||||
 | 
					                UNION_STRUCT_START(32);
 | 
				
			||||||
 | 
					                uint32_t _rsvd0 : 16;
 | 
				
			||||||
 | 
					                uint32_t maxaddr1 : 7;
 | 
				
			||||||
 | 
					                enum {
 | 
				
			||||||
 | 
					                        SIM_PFLSH_FLEXNVM = 0,
 | 
				
			||||||
 | 
					                        SIM_PFLSH_PROGRAM = 1
 | 
				
			||||||
 | 
					                } pflsh : 1;
 | 
				
			||||||
 | 
					                uint32_t maxaddr0 : 7;
 | 
				
			||||||
 | 
					                uint32_t _rsvd1 : 1;
 | 
				
			||||||
 | 
					                UNION_STRUCT_END;
 | 
				
			||||||
 | 
					        } fcfg2;
 | 
				
			||||||
 | 
					        uint32_t uidh;
 | 
				
			||||||
 | 
					        uint32_t uidmh;
 | 
				
			||||||
 | 
					        uint32_t uidml;
 | 
				
			||||||
 | 
					        uint32_t uidl;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					CTASSERT_SIZE_BYTE(struct SIM_t, 0x1064);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					extern volatile struct SIM_t SIM;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							
								
								
									
										60
									
								
								Bootloader/usb-common.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										60
									
								
								Bootloader/usb-common.h
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,60 @@
 | 
				
			||||||
 | 
					/* Copyright (c) 2011,2012 Simon Schubert <2@0x2c.org>.
 | 
				
			||||||
 | 
					 * Modifications by Jacob Alexander 2014 <haata@kiibohd.com>
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * 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/>.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef _USB_COMMON_H
 | 
				
			||||||
 | 
					#define _USB_COMMON_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ----- Enumerations -----
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * USB request data structures.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					enum usb_tok_pid {
 | 
				
			||||||
 | 
						USB_PID_TIMEOUT = 0,
 | 
				
			||||||
 | 
						USB_PID_OUT = 1,
 | 
				
			||||||
 | 
						USB_PID_ACK = 2,
 | 
				
			||||||
 | 
						USB_PID_DATA0 = 3,
 | 
				
			||||||
 | 
						USB_PID_IN = 9,
 | 
				
			||||||
 | 
						USB_PID_NAK = 10,
 | 
				
			||||||
 | 
						USB_PID_DATA1 = 11,
 | 
				
			||||||
 | 
						USB_PID_SETUP = 13,
 | 
				
			||||||
 | 
						USB_PID_STALL = 14,
 | 
				
			||||||
 | 
						USB_PID_DATAERR = 15
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					enum usb_ep_pingpong {
 | 
				
			||||||
 | 
						USB_EP_PINGPONG_EVEN = 0,
 | 
				
			||||||
 | 
						USB_EP_PINGPONG_ODD = 1
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					enum usb_ep_dir {
 | 
				
			||||||
 | 
						USB_EP_RX = 0,
 | 
				
			||||||
 | 
						USB_EP_TX = 1
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					enum usb_data01 {
 | 
				
			||||||
 | 
						USB_DATA01_DATA0 = 0,
 | 
				
			||||||
 | 
						USB_DATA01_DATA1 = 1
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					enum {
 | 
				
			||||||
 | 
						EP0_BUFSIZE = 64
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							
								
								
									
										104
									
								
								Bootloader/usb-internal.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										104
									
								
								Bootloader/usb-internal.h
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,104 @@
 | 
				
			||||||
 | 
					/* Copyright (c) 2011,2012 Simon Schubert <2@0x2c.org>.
 | 
				
			||||||
 | 
					 * Modifications by Jacob Alexander 2014 <haata@kiibohd.com>
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * 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/>.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef __USB_INTERNAL_H
 | 
				
			||||||
 | 
					#define __USB_INTERNAL_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Internal driver structures
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * USB state machine
 | 
				
			||||||
 | 
					 * =================
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Device configuration states:
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Attached <-> Powered
 | 
				
			||||||
 | 
					 * Powered -(reset)-> Default
 | 
				
			||||||
 | 
					 * Default -(SET_ADDRESS)-> Address
 | 
				
			||||||
 | 
					 * Address -(SET_CONFIGURATION)-> Configured
 | 
				
			||||||
 | 
					 * Configured -(SET_CONFIGURATION 0)-> Address
 | 
				
			||||||
 | 
					 * Address -(SET_ADDRESS 0)-> Default
 | 
				
			||||||
 | 
					 * [Default, Configured, Address] -(reset)-> Default
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ----- Defines -----
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef USB_MAX_EP
 | 
				
			||||||
 | 
					#define USB_MAX_EP 16
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ----- Structs -----
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct usbd_ep_pipe_state_t {
 | 
				
			||||||
 | 
						enum usb_ep_pingpong pingpong; /* next desc to use */
 | 
				
			||||||
 | 
						enum usb_data01 data01;
 | 
				
			||||||
 | 
						size_t transfer_size;
 | 
				
			||||||
 | 
						size_t pos;
 | 
				
			||||||
 | 
						uint8_t *data_buf;
 | 
				
			||||||
 | 
						const uint8_t *copy_source;
 | 
				
			||||||
 | 
						int short_transfer;
 | 
				
			||||||
 | 
						ep_callback_t callback;
 | 
				
			||||||
 | 
						void *callback_data;
 | 
				
			||||||
 | 
						size_t ep_maxsize;
 | 
				
			||||||
 | 
						/* constant */
 | 
				
			||||||
 | 
						int ep_num;
 | 
				
			||||||
 | 
						enum usb_ep_dir ep_dir;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct usbd_ep_state_t {
 | 
				
			||||||
 | 
						union {
 | 
				
			||||||
 | 
							struct usbd_ep_pipe_state_t pipe[2];
 | 
				
			||||||
 | 
							struct {
 | 
				
			||||||
 | 
								struct usbd_ep_pipe_state_t rx;
 | 
				
			||||||
 | 
								struct usbd_ep_pipe_state_t tx;
 | 
				
			||||||
 | 
							};
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct usbd_t {
 | 
				
			||||||
 | 
						struct usbd_function_ctx_header functions;
 | 
				
			||||||
 | 
						struct usbd_function control_function;
 | 
				
			||||||
 | 
						const struct usbd_device *identity;
 | 
				
			||||||
 | 
						int address;
 | 
				
			||||||
 | 
						int config;
 | 
				
			||||||
 | 
						enum usbd_dev_state {
 | 
				
			||||||
 | 
							USBD_STATE_DISABLED = 0,
 | 
				
			||||||
 | 
							USBD_STATE_DEFAULT,
 | 
				
			||||||
 | 
							USBD_STATE_SETTING_ADDRESS,
 | 
				
			||||||
 | 
							USBD_STATE_ADDRESS,
 | 
				
			||||||
 | 
							USBD_STATE_CONFIGURED
 | 
				
			||||||
 | 
						} state;
 | 
				
			||||||
 | 
						enum usb_ctrl_req_dir ctrl_dir;
 | 
				
			||||||
 | 
						struct usbd_ep_state_t ep_state[USB_MAX_EP];
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					extern struct usbd_t usb;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ----- Functions -----
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void usb_restart(void);
 | 
				
			||||||
 | 
					void usb_enable(void);
 | 
				
			||||||
 | 
					const struct usbd_config *usb_get_config_data(int config);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							
								
								
									
										590
									
								
								Bootloader/usb.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										590
									
								
								Bootloader/usb.c
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,590 @@
 | 
				
			||||||
 | 
					/* Copyright (c) 2011,2012 Simon Schubert <2@0x2c.org>.
 | 
				
			||||||
 | 
					 * Modifications by Jacob Alexander 2014 <haata@kiibohd.com>
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * 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/>.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ----- Compiler Includes -----
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <sys/types.h>
 | 
				
			||||||
 | 
					#include <inttypes.h>
 | 
				
			||||||
 | 
					#include <string.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ----- Local Includes -----
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "usb.h"
 | 
				
			||||||
 | 
					#include "usb-internal.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ----- Variables -----
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static uint8_t ep0_buf[2][EP0_BUFSIZE] __attribute__((aligned(4)));
 | 
				
			||||||
 | 
					struct usbd_t usb;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ----- Functions -----
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Returns: 0 when this is was the last transfer, 1 if there is still
 | 
				
			||||||
 | 
					 * more to go.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					/* Defaults to EP0 for now */
 | 
				
			||||||
 | 
					static int usb_tx_next(struct usbd_ep_pipe_state_t *s)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * Us being here means the previous transfer just completed
 | 
				
			||||||
 | 
						 * successfully.  That means the host just toggled its data
 | 
				
			||||||
 | 
						 * sync bit, and so do we.
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						s->data01 ^= 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (s->transfer_size > 0) {
 | 
				
			||||||
 | 
							size_t thislen = s->transfer_size;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (thislen > s->ep_maxsize)
 | 
				
			||||||
 | 
								thislen = s->ep_maxsize;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							void *addr = s->data_buf + s->pos;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (s->copy_source) {
 | 
				
			||||||
 | 
								/* Bounce buffer mode */
 | 
				
			||||||
 | 
								addr = s->data_buf;
 | 
				
			||||||
 | 
								memcpy(addr, s->copy_source + s->pos, thislen);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							s->pos += thislen;
 | 
				
			||||||
 | 
							s->transfer_size -= thislen;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							usb_queue_next(s, addr, thislen);
 | 
				
			||||||
 | 
							s->pingpong ^= 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							return (1);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * All data has been shipped.  Do we need to send a short
 | 
				
			||||||
 | 
						 * packet?
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						if (s->short_transfer) {
 | 
				
			||||||
 | 
							s->short_transfer = 0;
 | 
				
			||||||
 | 
							usb_queue_next(s, NULL, 0);
 | 
				
			||||||
 | 
							s->pingpong ^= 1;
 | 
				
			||||||
 | 
							return (1);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (s->callback)
 | 
				
			||||||
 | 
							s->callback(s->data_buf, s->pos, s->callback_data);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return (0);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void setup_tx(struct usbd_ep_pipe_state_t *s, const void *buf, size_t len, size_t reqlen, ep_callback_t cb, void *cb_data)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						s->data_buf = (void *)buf;
 | 
				
			||||||
 | 
						s->copy_source = NULL;
 | 
				
			||||||
 | 
						s->transfer_size = len;
 | 
				
			||||||
 | 
						s->pos = 0;
 | 
				
			||||||
 | 
						s->callback = cb;
 | 
				
			||||||
 | 
						s->callback_data = cb_data;
 | 
				
			||||||
 | 
						if (s->transfer_size > reqlen)
 | 
				
			||||||
 | 
							s->transfer_size = reqlen;
 | 
				
			||||||
 | 
						if (s->transfer_size < reqlen && s->transfer_size % s->ep_maxsize == 0)
 | 
				
			||||||
 | 
							s->short_transfer = 1;
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
							s->short_transfer = 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void submit_tx(struct usbd_ep_pipe_state_t *s)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						/* usb_tx_next() flips the data toggle, so invert this here. */
 | 
				
			||||||
 | 
						s->data01 ^= 1;
 | 
				
			||||||
 | 
						usb_tx_next(s);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * send USB data (IN device transaction)
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * So far this function is specialized for EP 0 only.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Returns: size to be transfered, or -1 on error.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					int usb_tx(struct usbd_ep_pipe_state_t *s, const void *buf, size_t len, size_t reqlen, ep_callback_t cb, void *cb_data)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						setup_tx(s, buf, len, reqlen, cb, cb_data);
 | 
				
			||||||
 | 
						submit_tx(s);
 | 
				
			||||||
 | 
						return (s->transfer_size);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Returns: 0 when this is was the last transfer, 1 if there is still
 | 
				
			||||||
 | 
					 * more to go.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					/* Defaults to EP0 for now */
 | 
				
			||||||
 | 
					/* XXX pass usb_stat to validate pingpong */
 | 
				
			||||||
 | 
					static int usb_rx_next(struct usbd_ep_pipe_state_t *s)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * Us being here means the previous transfer just completed
 | 
				
			||||||
 | 
						 * successfully.  That means the host just toggled its data
 | 
				
			||||||
 | 
						 * sync bit, and so do we.
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						s->data01 ^= 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						size_t thislen = usb_ep_get_transfer_size(s);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						s->transfer_size -= thislen;
 | 
				
			||||||
 | 
						s->pos += thislen;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * We're done with this buffer now.  Switch the pingpong now
 | 
				
			||||||
 | 
						 * before we might have to receive the next piece of data.
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						s->pingpong ^= 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * If this is a short transfer, or we received what we
 | 
				
			||||||
 | 
						 * expected, we're done.
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						if (thislen < s->ep_maxsize || s->transfer_size == 0) {
 | 
				
			||||||
 | 
							if (s->callback)
 | 
				
			||||||
 | 
								s->callback(s->data_buf, s->pos, s->callback_data);
 | 
				
			||||||
 | 
							return (0);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * Otherwise we still need to receive more data.
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						size_t nextlen = s->transfer_size;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (nextlen > s->ep_maxsize)
 | 
				
			||||||
 | 
					                nextlen = s->ep_maxsize;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        void *addr = s->data_buf + s->pos;
 | 
				
			||||||
 | 
						usb_queue_next(s, addr, nextlen);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return (1);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Receive USB data (OUT device transaction)
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Returns: size to be received, or -1 on error.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					int usb_rx(struct usbd_ep_pipe_state_t *s, void *buf, size_t len, ep_callback_t cb, void *cb_data)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						s->data_buf = buf;
 | 
				
			||||||
 | 
						s->transfer_size = len;
 | 
				
			||||||
 | 
						s->pos = 0;
 | 
				
			||||||
 | 
						s->callback = cb;
 | 
				
			||||||
 | 
						s->callback_data = cb_data;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						size_t thislen = s->transfer_size;
 | 
				
			||||||
 | 
						if (thislen > s->ep_maxsize)
 | 
				
			||||||
 | 
							thislen = s->ep_maxsize;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						usb_queue_next(s, s->data_buf, thislen);
 | 
				
			||||||
 | 
						return (len);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int usb_ep0_tx_cp(const void *buf, size_t len, size_t reqlen, ep_callback_t cb, void *cb_data)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct usbd_ep_pipe_state_t *s = &usb.ep_state[0].tx;
 | 
				
			||||||
 | 
						enum usb_ep_pingpong pp = s->pingpong;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						setup_tx(s, ep0_buf[pp], len, reqlen, cb, cb_data);
 | 
				
			||||||
 | 
						s->copy_source = buf;
 | 
				
			||||||
 | 
						submit_tx(s);
 | 
				
			||||||
 | 
						return (s->transfer_size);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void *usb_ep0_tx_inplace_prepare(size_t len)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						enum usb_ep_pingpong pp = usb.ep_state[0].tx.pingpong;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (len > EP0_BUFSIZE)
 | 
				
			||||||
 | 
							return (NULL);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return (ep0_buf[pp]);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int usb_ep0_tx(void *buf, size_t len, size_t reqlen, ep_callback_t cb, void *cb_data)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return (usb_tx(&usb.ep_state[0].tx, buf, len, reqlen, cb, cb_data));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int usb_ep0_rx(void *buf, size_t len, ep_callback_t cb, void *cb_data)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return (usb_rx(&usb.ep_state[0].rx, buf, len, cb, cb_data));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const struct usbd_config *
 | 
				
			||||||
 | 
					usb_get_config_data(int config)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						if (config <= 0)
 | 
				
			||||||
 | 
							config = usb.config;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (config != 0)
 | 
				
			||||||
 | 
							return (usb.identity->configs[config - 1]);
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
							return (NULL);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int usb_set_config(int config)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						const struct usbd_config *config_data;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (usb.config != 0) {
 | 
				
			||||||
 | 
							config_data = usb_get_config_data(-1);
 | 
				
			||||||
 | 
							if (config_data != NULL && config_data->init != NULL)
 | 
				
			||||||
 | 
								config_data->init(0);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (config != 0) {
 | 
				
			||||||
 | 
							/* XXX overflow */
 | 
				
			||||||
 | 
							config_data = usb_get_config_data(config);
 | 
				
			||||||
 | 
							if (config_data != NULL && config_data->init != NULL)
 | 
				
			||||||
 | 
								config_data->init(1);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						usb.config = config;
 | 
				
			||||||
 | 
						return (0);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int usb_set_interface(int iface, int altsetting)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int iface_count = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for (struct usbd_function_ctx_header *fh = &usb.functions;
 | 
				
			||||||
 | 
						     fh != NULL;
 | 
				
			||||||
 | 
						     fh = fh->next, iface_count += fh->function->interface_count) {
 | 
				
			||||||
 | 
							if (iface - iface_count < fh->function->interface_count) {
 | 
				
			||||||
 | 
								if (fh->function->configure != NULL)
 | 
				
			||||||
 | 
									return (fh->function->configure(iface,
 | 
				
			||||||
 | 
													iface - iface_count,
 | 
				
			||||||
 | 
													altsetting,
 | 
				
			||||||
 | 
													fh));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								/* Default to a single altsetting */
 | 
				
			||||||
 | 
								if (altsetting != 0)
 | 
				
			||||||
 | 
									return (-1);
 | 
				
			||||||
 | 
								else
 | 
				
			||||||
 | 
									return (0);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return (-1);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int usb_tx_config_desc(int idx, int reqlen)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						const struct usb_desc_config_t *d = usb.identity->configs[idx]->desc;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						usb_ep0_tx_cp(d, d->wTotalLength, reqlen, NULL, NULL);
 | 
				
			||||||
 | 
						return (0);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int usb_tx_string_desc(int idx, int reqlen)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						const struct usb_desc_string_t * const *d;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for (d = usb.identity->string_descs; idx != 0 && *d != NULL; ++d)
 | 
				
			||||||
 | 
							--idx;
 | 
				
			||||||
 | 
						switch ((uintptr_t)*d) {
 | 
				
			||||||
 | 
						case (uintptr_t)NULL:
 | 
				
			||||||
 | 
							return (-1);
 | 
				
			||||||
 | 
						case (uintptr_t)USB_DESC_STRING_SERIALNO:
 | 
				
			||||||
 | 
							return (usb_tx_serialno(reqlen));
 | 
				
			||||||
 | 
						default:
 | 
				
			||||||
 | 
							usb_ep0_tx_cp(*d, (*d)->bLength, reqlen, NULL, NULL);
 | 
				
			||||||
 | 
							return (0);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void usb_handle_control_done(void *data, ssize_t len, void *cbdata)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						if (usb.state == USBD_STATE_SETTING_ADDRESS) {
 | 
				
			||||||
 | 
							usb.state = USBD_STATE_ADDRESS;
 | 
				
			||||||
 | 
							usb_set_addr(usb.address);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						usb_setup_control();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void usb_handle_control_status_cb(ep_callback_t cb)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						/* empty status transfer */
 | 
				
			||||||
 | 
						switch (usb.ctrl_dir) {
 | 
				
			||||||
 | 
						case USB_CTRL_REQ_IN:
 | 
				
			||||||
 | 
							usb.ep_state[0].rx.data01 = USB_DATA01_DATA1;
 | 
				
			||||||
 | 
							usb_rx(&usb.ep_state[0].rx, NULL, 0, cb, NULL);
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						default:
 | 
				
			||||||
 | 
							usb.ep_state[0].tx.data01 = USB_DATA01_DATA1;
 | 
				
			||||||
 | 
							usb_ep0_tx_cp(NULL, 0, 1 /* short packet */, cb, NULL);
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void usb_handle_control_status(int fail)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						if (fail) {
 | 
				
			||||||
 | 
							usb_pipe_stall(&usb.ep_state[0].rx);
 | 
				
			||||||
 | 
							usb_pipe_stall(&usb.ep_state[0].tx);
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							usb_handle_control_status_cb(usb_handle_control_done);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Dispatch non-standard request to registered USB functions.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static void usb_handle_control_nonstd(struct usb_ctrl_req_t *req)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						/* XXX filter by interface/endpoint? */
 | 
				
			||||||
 | 
						for (struct usbd_function_ctx_header *fh = &usb.functions; fh != NULL; fh = fh->next) {
 | 
				
			||||||
 | 
							/* ->control() returns != 0 if it handled the request */
 | 
				
			||||||
 | 
							if (fh->function->control != NULL &&
 | 
				
			||||||
 | 
							    fh->function->control(req, fh))
 | 
				
			||||||
 | 
								return;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						usb_handle_control_status(-1);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Great resource: http://wiki.osdev.org/Universal_Serial_Bus
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Control Transfers
 | 
				
			||||||
 | 
					 * -----------------
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * A control transfer consists of a SETUP transaction (1), zero or
 | 
				
			||||||
 | 
					 * more data transactions (IN or OUT) (2), and a final status
 | 
				
			||||||
 | 
					 * transaction (3).
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Token sequence (data toggle):
 | 
				
			||||||
 | 
					 * 1.  SETUP (0)
 | 
				
			||||||
 | 
					 * (2a. OUT (1) ... (toggling))
 | 
				
			||||||
 | 
					 * 3a. IN (1)
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * or
 | 
				
			||||||
 | 
					 * 1.  SETUP (0)
 | 
				
			||||||
 | 
					 * 2b. IN (1) ... (toggling)
 | 
				
			||||||
 | 
					 * 3b. OUT (1)
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Report errors by STALLing the control EP after (1) or (2), so that
 | 
				
			||||||
 | 
					 * (3) will STALL.  Seems we need to clear the STALL after that so
 | 
				
			||||||
 | 
					 * that the next SETUP can make it through.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * The following code is not written defensively, but instead only
 | 
				
			||||||
 | 
					 * asserts values that are essential for correct execution.  It
 | 
				
			||||||
 | 
					 * accepts a superset of the protocol defined by the standard.  We do
 | 
				
			||||||
 | 
					 * this to save space.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void usb_handle_control(void *data, ssize_t len, void *cbdata)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct usb_ctrl_req_t *req = data;
 | 
				
			||||||
 | 
						uint16_t zero16 = 0;
 | 
				
			||||||
 | 
						int fail = 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						usb.ctrl_dir = req->in;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (req->type != USB_CTRL_REQ_STD) {
 | 
				
			||||||
 | 
							usb_handle_control_nonstd(req);
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Only STD requests here */
 | 
				
			||||||
 | 
						switch (req->bRequest) {
 | 
				
			||||||
 | 
						case USB_CTRL_REQ_GET_STATUS:
 | 
				
			||||||
 | 
							/**
 | 
				
			||||||
 | 
							 * Because we don't support remote wakeup or
 | 
				
			||||||
 | 
							 * self-powered operation, and we are specialized to
 | 
				
			||||||
 | 
							 * only EP 0 so far, all GET_STATUS replies are just
 | 
				
			||||||
 | 
							 * empty.
 | 
				
			||||||
 | 
							 */
 | 
				
			||||||
 | 
							usb_ep0_tx_cp(&zero16, sizeof(zero16), req->wLength, NULL, NULL);
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						case USB_CTRL_REQ_CLEAR_FEATURE:
 | 
				
			||||||
 | 
						case USB_CTRL_REQ_SET_FEATURE:
 | 
				
			||||||
 | 
							/**
 | 
				
			||||||
 | 
							 * Nothing to do.  Maybe return STALLs on illegal
 | 
				
			||||||
 | 
							 * accesses?
 | 
				
			||||||
 | 
							 */
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						case USB_CTRL_REQ_SET_ADDRESS:
 | 
				
			||||||
 | 
							/**
 | 
				
			||||||
 | 
							 * We must keep our previous address until the end of
 | 
				
			||||||
 | 
							 * the status stage;  therefore we can't set the
 | 
				
			||||||
 | 
							 * address right now.  Since this is a special case,
 | 
				
			||||||
 | 
							 * the EP 0 handler will take care of this later on.
 | 
				
			||||||
 | 
							 */
 | 
				
			||||||
 | 
							usb.address = req->wValue & 0x7f;
 | 
				
			||||||
 | 
							usb.state = USBD_STATE_SETTING_ADDRESS;
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						case USB_CTRL_REQ_GET_DESCRIPTOR:
 | 
				
			||||||
 | 
							switch (req->wValue >> 8) {
 | 
				
			||||||
 | 
							case USB_DESC_DEV:
 | 
				
			||||||
 | 
								usb_ep0_tx_cp(usb.identity->dev_desc, usb.identity->dev_desc->bLength,
 | 
				
			||||||
 | 
									      req->wLength, NULL, NULL);
 | 
				
			||||||
 | 
								fail = 0;
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							case USB_DESC_CONFIG:
 | 
				
			||||||
 | 
								fail = usb_tx_config_desc(req->wValue & 0xff, req->wLength);
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							case USB_DESC_STRING:
 | 
				
			||||||
 | 
								fail = usb_tx_string_desc(req->wValue & 0xff, req->wLength);
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							default:
 | 
				
			||||||
 | 
								fail = -1;
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							/* we set fail already, so we can go directly to `err' */
 | 
				
			||||||
 | 
							goto err;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						case USB_CTRL_REQ_GET_CONFIGURATION:
 | 
				
			||||||
 | 
							usb_ep0_tx_cp(&usb.config, 1, req->wLength, NULL, NULL); /* XXX implicit LE */
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						case USB_CTRL_REQ_SET_CONFIGURATION:
 | 
				
			||||||
 | 
							if (usb_set_config(req->wValue) < 0)
 | 
				
			||||||
 | 
								goto err;
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						case USB_CTRL_REQ_GET_INTERFACE:
 | 
				
			||||||
 | 
							/* We only support iface setting 0 */
 | 
				
			||||||
 | 
							usb_ep0_tx_cp(&zero16, 1, req->wLength, NULL, NULL);
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						case USB_CTRL_REQ_SET_INTERFACE:
 | 
				
			||||||
 | 
							if (usb_set_interface(req->wIndex, req->wValue) < 0)
 | 
				
			||||||
 | 
								goto err;
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						default:
 | 
				
			||||||
 | 
							goto err;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						fail = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					err:
 | 
				
			||||||
 | 
						usb_handle_control_status(fail);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void usb_setup_control(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						void *buf = ep0_buf[usb.ep_state[0].rx.pingpong];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						usb.ep_state[0].rx.data01 = USB_DATA01_DATA0;
 | 
				
			||||||
 | 
						usb.ep_state[0].tx.data01 = USB_DATA01_DATA1;
 | 
				
			||||||
 | 
						usb_rx(&usb.ep_state[0].rx, buf, EP0_BUFSIZE, usb_handle_control, NULL);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * This is called by the interrupt handler
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					void usb_handle_transaction(struct usb_xfer_info *info)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						enum usb_tok_pid pid = usb_get_xfer_pid(info);
 | 
				
			||||||
 | 
						struct usbd_ep_state_t *eps = &usb.ep_state[usb_get_xfer_ep(info)];
 | 
				
			||||||
 | 
						struct usbd_ep_pipe_state_t *s = &eps->pipe[usb_get_xfer_dir(info)];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						switch (pid) {
 | 
				
			||||||
 | 
						case USB_PID_SETUP:
 | 
				
			||||||
 | 
						case USB_PID_OUT:
 | 
				
			||||||
 | 
							/**
 | 
				
			||||||
 | 
							 * If we receive a SETUP transaction, but don't expect
 | 
				
			||||||
 | 
							 * it (callback set to somewhere else), stall the EP.
 | 
				
			||||||
 | 
							 */
 | 
				
			||||||
 | 
							if (pid == USB_PID_SETUP && s->callback != usb_handle_control)
 | 
				
			||||||
 | 
								usb_handle_control_status(1);
 | 
				
			||||||
 | 
							else
 | 
				
			||||||
 | 
								usb_rx_next(s);
 | 
				
			||||||
 | 
							if (pid == USB_PID_SETUP)
 | 
				
			||||||
 | 
								usb_enable_xfers();
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case USB_PID_IN:
 | 
				
			||||||
 | 
							usb_tx_next(s);
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						default:
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct usbd_ep_pipe_state_t *usb_init_ep(struct usbd_function_ctx_header *ctx, int ep, enum usb_ep_dir dir, size_t size)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct usbd_ep_pipe_state_t *s;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (dir == USB_EP_RX)
 | 
				
			||||||
 | 
							s = &usb.ep_state[ctx->ep_rx_offset + ep].rx;
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
							s = &usb.ep_state[ctx->ep_tx_offset + ep].tx;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						memset(s, 0, sizeof(*s));
 | 
				
			||||||
 | 
						s->ep_maxsize = size;
 | 
				
			||||||
 | 
						s->ep_num = ep;
 | 
				
			||||||
 | 
						s->ep_dir = dir;
 | 
				
			||||||
 | 
						usb_pipe_enable(s);
 | 
				
			||||||
 | 
						return (s);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void usb_restart(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						const struct usbd_device *identity = usb.identity;
 | 
				
			||||||
 | 
						/* XXX reset existing functions? */
 | 
				
			||||||
 | 
						memset(&usb, 0, sizeof(usb));
 | 
				
			||||||
 | 
						usb.functions.function = &usb.control_function;
 | 
				
			||||||
 | 
						usb.identity = identity;
 | 
				
			||||||
 | 
						usb_init_ep(&usb.functions, 0, USB_EP_RX, EP0_BUFSIZE);
 | 
				
			||||||
 | 
						usb_init_ep(&usb.functions, 0, USB_EP_TX, EP0_BUFSIZE);
 | 
				
			||||||
 | 
						usb_setup_control();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void usb_attach_function(const struct usbd_function *function, struct usbd_function_ctx_header *ctx)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						/* XXX right now this requires a sequential initialization */
 | 
				
			||||||
 | 
						struct usbd_function_ctx_header *prev = &usb.functions;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						while (prev->next != NULL)
 | 
				
			||||||
 | 
							prev = prev->next;
 | 
				
			||||||
 | 
						ctx->next = NULL;
 | 
				
			||||||
 | 
						ctx->function = function;
 | 
				
			||||||
 | 
						ctx->interface_offset = prev->interface_offset + prev->function->interface_count;
 | 
				
			||||||
 | 
						ctx->ep_rx_offset = prev->ep_rx_offset + prev->function->ep_rx_count;
 | 
				
			||||||
 | 
						ctx->ep_tx_offset = prev->ep_tx_offset + prev->function->ep_tx_count;
 | 
				
			||||||
 | 
						prev->next = ctx;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void usb_init(const struct usbd_device *identity)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						usb.identity = identity;
 | 
				
			||||||
 | 
						usb_enable();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							
								
								
									
										513
									
								
								Bootloader/usb.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										513
									
								
								Bootloader/usb.h
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,513 @@
 | 
				
			||||||
 | 
					/* Copyright (c) 2011,2012 Simon Schubert <2@0x2c.org>.
 | 
				
			||||||
 | 
					 * Modifications by Jacob Alexander 2014 <haata@kiibohd.com>
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * 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/>.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef __USB_H
 | 
				
			||||||
 | 
					#define __USB_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ----- Compiler Includes -----
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <sys/types.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ----- Local Includes -----
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "mchck.h"
 | 
				
			||||||
 | 
					#include "usb-common.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ----- Defines -----
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define USB_CTRL_REQ_DIR_SHIFT 0
 | 
				
			||||||
 | 
					#define USB_CTRL_REQ_TYPE_SHIFT 1
 | 
				
			||||||
 | 
					#define USB_CTRL_REQ_RECP_SHIFT 3
 | 
				
			||||||
 | 
					#define USB_CTRL_REQ_CODE_SHIFT 8
 | 
				
			||||||
 | 
					#define USB_CTRL_REQ(req_inout, req_type, req_code)			\
 | 
				
			||||||
 | 
						(uint16_t)							\
 | 
				
			||||||
 | 
						((USB_CTRL_REQ_##req_inout << USB_CTRL_REQ_DIR_SHIFT)		\
 | 
				
			||||||
 | 
						 |(USB_CTRL_REQ_##req_type << USB_CTRL_REQ_TYPE_SHIFT)		\
 | 
				
			||||||
 | 
						 |(USB_CTRL_REQ_##req_code << USB_CTRL_REQ_CODE_SHIFT))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ----- Macros -----
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define USB_DESC_STRING(s)					\
 | 
				
			||||||
 | 
					        (const void *)&(const struct {				\
 | 
				
			||||||
 | 
								struct usb_desc_string_t dsc;		\
 | 
				
			||||||
 | 
								char16_t str[sizeof(s) / 2 - 1];	\
 | 
				
			||||||
 | 
					        }) {{						\
 | 
				
			||||||
 | 
								.bLength = sizeof(struct usb_desc_string_t) +	\
 | 
				
			||||||
 | 
									sizeof(s) - 2,			\
 | 
				
			||||||
 | 
								.bDescriptorType = USB_DESC_STRING,	\
 | 
				
			||||||
 | 
								},					\
 | 
				
			||||||
 | 
								s					\
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					#define USB_DESC_STRING_LANG_ENUS USB_DESC_STRING(u"\x0409")
 | 
				
			||||||
 | 
					#define USB_DESC_STRING_SERIALNO ((const void *)1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define USB_FUNCTION_IFACE(iface, iface_off, tx_ep_off, rx_ep_off)	\
 | 
				
			||||||
 | 
						((iface_off) + (iface))
 | 
				
			||||||
 | 
					#define USB_FUNCTION_TX_EP(ep, iface_off, tx_ep_off, rx_ep_off)	\
 | 
				
			||||||
 | 
						((tx_ep_off) + (ep))
 | 
				
			||||||
 | 
					#define USB_FUNCTION_RX_EP(ep, iface_off, tx_ep_off, rx_ep_off)	\
 | 
				
			||||||
 | 
						((rx_ep_off) + (ep))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define USB__INCREMENT(i, _0) (i + 1)
 | 
				
			||||||
 | 
					#define USB__COUNT_IFACE_EP(i, e)			\
 | 
				
			||||||
 | 
						__DEFER(USB__COUNT_IFACE_EP_)(__EXPAND i, e)
 | 
				
			||||||
 | 
					#define USB__COUNT_IFACE_EP_(iface, tx_ep, rx_ep, func)   \
 | 
				
			||||||
 | 
						(iface + USB_FUNCTION_ ## func ## _IFACE_COUNT,	  \
 | 
				
			||||||
 | 
						 tx_ep + USB_FUNCTION_ ## func ## _TX_EP_COUNT,	  \
 | 
				
			||||||
 | 
						 rx_ep + USB_FUNCTION_ ## func ## _RX_EP_COUNT)
 | 
				
			||||||
 | 
					#define USB__GET_FUNCTION_IFACE_COUNT(iter, func)	\
 | 
				
			||||||
 | 
						USB_FUNCTION_ ## func ## _IFACE_COUNT +
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define USB__DEFINE_FUNCTION_DESC(iter, func)				\
 | 
				
			||||||
 | 
						USB_FUNCTION_DESC_ ## func ## _DECL __CAT(__usb_func_desc, __COUNTER__);
 | 
				
			||||||
 | 
					#define USB__INIT_FUNCTION_DESC(iter, func)	\
 | 
				
			||||||
 | 
						USB_FUNCTION_DESC_ ## func iter,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define USB__DEFINE_CONFIG_DESC(confignum, name, ...)			\
 | 
				
			||||||
 | 
						&((const struct name {						\
 | 
				
			||||||
 | 
							struct usb_desc_config_t config;			\
 | 
				
			||||||
 | 
							__REPEAT_INNER(, __EAT, USB__DEFINE_FUNCTION_DESC, __VA_ARGS__) \
 | 
				
			||||||
 | 
						}){								\
 | 
				
			||||||
 | 
							.config = {						\
 | 
				
			||||||
 | 
								.bLength = sizeof(struct usb_desc_config_t),	\
 | 
				
			||||||
 | 
								.bDescriptorType = USB_DESC_CONFIG,		\
 | 
				
			||||||
 | 
								.wTotalLength = sizeof(struct name),		\
 | 
				
			||||||
 | 
								.bNumInterfaces = __REPEAT_INNER(, __EAT, USB__GET_FUNCTION_IFACE_COUNT, __VA_ARGS__) 0, \
 | 
				
			||||||
 | 
								.bConfigurationValue = confignum,		\
 | 
				
			||||||
 | 
								.iConfiguration = 0,				\
 | 
				
			||||||
 | 
								.one = 1,					\
 | 
				
			||||||
 | 
								.bMaxPower = 50					\
 | 
				
			||||||
 | 
							},							\
 | 
				
			||||||
 | 
							__REPEAT_INNER((0, 0, 0), USB__COUNT_IFACE_EP, USB__INIT_FUNCTION_DESC, __VA_ARGS__) \
 | 
				
			||||||
 | 
						}).config
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define USB__DEFINE_CONFIG(iter, args)				\
 | 
				
			||||||
 | 
						__DEFER(USB__DEFINE_CONFIG_)(iter, __EXPAND args)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define USB__DEFINE_CONFIG_(confignum, initfun, ...)			\
 | 
				
			||||||
 | 
						&(const struct usbd_config){					\
 | 
				
			||||||
 | 
							.init = initfun,					\
 | 
				
			||||||
 | 
							.desc = USB__DEFINE_CONFIG_DESC(			\
 | 
				
			||||||
 | 
								confignum,					\
 | 
				
			||||||
 | 
								__CAT(__usb_desc, __COUNTER__),			\
 | 
				
			||||||
 | 
								__VA_ARGS__)					\
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define USB_INIT_DEVICE(vid, pid, manuf, product, ...)			\
 | 
				
			||||||
 | 
						{								\
 | 
				
			||||||
 | 
							.dev_desc = &(const struct usb_desc_dev_t){		\
 | 
				
			||||||
 | 
								.bLength = sizeof(struct usb_desc_dev_t),	\
 | 
				
			||||||
 | 
								.bDescriptorType = USB_DESC_DEV,		\
 | 
				
			||||||
 | 
								.bcdUSB = { .maj = 2 },				\
 | 
				
			||||||
 | 
								.bDeviceClass = USB_DEV_CLASS_SEE_IFACE,	\
 | 
				
			||||||
 | 
								.bDeviceSubClass = USB_DEV_SUBCLASS_SEE_IFACE,	\
 | 
				
			||||||
 | 
								.bDeviceProtocol = USB_DEV_PROTO_SEE_IFACE,	\
 | 
				
			||||||
 | 
								.bMaxPacketSize0 = EP0_BUFSIZE,			\
 | 
				
			||||||
 | 
								.idVendor = vid,				\
 | 
				
			||||||
 | 
								.idProduct = pid,				\
 | 
				
			||||||
 | 
								.bcdDevice = { .raw = 0 },			\
 | 
				
			||||||
 | 
								.iManufacturer = 1,				\
 | 
				
			||||||
 | 
								.iProduct = 2,					\
 | 
				
			||||||
 | 
								.iSerialNumber = 3,				\
 | 
				
			||||||
 | 
								.bNumConfigurations = __PP_NARG(__VA_ARGS__),	\
 | 
				
			||||||
 | 
							},							\
 | 
				
			||||||
 | 
							.string_descs = (const struct usb_desc_string_t * const []){ \
 | 
				
			||||||
 | 
								USB_DESC_STRING_LANG_ENUS,			\
 | 
				
			||||||
 | 
								USB_DESC_STRING(manuf),				\
 | 
				
			||||||
 | 
								USB_DESC_STRING(product),			\
 | 
				
			||||||
 | 
								USB_DESC_STRING_SERIALNO,			\
 | 
				
			||||||
 | 
								NULL						\
 | 
				
			||||||
 | 
							},							\
 | 
				
			||||||
 | 
							.configs = {						\
 | 
				
			||||||
 | 
								__REPEAT(1, USB__INCREMENT, USB__DEFINE_CONFIG, __VA_ARGS__) \
 | 
				
			||||||
 | 
								NULL						\
 | 
				
			||||||
 | 
							}							\
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ----- Structs & Enumerations -----
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Note: bitfields ahead.
 | 
				
			||||||
 | 
					 * GCC fills the fields lsb-to-msb on little endian.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * USB descriptors
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					enum usb_desc_type {
 | 
				
			||||||
 | 
						USB_DESC_DEV = 1,
 | 
				
			||||||
 | 
						USB_DESC_CONFIG = 2,
 | 
				
			||||||
 | 
						USB_DESC_STRING = 3,
 | 
				
			||||||
 | 
						USB_DESC_IFACE = 4,
 | 
				
			||||||
 | 
						USB_DESC_EP = 5,
 | 
				
			||||||
 | 
						USB_DESC_DEVQUAL = 6,
 | 
				
			||||||
 | 
						USB_DESC_OTHERSPEED = 7,
 | 
				
			||||||
 | 
						USB_DESC_POWER = 8
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct usb_desc_type_t {
 | 
				
			||||||
 | 
						UNION_STRUCT_START(8);
 | 
				
			||||||
 | 
						enum usb_desc_type id : 5;
 | 
				
			||||||
 | 
						enum usb_desc_type_type {
 | 
				
			||||||
 | 
							USB_DESC_TYPE_STD = 0,
 | 
				
			||||||
 | 
							USB_DESC_TYPE_CLASS = 1,
 | 
				
			||||||
 | 
							USB_DESC_TYPE_VENDOR = 2
 | 
				
			||||||
 | 
						} type_type : 2;
 | 
				
			||||||
 | 
						uint8_t _rsvd0 : 1;
 | 
				
			||||||
 | 
						UNION_STRUCT_END;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					CTASSERT_SIZE_BYTE(struct usb_desc_type_t, 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					enum usb_dev_class {
 | 
				
			||||||
 | 
						USB_DEV_CLASS_SEE_IFACE = 0,
 | 
				
			||||||
 | 
						USB_DEV_CLASS_APP = 0xfe,
 | 
				
			||||||
 | 
						USB_DEV_CLASS_VENDOR = 0xff
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					enum usb_dev_subclass {
 | 
				
			||||||
 | 
						USB_DEV_SUBCLASS_SEE_IFACE = 0,
 | 
				
			||||||
 | 
						USB_DEV_SUBCLASS_VENDOR = 0xff
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					enum usb_dev_proto {
 | 
				
			||||||
 | 
						USB_DEV_PROTO_SEE_IFACE = 0,
 | 
				
			||||||
 | 
						USB_DEV_PROTO_VENDOR = 0xff
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct usb_bcd_t {
 | 
				
			||||||
 | 
						UNION_STRUCT_START(16);
 | 
				
			||||||
 | 
						struct {
 | 
				
			||||||
 | 
							uint8_t sub : 4;
 | 
				
			||||||
 | 
							uint8_t min : 4;
 | 
				
			||||||
 | 
							uint16_t maj : 8;
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
						UNION_STRUCT_END;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					CTASSERT_SIZE_BYTE(struct usb_bcd_t, 2);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct usb_desc_generic_t {
 | 
				
			||||||
 | 
						uint8_t bLength;
 | 
				
			||||||
 | 
						struct usb_desc_type_t bDescriptorType;
 | 
				
			||||||
 | 
						uint8_t data[];
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					CTASSERT_SIZE_BYTE(struct usb_desc_generic_t, 2);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct usb_desc_dev_t {
 | 
				
			||||||
 | 
						uint8_t bLength;
 | 
				
			||||||
 | 
						enum usb_desc_type bDescriptorType : 8; /* = USB_DESC_DEV */
 | 
				
			||||||
 | 
						struct usb_bcd_t bcdUSB;	     /* = 0x0200 */
 | 
				
			||||||
 | 
						enum usb_dev_class bDeviceClass : 8;
 | 
				
			||||||
 | 
						enum usb_dev_subclass bDeviceSubClass : 8;
 | 
				
			||||||
 | 
						enum usb_dev_proto bDeviceProtocol : 8;
 | 
				
			||||||
 | 
						uint8_t bMaxPacketSize0;
 | 
				
			||||||
 | 
						uint16_t idVendor;
 | 
				
			||||||
 | 
						uint16_t idProduct;
 | 
				
			||||||
 | 
						struct usb_bcd_t bcdDevice;
 | 
				
			||||||
 | 
						uint8_t iManufacturer;
 | 
				
			||||||
 | 
						uint8_t iProduct;
 | 
				
			||||||
 | 
						uint8_t iSerialNumber;
 | 
				
			||||||
 | 
						uint8_t bNumConfigurations;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					CTASSERT_SIZE_BYTE(struct usb_desc_dev_t, 18);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct usb_desc_ep_t {
 | 
				
			||||||
 | 
						uint8_t bLength;
 | 
				
			||||||
 | 
						enum usb_desc_type bDescriptorType : 8; /* = USB_DESC_EP */
 | 
				
			||||||
 | 
						union {
 | 
				
			||||||
 | 
							struct {
 | 
				
			||||||
 | 
								uint8_t ep_num : 4;
 | 
				
			||||||
 | 
								uint8_t _rsvd0 : 3;
 | 
				
			||||||
 | 
								uint8_t in : 1;
 | 
				
			||||||
 | 
							};
 | 
				
			||||||
 | 
							uint8_t bEndpointAddress;
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
						struct {
 | 
				
			||||||
 | 
							enum usb_ep_type {
 | 
				
			||||||
 | 
								USB_EP_CONTROL = 0,
 | 
				
			||||||
 | 
								USB_EP_ISO = 1,
 | 
				
			||||||
 | 
								USB_EP_BULK = 2,
 | 
				
			||||||
 | 
								USB_EP_INTR = 3
 | 
				
			||||||
 | 
							} type : 2;
 | 
				
			||||||
 | 
							enum usb_ep_iso_synctype {
 | 
				
			||||||
 | 
								USB_EP_ISO_NOSYNC = 0,
 | 
				
			||||||
 | 
								USB_EP_ISO_ASYNC = 1,
 | 
				
			||||||
 | 
								USB_EP_ISO_ADAPTIVE = 2,
 | 
				
			||||||
 | 
								USB_EP_ISO_SYNC = 3
 | 
				
			||||||
 | 
							} sync_type : 2;
 | 
				
			||||||
 | 
							enum usb_ep_iso_usagetype {
 | 
				
			||||||
 | 
								USB_EP_ISO_DATA = 0,
 | 
				
			||||||
 | 
								USB_EP_ISO_FEEDBACK = 1,
 | 
				
			||||||
 | 
								USB_EP_ISO_IMPLICIT = 2
 | 
				
			||||||
 | 
							} usage_type : 2;
 | 
				
			||||||
 | 
							uint8_t _rsvd1 : 2;
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
						struct {
 | 
				
			||||||
 | 
							uint16_t wMaxPacketSize : 11;
 | 
				
			||||||
 | 
							uint16_t _rsvd2 : 5;
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
						uint8_t bInterval;
 | 
				
			||||||
 | 
					} __packed;
 | 
				
			||||||
 | 
					CTASSERT_SIZE_BYTE(struct usb_desc_ep_t, 7);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct usb_desc_iface_t {
 | 
				
			||||||
 | 
						uint8_t bLength;
 | 
				
			||||||
 | 
						enum usb_desc_type bDescriptorType : 8; /* = USB_DESC_IFACE */
 | 
				
			||||||
 | 
						uint8_t bInterfaceNumber;
 | 
				
			||||||
 | 
						uint8_t bAlternateSetting;
 | 
				
			||||||
 | 
						uint8_t bNumEndpoints;
 | 
				
			||||||
 | 
						enum usb_dev_class bInterfaceClass : 8;
 | 
				
			||||||
 | 
						enum usb_dev_subclass bInterfaceSubClass: 8;
 | 
				
			||||||
 | 
						enum usb_dev_proto bInterfaceProtocol : 8;
 | 
				
			||||||
 | 
						uint8_t iInterface;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					CTASSERT_SIZE_BYTE(struct usb_desc_iface_t, 9);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct usb_desc_config_t {
 | 
				
			||||||
 | 
						uint8_t bLength;
 | 
				
			||||||
 | 
						enum usb_desc_type bDescriptorType : 8; /* = USB_DESC_CONFIG */
 | 
				
			||||||
 | 
						uint16_t wTotalLength;	     /* size of config, iface, ep */
 | 
				
			||||||
 | 
						uint8_t bNumInterfaces;
 | 
				
			||||||
 | 
						uint8_t bConfigurationValue;
 | 
				
			||||||
 | 
						uint8_t iConfiguration;
 | 
				
			||||||
 | 
						struct {
 | 
				
			||||||
 | 
							uint8_t _rsvd0 : 5;
 | 
				
			||||||
 | 
							uint8_t remote_wakeup : 1;
 | 
				
			||||||
 | 
							uint8_t self_powered : 1;
 | 
				
			||||||
 | 
							uint8_t one : 1; /* = 1 for historical reasons */
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
						uint8_t bMaxPower;	/* units of 2mA */
 | 
				
			||||||
 | 
					} __packed;
 | 
				
			||||||
 | 
					CTASSERT_SIZE_BYTE(struct usb_desc_config_t, 9);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct usb_desc_string_t {
 | 
				
			||||||
 | 
						uint8_t bLength;
 | 
				
			||||||
 | 
						enum usb_desc_type bDescriptorType : 8; /* = USB_DESC_STRING */
 | 
				
			||||||
 | 
						const char16_t bString[];
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					CTASSERT_SIZE_BYTE(struct usb_desc_string_t, 2);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct usb_ctrl_req_t {
 | 
				
			||||||
 | 
						union /* reqtype and request & u16 */ {
 | 
				
			||||||
 | 
							struct /* reqtype and request */ {
 | 
				
			||||||
 | 
								union /* reqtype in bitfield & u8 */ {
 | 
				
			||||||
 | 
									struct /* reqtype */ {
 | 
				
			||||||
 | 
										enum usb_ctrl_req_recp {
 | 
				
			||||||
 | 
											USB_CTRL_REQ_DEV = 0,
 | 
				
			||||||
 | 
											USB_CTRL_REQ_IFACE = 1,
 | 
				
			||||||
 | 
											USB_CTRL_REQ_EP = 2,
 | 
				
			||||||
 | 
											USB_CTRL_REQ_OTHER = 3
 | 
				
			||||||
 | 
										} recp : 5;
 | 
				
			||||||
 | 
										enum usb_ctrl_req_type {
 | 
				
			||||||
 | 
											USB_CTRL_REQ_STD = 0,
 | 
				
			||||||
 | 
											USB_CTRL_REQ_CLASS = 1,
 | 
				
			||||||
 | 
											USB_CTRL_REQ_VENDOR = 2
 | 
				
			||||||
 | 
										} type : 2;
 | 
				
			||||||
 | 
										enum usb_ctrl_req_dir {
 | 
				
			||||||
 | 
											USB_CTRL_REQ_OUT = 0,
 | 
				
			||||||
 | 
											USB_CTRL_REQ_IN = 1
 | 
				
			||||||
 | 
										} in : 1;
 | 
				
			||||||
 | 
									};
 | 
				
			||||||
 | 
									uint8_t bmRequestType;
 | 
				
			||||||
 | 
								}; /* union */
 | 
				
			||||||
 | 
								enum usb_ctrl_req_code {
 | 
				
			||||||
 | 
									USB_CTRL_REQ_GET_STATUS = 0,
 | 
				
			||||||
 | 
									USB_CTRL_REQ_CLEAR_FEATURE = 1,
 | 
				
			||||||
 | 
									USB_CTRL_REQ_SET_FEATURE = 3,
 | 
				
			||||||
 | 
									USB_CTRL_REQ_SET_ADDRESS = 5,
 | 
				
			||||||
 | 
									USB_CTRL_REQ_GET_DESCRIPTOR = 6,
 | 
				
			||||||
 | 
									USB_CTRL_REQ_SET_DESCRIPTOR = 7,
 | 
				
			||||||
 | 
									USB_CTRL_REQ_GET_CONFIGURATION = 8,
 | 
				
			||||||
 | 
									USB_CTRL_REQ_SET_CONFIGURATION = 9,
 | 
				
			||||||
 | 
									USB_CTRL_REQ_GET_INTERFACE = 10,
 | 
				
			||||||
 | 
									USB_CTRL_REQ_SET_INTERFACE = 11,
 | 
				
			||||||
 | 
									USB_CTRL_REQ_SYNC_FRAME = 12
 | 
				
			||||||
 | 
								} bRequest : 8;
 | 
				
			||||||
 | 
							}; /* struct */
 | 
				
			||||||
 | 
							uint16_t type_and_req;
 | 
				
			||||||
 | 
						}; /* union */
 | 
				
			||||||
 | 
						union {
 | 
				
			||||||
 | 
							uint16_t wValue;
 | 
				
			||||||
 | 
							struct {
 | 
				
			||||||
 | 
								uint8_t wValueLow;
 | 
				
			||||||
 | 
								uint8_t wValueHigh;
 | 
				
			||||||
 | 
							};
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
						uint16_t wIndex;
 | 
				
			||||||
 | 
						uint16_t wLength;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					CTASSERT_SIZE_BYTE(struct usb_ctrl_req_t, 8);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * status replies for GET_STATUS.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct usb_ctrl_req_status_dev_t {
 | 
				
			||||||
 | 
						uint16_t self_powered : 1;
 | 
				
			||||||
 | 
						uint16_t remote_wakeup : 1;
 | 
				
			||||||
 | 
						uint16_t _rsvd : 14;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					CTASSERT_SIZE_BIT(struct usb_ctrl_req_status_dev_t, 16);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct usb_ctrl_req_status_iface_t {
 | 
				
			||||||
 | 
						uint16_t _rsvd;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					CTASSERT_SIZE_BIT(struct usb_ctrl_req_status_iface_t, 16);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct usb_ctrl_req_status_ep_t {
 | 
				
			||||||
 | 
						uint16_t halt : 1;
 | 
				
			||||||
 | 
						uint16_t _rsvd : 15;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					CTASSERT_SIZE_BIT(struct usb_ctrl_req_status_ep_t, 16);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Descriptor type (in req->value) for GET_DESCRIPTOR.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					struct usb_ctrl_req_desc_t {
 | 
				
			||||||
 | 
						uint8_t idx;
 | 
				
			||||||
 | 
						enum usb_desc_type type : 8;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					CTASSERT_SIZE_BIT(struct usb_ctrl_req_desc_t, 16);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Feature selector (in req->value) for CLEAR_FEATURE.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					enum usb_ctrl_req_feature {
 | 
				
			||||||
 | 
						USB_CTRL_REQ_FEAT_EP_HALT = 0,
 | 
				
			||||||
 | 
						USB_CTRL_REQ_FEAT_DEV_REMOTE_WKUP = 1,
 | 
				
			||||||
 | 
						USB_CTRL_REQ_FEAT_TEST_MODE = 2
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct usb_xfer_info;
 | 
				
			||||||
 | 
					typedef void (*ep_callback_t)(void *buf, ssize_t len, void *data);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * (Artificial) function.  Aggregates one or more interfaces.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					struct usbd_function {
 | 
				
			||||||
 | 
						int (*configure)(int orig_iface, int iface, int altsetting, void *data);
 | 
				
			||||||
 | 
						int (*control)(struct usb_ctrl_req_t *, void *);
 | 
				
			||||||
 | 
						int interface_count;
 | 
				
			||||||
 | 
						int ep_rx_count;
 | 
				
			||||||
 | 
						int ep_tx_count;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct usbd_function_ctx_header {
 | 
				
			||||||
 | 
						struct usbd_function_ctx_header *next;
 | 
				
			||||||
 | 
						const struct usbd_function *function;
 | 
				
			||||||
 | 
						int interface_offset;
 | 
				
			||||||
 | 
						int ep_rx_offset;
 | 
				
			||||||
 | 
						int ep_tx_offset;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef void (usbd_init_fun_t)(int);
 | 
				
			||||||
 | 
					typedef void (usbd_suspend_resume_fun_t)(void);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Configuration.  Contains one or more functions which all will be
 | 
				
			||||||
 | 
					 * active concurrently.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					struct usbd_config {
 | 
				
			||||||
 | 
						usbd_init_fun_t *init;
 | 
				
			||||||
 | 
						usbd_suspend_resume_fun_t *suspend;
 | 
				
			||||||
 | 
						usbd_suspend_resume_fun_t *resume;
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * We will not set a config for now, because there is not much to
 | 
				
			||||||
 | 
						 * configure, except for power
 | 
				
			||||||
 | 
						 *
 | 
				
			||||||
 | 
						 * const struct usb_desc_config_t *config_desc;
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						const struct usb_desc_config_t *desc;
 | 
				
			||||||
 | 
						const struct usbd_function *function[];
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Device.  Contains one or more configurations, out of which only one
 | 
				
			||||||
 | 
					 * is active at a time.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					struct usbd_device {
 | 
				
			||||||
 | 
						const struct usb_desc_dev_t *dev_desc;
 | 
				
			||||||
 | 
						const struct usb_desc_string_t * const *string_descs;
 | 
				
			||||||
 | 
						const struct usbd_config *configs[];
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Provided by MD code */
 | 
				
			||||||
 | 
					struct usbd_ep_pipe_state_t;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ----- Functions -----
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void *usb_get_xfer_data(struct usb_xfer_info *);
 | 
				
			||||||
 | 
					enum usb_tok_pid usb_get_xfer_pid(struct usb_xfer_info *);
 | 
				
			||||||
 | 
					int usb_get_xfer_ep(struct usb_xfer_info *);
 | 
				
			||||||
 | 
					enum usb_ep_dir usb_get_xfer_dir(struct usb_xfer_info *);
 | 
				
			||||||
 | 
					void usb_enable_xfers(void);
 | 
				
			||||||
 | 
					void usb_set_addr(int);
 | 
				
			||||||
 | 
					void usb_ep_stall(int);
 | 
				
			||||||
 | 
					size_t usb_ep_get_transfer_size(struct usbd_ep_pipe_state_t *);
 | 
				
			||||||
 | 
					void usb_queue_next(struct usbd_ep_pipe_state_t *, void *, size_t);
 | 
				
			||||||
 | 
					void usb_pipe_stall(struct usbd_ep_pipe_state_t *);
 | 
				
			||||||
 | 
					void usb_pipe_unstall(struct usbd_ep_pipe_state_t *);
 | 
				
			||||||
 | 
					void usb_pipe_enable(struct usbd_ep_pipe_state_t *s);
 | 
				
			||||||
 | 
					void usb_pipe_disable(struct usbd_ep_pipe_state_t *s);
 | 
				
			||||||
 | 
					#ifdef VUSB
 | 
				
			||||||
 | 
					void vusb_main_loop(void);
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
					void usb_poll(void);
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					int usb_tx_serialno(size_t reqlen);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Provided by MI code */
 | 
				
			||||||
 | 
					void usb_init(const struct usbd_device *);
 | 
				
			||||||
 | 
					void usb_attach_function(const struct usbd_function *function, struct usbd_function_ctx_header *ctx);
 | 
				
			||||||
 | 
					void usb_handle_transaction(struct usb_xfer_info *);
 | 
				
			||||||
 | 
					void usb_setup_control(void);
 | 
				
			||||||
 | 
					void usb_handle_control_status_cb(ep_callback_t cb);
 | 
				
			||||||
 | 
					void usb_handle_control_status(int);
 | 
				
			||||||
 | 
					struct usbd_ep_pipe_state_t *usb_init_ep(struct usbd_function_ctx_header *ctx, int ep, enum usb_ep_dir dir, size_t size);
 | 
				
			||||||
 | 
					int usb_rx(struct usbd_ep_pipe_state_t *, void *, size_t, ep_callback_t, void *);
 | 
				
			||||||
 | 
					int usb_tx(struct usbd_ep_pipe_state_t *, const void *, size_t, size_t, ep_callback_t, void *);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int usb_ep0_rx(void *, size_t, ep_callback_t, void *);
 | 
				
			||||||
 | 
					void *usb_ep0_tx_inplace_prepare(size_t len);
 | 
				
			||||||
 | 
					int usb_ep0_tx(void *buf, size_t len, size_t reqlen, ep_callback_t cb, void *cb_data);
 | 
				
			||||||
 | 
					int usb_ep0_tx_cp(const void *, size_t, size_t, ep_callback_t, void *);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ----- DFU USB Additional Includes -----
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "dfu.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							
								
								
									
										301
									
								
								Bootloader/usbotg.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										301
									
								
								Bootloader/usbotg.h
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,301 @@
 | 
				
			||||||
 | 
					/* Copyright (c) 2011,2012 Simon Schubert <2@0x2c.org>.
 | 
				
			||||||
 | 
					 * Modifications by Jacob Alexander 2014 <haata@kiibohd.com>
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * 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 "mchck.h"
 | 
				
			||||||
 | 
					#include "usb-common.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ----- Structs -----
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Hardware structures
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct USB_ADDINFO_t {
 | 
				
			||||||
 | 
					        UNION_STRUCT_START(8);
 | 
				
			||||||
 | 
					        uint8_t iehost : 1;
 | 
				
			||||||
 | 
					        uint8_t _rsvd0 : 2;
 | 
				
			||||||
 | 
					        uint8_t irqnum : 5;
 | 
				
			||||||
 | 
					        UNION_STRUCT_END;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					CTASSERT_SIZE_BIT(struct USB_ADDINFO_t, 8);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct USB_OTGSTAT_t {
 | 
				
			||||||
 | 
					        UNION_STRUCT_START(8);
 | 
				
			||||||
 | 
					        uint8_t avbus : 1;
 | 
				
			||||||
 | 
					        uint8_t _rsvd0 : 1;
 | 
				
			||||||
 | 
					        uint8_t b_sess : 1;
 | 
				
			||||||
 | 
					        uint8_t sessvld : 1;
 | 
				
			||||||
 | 
					        uint8_t _rsvd1 : 1;
 | 
				
			||||||
 | 
					        uint8_t line_state : 1;
 | 
				
			||||||
 | 
					        uint8_t onemsec : 1;
 | 
				
			||||||
 | 
					        uint8_t idchg : 1;
 | 
				
			||||||
 | 
					        UNION_STRUCT_END;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					CTASSERT_SIZE_BIT(struct USB_OTGSTAT_t, 8);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct USB_OTGCTL_t {
 | 
				
			||||||
 | 
					        UNION_STRUCT_START(8);
 | 
				
			||||||
 | 
					        uint8_t _rsvd0 : 2;
 | 
				
			||||||
 | 
					        uint8_t otgen : 1;
 | 
				
			||||||
 | 
					        uint8_t _rsvd1 : 1;
 | 
				
			||||||
 | 
					        uint8_t dmlow : 1;
 | 
				
			||||||
 | 
					        uint8_t dplow : 1;
 | 
				
			||||||
 | 
					        uint8_t _rsvd2 : 1;
 | 
				
			||||||
 | 
					        uint8_t dphigh : 1;
 | 
				
			||||||
 | 
					        UNION_STRUCT_END;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					CTASSERT_SIZE_BIT(struct USB_OTGCTL_t, 8);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct USB_ISTAT_t {
 | 
				
			||||||
 | 
					        UNION_STRUCT_START(8);
 | 
				
			||||||
 | 
					        uint8_t usbrst : 1;
 | 
				
			||||||
 | 
					        uint8_t error : 1;
 | 
				
			||||||
 | 
					        uint8_t softok : 1;
 | 
				
			||||||
 | 
					        uint8_t tokdne : 1;
 | 
				
			||||||
 | 
					        uint8_t sleep : 1;
 | 
				
			||||||
 | 
					        uint8_t resume : 1;
 | 
				
			||||||
 | 
					        uint8_t attach : 1;
 | 
				
			||||||
 | 
					        uint8_t stall : 1;
 | 
				
			||||||
 | 
					        UNION_STRUCT_END;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					CTASSERT_SIZE_BIT(struct USB_ISTAT_t, 8);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct USB_ERRSTAT_t {
 | 
				
			||||||
 | 
					        UNION_STRUCT_START(8);
 | 
				
			||||||
 | 
					        uint8_t piderr : 1;
 | 
				
			||||||
 | 
					        uint8_t crc5eof : 1;
 | 
				
			||||||
 | 
					        uint8_t crc16 : 1;
 | 
				
			||||||
 | 
					        uint8_t dfn8 : 1;
 | 
				
			||||||
 | 
					        uint8_t btoerr : 1;
 | 
				
			||||||
 | 
					        uint8_t dmaerr : 1;
 | 
				
			||||||
 | 
					        uint8_t _rsvd0 : 1;
 | 
				
			||||||
 | 
					        uint8_t btserr : 1;
 | 
				
			||||||
 | 
					        UNION_STRUCT_END;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					CTASSERT_SIZE_BIT(struct USB_ERRSTAT_t, 8);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct USB_STAT_t {
 | 
				
			||||||
 | 
					        UNION_STRUCT_START(8);
 | 
				
			||||||
 | 
					        uint8_t _rsvd0 : 2;
 | 
				
			||||||
 | 
					        enum usb_ep_pingpong pingpong : 1;
 | 
				
			||||||
 | 
					        enum usb_ep_dir dir : 1;
 | 
				
			||||||
 | 
					        uint8_t ep : 4;
 | 
				
			||||||
 | 
					        UNION_STRUCT_END;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					CTASSERT_SIZE_BIT(struct USB_STAT_t, 8);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct USB_CTL_t {
 | 
				
			||||||
 | 
					        union {
 | 
				
			||||||
 | 
					                struct /* common */ {
 | 
				
			||||||
 | 
					                        uint8_t _rsvd1 : 1;
 | 
				
			||||||
 | 
					                        uint8_t oddrst : 1;
 | 
				
			||||||
 | 
					                        uint8_t resume : 1;
 | 
				
			||||||
 | 
					                        uint8_t _rsvd2 : 3;
 | 
				
			||||||
 | 
					                        uint8_t se0 : 1;
 | 
				
			||||||
 | 
					                        uint8_t jstate : 1;
 | 
				
			||||||
 | 
					                };
 | 
				
			||||||
 | 
					                struct /* host */ {
 | 
				
			||||||
 | 
					                        uint8_t sofen : 1;
 | 
				
			||||||
 | 
					                        uint8_t _rsvd3 : 2;
 | 
				
			||||||
 | 
					                        uint8_t hostmodeen : 1;
 | 
				
			||||||
 | 
					                        uint8_t reset : 1;
 | 
				
			||||||
 | 
					                        uint8_t token_busy : 1;
 | 
				
			||||||
 | 
					                        uint8_t _rsvd4 : 2;
 | 
				
			||||||
 | 
					                };
 | 
				
			||||||
 | 
					                struct /* device */ {
 | 
				
			||||||
 | 
					                        uint8_t usben : 1;
 | 
				
			||||||
 | 
					                        uint8_t _rsvd5 : 4;
 | 
				
			||||||
 | 
					                        uint8_t txd_suspend : 1;
 | 
				
			||||||
 | 
					                        uint8_t _rsvd6 : 2;
 | 
				
			||||||
 | 
					                };
 | 
				
			||||||
 | 
					                uint8_t raw;
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					CTASSERT_SIZE_BIT(struct USB_CTL_t, 8);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct USB_ADDR_t {
 | 
				
			||||||
 | 
					        UNION_STRUCT_START(8);
 | 
				
			||||||
 | 
					        uint8_t addr : 7;
 | 
				
			||||||
 | 
					        uint8_t lsen : 1;
 | 
				
			||||||
 | 
					        UNION_STRUCT_END;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					CTASSERT_SIZE_BIT(struct USB_ADDR_t, 8);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct USB_TOKEN_t {
 | 
				
			||||||
 | 
					        UNION_STRUCT_START(8);
 | 
				
			||||||
 | 
					        uint8_t endpt : 4;
 | 
				
			||||||
 | 
					        enum usb_tok_pid pid : 4;
 | 
				
			||||||
 | 
					        UNION_STRUCT_END;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					CTASSERT_SIZE_BIT(struct USB_TOKEN_t, 8);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct USB_ENDPT_t {
 | 
				
			||||||
 | 
					        UNION_STRUCT_START(8);
 | 
				
			||||||
 | 
					        uint8_t ephshk : 1;
 | 
				
			||||||
 | 
					        uint8_t epstall : 1;
 | 
				
			||||||
 | 
					        uint8_t eptxen : 1;
 | 
				
			||||||
 | 
					        uint8_t eprxen : 1;
 | 
				
			||||||
 | 
					        uint8_t epctldis : 1;
 | 
				
			||||||
 | 
					        uint8_t _rsvd0 : 1;
 | 
				
			||||||
 | 
					        uint8_t retrydis : 1;
 | 
				
			||||||
 | 
					        uint8_t hostwohub : 1;
 | 
				
			||||||
 | 
					        UNION_STRUCT_END;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					CTASSERT_SIZE_BIT(struct USB_ENDPT_t, 8);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct USB_USBCTRL_t {
 | 
				
			||||||
 | 
					        UNION_STRUCT_START(8);
 | 
				
			||||||
 | 
					        uint8_t _rsvd0 : 6;
 | 
				
			||||||
 | 
					        uint8_t pde : 1;
 | 
				
			||||||
 | 
					        uint8_t susp : 1;
 | 
				
			||||||
 | 
					        UNION_STRUCT_END;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					CTASSERT_SIZE_BIT(struct USB_USBCTRL_t, 8);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct USB_OBSERVE_t {
 | 
				
			||||||
 | 
					        UNION_STRUCT_START(8);
 | 
				
			||||||
 | 
					        uint8_t _rsvd0 : 4;
 | 
				
			||||||
 | 
					        uint8_t dmpd : 1;
 | 
				
			||||||
 | 
					        uint8_t _rsvd1 : 1;
 | 
				
			||||||
 | 
					        uint8_t dppd : 1;
 | 
				
			||||||
 | 
					        uint8_t dppu : 1;
 | 
				
			||||||
 | 
					        UNION_STRUCT_END;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					CTASSERT_SIZE_BIT(struct USB_OBSERVE_t, 8);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct USB_CONTROL_t {
 | 
				
			||||||
 | 
					        UNION_STRUCT_START(8);
 | 
				
			||||||
 | 
					        uint8_t _rsvd0 : 4;
 | 
				
			||||||
 | 
					        uint8_t dppullupnonotg : 1;
 | 
				
			||||||
 | 
					        uint8_t _rsvd1 : 3;
 | 
				
			||||||
 | 
					        UNION_STRUCT_END;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					CTASSERT_SIZE_BIT(struct USB_CONTROL_t, 8);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct USB_USBTRC0_t {
 | 
				
			||||||
 | 
					        UNION_STRUCT_START(8);
 | 
				
			||||||
 | 
					        uint8_t usb_resume_int : 1;
 | 
				
			||||||
 | 
					        uint8_t sync_det : 1;
 | 
				
			||||||
 | 
					        uint8_t _rsvd0 : 3;
 | 
				
			||||||
 | 
					        uint8_t usbresmen : 1;
 | 
				
			||||||
 | 
					        uint8_t _rsvd1 : 1;
 | 
				
			||||||
 | 
					        uint8_t usbreset : 1;
 | 
				
			||||||
 | 
					        UNION_STRUCT_END;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					CTASSERT_SIZE_BIT(struct USB_USBTRC0_t, 8);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct USB_t {
 | 
				
			||||||
 | 
					        uint8_t perid;
 | 
				
			||||||
 | 
					        uint8_t _pad0[3];
 | 
				
			||||||
 | 
					        uint8_t idcomp;
 | 
				
			||||||
 | 
					        uint8_t _pad1[3];
 | 
				
			||||||
 | 
					        uint8_t rev;
 | 
				
			||||||
 | 
					        uint8_t _pad2[3];
 | 
				
			||||||
 | 
					        struct USB_ADDINFO_t addinfo;
 | 
				
			||||||
 | 
					        uint8_t _pad3[3];
 | 
				
			||||||
 | 
					        struct USB_OTGSTAT_t otgistat;
 | 
				
			||||||
 | 
					        uint8_t _pad4[3];
 | 
				
			||||||
 | 
					        struct USB_OTGSTAT_t otgicr;
 | 
				
			||||||
 | 
					        uint8_t _pad5[3];
 | 
				
			||||||
 | 
					        struct USB_OTGSTAT_t otgstat;
 | 
				
			||||||
 | 
					        uint8_t _pad6[3];
 | 
				
			||||||
 | 
					        struct USB_OTGCTL_t otgctl;
 | 
				
			||||||
 | 
					        uint8_t _pad7[3];
 | 
				
			||||||
 | 
					        uint8_t _pad8[0x80 - 0x20];
 | 
				
			||||||
 | 
					        struct USB_ISTAT_t istat;
 | 
				
			||||||
 | 
					        uint8_t _pad9[3];
 | 
				
			||||||
 | 
					        struct USB_ISTAT_t inten;
 | 
				
			||||||
 | 
					        uint8_t _pad10[3];
 | 
				
			||||||
 | 
					        struct USB_ERRSTAT_t errstat;
 | 
				
			||||||
 | 
					        uint8_t _pad11[3];
 | 
				
			||||||
 | 
					        struct USB_ERRSTAT_t erren;
 | 
				
			||||||
 | 
					        uint8_t _pad12[3];
 | 
				
			||||||
 | 
					        struct USB_STAT_t stat;
 | 
				
			||||||
 | 
					        uint8_t _pad13[3];
 | 
				
			||||||
 | 
					        struct USB_CTL_t ctl;
 | 
				
			||||||
 | 
					        uint8_t _pad14[3];
 | 
				
			||||||
 | 
					        struct USB_ADDR_t addr;
 | 
				
			||||||
 | 
					        uint8_t _pad15[3];
 | 
				
			||||||
 | 
					        uint8_t bdtpage1;
 | 
				
			||||||
 | 
					        uint8_t _pad16[3];
 | 
				
			||||||
 | 
					        uint8_t frmnuml;
 | 
				
			||||||
 | 
					        uint8_t _pad17[3];
 | 
				
			||||||
 | 
					        struct {
 | 
				
			||||||
 | 
					                uint8_t frmnumh : 3;
 | 
				
			||||||
 | 
					                uint8_t _rsvd0 : 5;
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					        uint8_t _pad18[3];
 | 
				
			||||||
 | 
					        struct USB_TOKEN_t token;
 | 
				
			||||||
 | 
					        uint8_t _pad19[3];
 | 
				
			||||||
 | 
					        uint8_t softhld;
 | 
				
			||||||
 | 
					        uint8_t _pad20[3];
 | 
				
			||||||
 | 
					        uint8_t bdtpage2;
 | 
				
			||||||
 | 
					        uint8_t _pad21[3];
 | 
				
			||||||
 | 
					        uint8_t bdtpage3;
 | 
				
			||||||
 | 
					        uint8_t _pad22[3];
 | 
				
			||||||
 | 
					        uint8_t _pad23[0xc0 - 0xb8];
 | 
				
			||||||
 | 
					        struct {
 | 
				
			||||||
 | 
					                struct USB_ENDPT_t;
 | 
				
			||||||
 | 
					                uint8_t _pad24[3];
 | 
				
			||||||
 | 
					        } endpt[16];
 | 
				
			||||||
 | 
					        struct USB_USBCTRL_t usbctrl;
 | 
				
			||||||
 | 
					        uint8_t _pad25[3];
 | 
				
			||||||
 | 
					        struct USB_OBSERVE_t observe;
 | 
				
			||||||
 | 
					        uint8_t _pad26[3];
 | 
				
			||||||
 | 
					        struct USB_CONTROL_t control;
 | 
				
			||||||
 | 
					        uint8_t _pad27[3];
 | 
				
			||||||
 | 
					        struct USB_USBTRC0_t usbtrc0;
 | 
				
			||||||
 | 
					        uint8_t _pad28[3];
 | 
				
			||||||
 | 
					        uint8_t _pad29[4];
 | 
				
			||||||
 | 
					        uint8_t usbfrmadjust;
 | 
				
			||||||
 | 
					        uint8_t _pad30[3];
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					CTASSERT_SIZE_BYTE(struct USB_t, 0x118);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct USB_BD_t {
 | 
				
			||||||
 | 
					        struct USB_BD_BITS_t {
 | 
				
			||||||
 | 
					                union {
 | 
				
			||||||
 | 
					                        struct {
 | 
				
			||||||
 | 
					                                uint32_t _rsvd0  : 2;
 | 
				
			||||||
 | 
					                                uint32_t stall   : 1;
 | 
				
			||||||
 | 
					                                uint32_t dts     : 1;
 | 
				
			||||||
 | 
					                                uint32_t ninc    : 1;
 | 
				
			||||||
 | 
					                                uint32_t keep    : 1;
 | 
				
			||||||
 | 
					                                enum usb_data01 data01 : 1;
 | 
				
			||||||
 | 
					                                uint32_t own     : 1;
 | 
				
			||||||
 | 
					                                uint32_t _rsvd1  : 8;
 | 
				
			||||||
 | 
					                                uint32_t bc      : 10;
 | 
				
			||||||
 | 
					                                uint32_t _rsvd2  : 6;
 | 
				
			||||||
 | 
					                        };
 | 
				
			||||||
 | 
					                        struct /* processor */ {
 | 
				
			||||||
 | 
					                                uint32_t _rsvd5  : 2;
 | 
				
			||||||
 | 
					                                enum usb_tok_pid tok_pid : 4;
 | 
				
			||||||
 | 
					                                uint32_t _rsvd6  : 26;
 | 
				
			||||||
 | 
					                        };
 | 
				
			||||||
 | 
					                        uint32_t raw;
 | 
				
			||||||
 | 
					                };
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					        void *addr;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					CTASSERT_SIZE_BYTE(struct USB_BD_t, 8);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					extern volatile struct USB_t USB0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							
								
								
									
										112
									
								
								Lib/mk20dx128vlf5.bootloader.ld
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										112
									
								
								Lib/mk20dx128vlf5.bootloader.ld
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,112 @@
 | 
				
			||||||
 | 
					/* Teensyduino Core Library
 | 
				
			||||||
 | 
					 * http://www.pjrc.com/teensy/
 | 
				
			||||||
 | 
					 * Copyright (c) 2013 PJRC.COM, LLC.
 | 
				
			||||||
 | 
					 * Modifications by Jacob Alexander 2014 for use with McHCK
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * 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:
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * 1. The above copyright notice and this permission notice shall be
 | 
				
			||||||
 | 
					 * included in all copies or substantial portions of the Software.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * 2. If the Software is incorporated into a build system that allows
 | 
				
			||||||
 | 
					 * selection among a list of target devices, then similar target
 | 
				
			||||||
 | 
					 * devices manufactured by PJRC.COM must be included in the list of
 | 
				
			||||||
 | 
					 * target devices and selectable in the same manner.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * 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.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					MEMORY
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						FLASH (rx)     : ORIGIN = 0x0, LENGTH = 128K
 | 
				
			||||||
 | 
						FLASH_APP (rx) : ORIGIN = 4K, LENGTH = 128K-4K
 | 
				
			||||||
 | 
						RAM  (rwx)     : ORIGIN = 0x20000000 - 16K / 2, LENGTH = 16K
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Starting Address of the application ROM */
 | 
				
			||||||
 | 
					_app_rom = ORIGIN( FLASH_APP );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					FlexRAM = 0x14000000;
 | 
				
			||||||
 | 
					FTFL = 0x40020000;
 | 
				
			||||||
 | 
					SCB = 0xe000ed00;
 | 
				
			||||||
 | 
					USB0 = 0x40072000;
 | 
				
			||||||
 | 
					SIM = 0x40047000;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Section Definitions */
 | 
				
			||||||
 | 
					SECTIONS
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						.text :
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							. = 0;
 | 
				
			||||||
 | 
							KEEP(* (.vectors))
 | 
				
			||||||
 | 
							*(.startup*)
 | 
				
			||||||
 | 
							*(.rodata*)
 | 
				
			||||||
 | 
							. = 0x400;
 | 
				
			||||||
 | 
							KEEP(* (.flashconfig))
 | 
				
			||||||
 | 
							*(.text*)
 | 
				
			||||||
 | 
							. = ALIGN(4);
 | 
				
			||||||
 | 
							KEEP(*(.init))
 | 
				
			||||||
 | 
						} > FLASH
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						.ARM.exidx :
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							__exidx_start = .;
 | 
				
			||||||
 | 
							*(.ARM.exidx* .gnu.linkonce.armexidx.*)
 | 
				
			||||||
 | 
							__exidx_end = .;
 | 
				
			||||||
 | 
						} > FLASH
 | 
				
			||||||
 | 
						_etext = .;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						.usbdescriptortable (NOLOAD) : {
 | 
				
			||||||
 | 
							. = ALIGN(512);
 | 
				
			||||||
 | 
							*(.usbdescriptortable*)
 | 
				
			||||||
 | 
						} > RAM
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						.dmabuffers (NOLOAD) : {
 | 
				
			||||||
 | 
							. = ALIGN(4);
 | 
				
			||||||
 | 
							*(.dmabuffers*)
 | 
				
			||||||
 | 
						} > RAM
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						.usbbuffers (NOLOAD) : {
 | 
				
			||||||
 | 
							. = ALIGN(4);
 | 
				
			||||||
 | 
							*(.usbbuffers*)
 | 
				
			||||||
 | 
						} > RAM
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						.data : AT (_etext) {
 | 
				
			||||||
 | 
							. = ALIGN(4);
 | 
				
			||||||
 | 
							_sdata = .;
 | 
				
			||||||
 | 
							*(SORT_BY_ALIGNMENT(.ramtext.*) SORT_BY_ALIGNMENT(.data*))
 | 
				
			||||||
 | 
							*(.data*)
 | 
				
			||||||
 | 
							. = ALIGN(4);
 | 
				
			||||||
 | 
							_edata = .;
 | 
				
			||||||
 | 
						} > RAM
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						.noinit (NOLOAD) : {
 | 
				
			||||||
 | 
							*(.noinit*)
 | 
				
			||||||
 | 
						} > RAM
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						.bss : {
 | 
				
			||||||
 | 
							. = ALIGN(4);
 | 
				
			||||||
 | 
							_sbss = .;
 | 
				
			||||||
 | 
							*(.bss*)
 | 
				
			||||||
 | 
							*(COMMON)
 | 
				
			||||||
 | 
							. = ALIGN(4);
 | 
				
			||||||
 | 
							_ebss = .;
 | 
				
			||||||
 | 
							__bss_end = .;
 | 
				
			||||||
 | 
						} > RAM
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						_estack = ORIGIN(RAM) + LENGTH(RAM);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue