- McHCK uses FLL instead of the PLL for USB (startup, not usb init) - Added optional debug for the pjrc USB module - Cleaned up compiler flagssimple
set( MacroModule "PartialMap" ) | set( MacroModule "PartialMap" ) | ||||
##| Sends the current list of usb key codes through USB HID | ##| Sends the current list of usb key codes through USB HID | ||||
set( OutputModule "uartOut" ) | |||||
set( OutputModule "pjrcUSB" ) | |||||
##| Debugging source to use, each module has it's own set of defines that it sets | ##| Debugging source to use, each module has it's own set of defines that it sets | ||||
set( DebugModule "full" ) | set( DebugModule "full" ) |
dPrintStr( tmpStr ); | dPrintStr( tmpStr ); | ||||
} | } | ||||
void printHex32_op( uint32_t in, uint8_t op ) | |||||
{ | |||||
// With an op of 1, the max number of characters is 6 + 1 for null | |||||
// e.g. "0xFFFF\0" | |||||
// op 2 and 4 require fewer characters (2+1 and 4+1 respectively) | |||||
char tmpStr[7]; | |||||
// Convert number | |||||
hex32ToStr_op( in, tmpStr, op ); | |||||
// Print number | |||||
dPrintStr( tmpStr ); | |||||
} | |||||
// String Functions | // String Functions | ||||
} | } | ||||
void hex32ToStr_op( uint32_t in, char* out, uint8_t op ) | |||||
{ | |||||
// Position container | |||||
uint32_t pos = 0; | |||||
// Evaluate through digits as hex | |||||
do | |||||
{ | |||||
uint32_t cur = in % 16; | |||||
out[pos++] = cur + (( cur < 10 ) ? '0' : 'A' - 10); | |||||
} | |||||
while ( (in /= 16) > 0 ); | |||||
// Output formatting options | |||||
switch ( op ) | |||||
{ | |||||
case 1: // Add 0x | |||||
out[pos++] = 'x'; | |||||
out[pos++] = '0'; | |||||
break; | |||||
case 2: // 8-bit padding | |||||
case 4: // 16-bit padding | |||||
while ( pos < op ) | |||||
out[pos++] = '0'; | |||||
break; | |||||
} | |||||
// Append null | |||||
out[pos] = '\0'; | |||||
// Reverse the string to the correct order | |||||
revsStr(out); | |||||
} | |||||
void revsStr( char* in ) | void revsStr( char* in ) | ||||
{ | { | ||||
// Iterators | // Iterators |
// Printing numbers | // Printing numbers | ||||
#define printHex(hex) printHex_op(hex, 1) | |||||
#define printHex(hex) printHex_op(hex, 1) | |||||
#define printHex32(hex) printHex32_op(hex, 1) | |||||
void printInt8 ( uint8_t in ); | |||||
void printInt16 ( uint16_t in ); | |||||
void printInt32 ( uint32_t in ); | |||||
void printHex_op( uint16_t in, uint8_t op ); | |||||
void printInt8 ( uint8_t in ); | |||||
void printInt16 ( uint16_t in ); | |||||
void printInt32 ( uint32_t in ); | |||||
void printHex_op ( uint16_t in, uint8_t op ); | |||||
void printHex32_op( uint32_t in, uint8_t op ); | |||||
// String Functions | // String Functions | ||||
#define hexToStr(hex, out) hexToStr_op(hex, out, 1) | #define hexToStr(hex, out) hexToStr_op(hex, out, 1) | ||||
void int8ToStr ( uint8_t in, char* out ); | |||||
void int16ToStr ( uint16_t in, char* out ); | |||||
void int32ToStr ( uint32_t in, char* out ); | |||||
void hexToStr_op( uint16_t in, char* out, uint8_t op ); | |||||
void revsStr ( char* in ); | |||||
uint16_t lenStr ( char* in ); | |||||
int16_t eqStr ( char* str1, char* str2 ); // Returns -1 if identical, last character of str1 comparison (0 if str1 is like str2) | |||||
int decToInt ( char* in ); // Returns the int representation of a string | |||||
void int8ToStr ( uint8_t in, char* out ); | |||||
void int16ToStr ( uint16_t in, char* out ); | |||||
void int32ToStr ( uint32_t in, char* out ); | |||||
void hexToStr_op ( uint16_t in, char* out, uint8_t op ); | |||||
void hex32ToStr_op( uint32_t in, char* out, uint8_t op ); | |||||
void revsStr ( char* in ); | |||||
uint16_t lenStr ( char* in ); | |||||
int16_t eqStr ( char* str1, char* str2 ); // Returns -1 if identical, last character of str1 comparison (0 if str1 is like str2) | |||||
int decToInt ( char* in ); // Returns the int representation of a string | |||||
#endif | #endif | ||||
#| Tuning Options | #| Tuning Options | ||||
#| -f...: tuning, see GCC manual | #| -f...: tuning, see GCC manual | ||||
#| NOTE: -fshort-wchar is specified to allow USB strings be passed conveniently | #| NOTE: -fshort-wchar is specified to allow USB strings be passed conveniently | ||||
set( TUNING "-mthumb -nostdlib -fdata-sections -ffunction-sections -fshort-wchar -fno-builtin -flto -fno-use-linker-plugin" ) | |||||
set( TUNING "-mthumb -nostdlib -fdata-sections -ffunction-sections -fshort-wchar -fno-builtin" ) | |||||
#| Optimization level, can be [0, 1, 2, 3, s]. | #| Optimization level, can be [0, 1, 2, 3, s]. |
#| Convert the .ELF into a .bin to load onto the McHCK | #| Convert the .ELF into a .bin to load onto the McHCK | ||||
set( TARGET_BIN ${TARGET}.dfu.bin ) | |||||
set( TARGET_BIN ${TARGET}.bin.dfu ) | |||||
add_custom_command( TARGET ${TARGET_ELF} POST_BUILD | add_custom_command( TARGET ${TARGET_ELF} POST_BUILD | ||||
COMMAND ${CMAKE_OBJCOPY} ${BIN_FLAGS} ${TARGET_ELF} ${TARGET_BIN} | COMMAND ${CMAKE_OBJCOPY} ${BIN_FLAGS} ${TARGET_ELF} ${TARGET_BIN} | ||||
COMMENT "Creating binary file to load: ${TARGET_BIN}" | COMMENT "Creating binary file to load: ${TARGET_BIN}" |
// Local Includes | // Local Includes | ||||
#include "mk20dx.h" | #include "mk20dx.h" | ||||
#include <print.h> | |||||
uint32_t *src = &_etext; | uint32_t *src = &_etext; | ||||
uint32_t *dest = &_sdata; | uint32_t *dest = &_sdata; | ||||
/* Disable Watchdog */ | |||||
// Disable Watchdog | |||||
WDOG_UNLOCK = WDOG_UNLOCK_SEQ1; | WDOG_UNLOCK = WDOG_UNLOCK_SEQ1; | ||||
WDOG_UNLOCK = WDOG_UNLOCK_SEQ2; | WDOG_UNLOCK = WDOG_UNLOCK_SEQ2; | ||||
WDOG_STCTRLH = WDOG_STCTRLH_ALLOWUPDATE; | WDOG_STCTRLH = WDOG_STCTRLH_ALLOWUPDATE; | ||||
// enable clocks to always-used peripherals | |||||
#if defined(_mk20dx128_) || defined(_mk20dx128vlf5_) | |||||
SIM_SCGC5 = 0x00043F82; // clocks active to all GPIO | |||||
SIM_SCGC6 = SIM_SCGC6_RTC | SIM_SCGC6_FTM0 | SIM_SCGC6_FTM1 | SIM_SCGC6_ADC0 | SIM_SCGC6_FTFL; | |||||
// Enable clocks to always-used peripherals | |||||
SIM_SCGC5 = 0x00043F82; // Clocks active to all GPIO | |||||
SIM_SCGC6 = SIM_SCGC6_FTM0 | SIM_SCGC6_FTM1 | SIM_SCGC6_ADC0 | SIM_SCGC6_FTFL; | |||||
#if defined(_mk20dx128_) | |||||
SIM_SCGC6 |= SIM_SCGC6_RTC; | |||||
#elif defined(_mk20dx256_) | #elif defined(_mk20dx256_) | ||||
SIM_SCGC3 = SIM_SCGC3_ADC1 | SIM_SCGC3_FTM2; | SIM_SCGC3 = SIM_SCGC3_ADC1 | SIM_SCGC3_FTM2; | ||||
SIM_SCGC5 = 0x00043F82; // clocks active to all GPIO | |||||
SIM_SCGC6 = SIM_SCGC6_RTC | SIM_SCGC6_FTM0 | SIM_SCGC6_FTM1 | SIM_SCGC6_ADC0 | SIM_SCGC6_FTFL; | |||||
SIM_SCGC6 |= SIM_SCGC6_RTC; | |||||
#endif | #endif | ||||
#if defined(_mk20dx128_) || defined(_mk20dx256_) // Teensy 3s | #if defined(_mk20dx128_) || defined(_mk20dx256_) // Teensy 3s | ||||
#endif | #endif | ||||
// release I/O pins hold, if we woke up from VLLS mode | // release I/O pins hold, if we woke up from VLLS mode | ||||
if (PMC_REGSC & PMC_REGSC_ACKISO) PMC_REGSC |= PMC_REGSC_ACKISO; | |||||
if ( PMC_REGSC & PMC_REGSC_ACKISO ) | |||||
{ | |||||
PMC_REGSC |= PMC_REGSC_ACKISO; | |||||
} | |||||
// Prepare RAM | // Prepare RAM | ||||
while ( dest < &_edata ) *dest++ = *src++; | while ( dest < &_edata ) *dest++ = *src++; | ||||
// MCHCK | // MCHCK | ||||
#if defined(_mk20dx128vlf5_) | #if defined(_mk20dx128vlf5_) | ||||
/* FLL at 48MHz */ | |||||
// Default all interrupts to medium priority level | |||||
for ( unsigned int i = 0; i < NVIC_NUM_INTERRUPTS; i++ ) | |||||
{ | |||||
NVIC_SET_PRIORITY( i, 128 ); | |||||
} | |||||
// FLL at 48MHz | |||||
MCG_C4 = MCG_C4_DMX32 | MCG_C4_DRST_DRS( 1 ); | MCG_C4 = MCG_C4_DMX32 | MCG_C4_DRST_DRS( 1 ); | ||||
//SIM_SOPT2 = SIM_SOPT2_PLLFLLSEL; | |||||
SIM_SOPT2 = SIM_SOPT2_USBSRC | SIM_SOPT2_PLLFLLSEL | SIM_SOPT2_TRACECLKSEL | SIM_SOPT2_CLKOUTSEL( 6 ); | |||||
// USB Clock and FLL select | |||||
SIM_SOPT2 = SIM_SOPT2_USBSRC | SIM_SOPT2_TRACECLKSEL; | |||||
// Teensy 3.0 and 3.1 | // Teensy 3.0 and 3.1 | ||||
#else | #else |
*(.rodata*) | *(.rodata*) | ||||
. = ALIGN(4); | . = ALIGN(4); | ||||
KEEP(*(.init)) | KEEP(*(.init)) | ||||
. = ALIGN(4); | . = ALIGN(4); | ||||
__preinit_array_start = .; | __preinit_array_start = .; | ||||
KEEP (*(.preinit_array)) | KEEP (*(.preinit_array)) | ||||
KEEP (*(SORT(.init_array.*))) | KEEP (*(SORT(.init_array.*))) | ||||
KEEP (*(.init_array)) | KEEP (*(.init_array)) | ||||
__init_array_end = .; | __init_array_end = .; | ||||
} > FLASH = 0xFF | } > FLASH = 0xFF | ||||
.ARM.exidx : { | .ARM.exidx : { |
KEEP(* (.vectors)) | KEEP(* (.vectors)) | ||||
*(.startup*) | *(.startup*) | ||||
*(.text*) | *(.text*) | ||||
*(.rodata*) | |||||
. = ALIGN(4); | . = ALIGN(4); | ||||
KEEP(*(.init)) | KEEP(*(.init)) | ||||
} > FLASH | } > FLASH |
/* Teensyduino Core Library | /* Teensyduino Core Library | ||||
* http://www.pjrc.com/teensy/ | * http://www.pjrc.com/teensy/ | ||||
* Copyright (c) 2013 PJRC.COM, LLC. | * Copyright (c) 2013 PJRC.COM, LLC. | ||||
* Modified by Jacob Alexander 2013-2014 | |||||
* | * | ||||
* Permission is hereby granted, free of charge, to any person obtaining | * Permission is hereby granted, free of charge, to any person obtaining | ||||
* a copy of this software and associated documentation files (the | * a copy of this software and associated documentation files (the | ||||
* permit persons to whom the Software is furnished to do so, subject to | * permit persons to whom the Software is furnished to do so, subject to | ||||
* the following conditions: | * the following conditions: | ||||
* | * | ||||
* 1. The above copyright notice and this permission notice shall be | |||||
* 1. The above copyright notice and this permission notice shall be | |||||
* included in all copies or substantial portions of the Software. | * included in all copies or substantial portions of the Software. | ||||
* | * | ||||
* 2. If the Software is incorporated into a build system that allows | |||||
* 2. If the Software is incorporated into a build system that allows | |||||
* selection among a list of target devices, then similar target | * selection among a list of target devices, then similar target | ||||
* devices manufactured by PJRC.COM must be included in the list of | * devices manufactured by PJRC.COM must be included in the list of | ||||
* target devices and selectable in the same manner. | * target devices and selectable in the same manner. | ||||
* SOFTWARE. | * SOFTWARE. | ||||
*/ | */ | ||||
// Project Includes | |||||
#include <Lib/OutputLib.h> | #include <Lib/OutputLib.h> | ||||
#include <print.h> | |||||
// Local Includes | |||||
#include "usb_dev.h" | #include "usb_dev.h" | ||||
#include "usb_mem.h" | #include "usb_mem.h" | ||||
volatile uint8_t usb_reboot_timer = 0; | volatile uint8_t usb_reboot_timer = 0; | ||||
static void endpoint0_stall(void) | |||||
static void endpoint0_stall() | |||||
{ | { | ||||
//print("STALL"); | |||||
USB0_ENDPT0 = USB_ENDPT_EPSTALL | USB_ENDPT_EPRXEN | USB_ENDPT_EPTXEN | USB_ENDPT_EPHSHK; | USB0_ENDPT0 = USB_ENDPT_EPSTALL | USB_ENDPT_EPRXEN | USB_ENDPT_EPTXEN | USB_ENDPT_EPHSHK; | ||||
} | } | ||||
static void endpoint0_transmit(const void *data, uint32_t len) | static void endpoint0_transmit(const void *data, uint32_t len) | ||||
{ | { | ||||
//print("TRANSMIT"); | |||||
#if 0 | #if 0 | ||||
serial_print("tx0:"); | serial_print("tx0:"); | ||||
serial_phex32((uint32_t)data); | serial_phex32((uint32_t)data); | ||||
static uint8_t reply_buffer[8]; | static uint8_t reply_buffer[8]; | ||||
static void usb_setup(void) | |||||
static void usb_setup() | |||||
{ | { | ||||
//print("SETUP"); | |||||
const uint8_t *data = NULL; | const uint8_t *data = NULL; | ||||
uint32_t datalen = 0; | uint32_t datalen = 0; | ||||
const usb_descriptor_list_t *list; | const usb_descriptor_list_t *list; | ||||
static void usb_control(uint32_t stat) | static void usb_control(uint32_t stat) | ||||
{ | { | ||||
//print("CONTROL"); | |||||
bdt_t *b; | bdt_t *b; | ||||
uint32_t pid, size; | uint32_t pid, size; | ||||
uint8_t *buf; | uint8_t *buf; | ||||
usb_packet_t *usb_rx(uint32_t endpoint) | usb_packet_t *usb_rx(uint32_t endpoint) | ||||
{ | { | ||||
//print("USB RX"); | |||||
usb_packet_t *ret; | usb_packet_t *ret; | ||||
endpoint--; | endpoint--; | ||||
if (endpoint >= NUM_ENDPOINTS) return NULL; | if (endpoint >= NUM_ENDPOINTS) return NULL; | ||||
// | // | ||||
void usb_rx_memory(usb_packet_t *packet) | void usb_rx_memory(usb_packet_t *packet) | ||||
{ | { | ||||
//print("USB RX MEMORY"); | |||||
unsigned int i; | unsigned int i; | ||||
const uint8_t *cfg; | const uint8_t *cfg; | ||||
__enable_irq(); | __enable_irq(); | ||||
// we should never reach this point. If we get here, it means | // we should never reach this point. If we get here, it means | ||||
// usb_rx_memory_needed was set greater than zero, but no memory | // usb_rx_memory_needed was set greater than zero, but no memory | ||||
// was actually needed. | |||||
// was actually needed. | |||||
usb_rx_memory_needed = 0; | usb_rx_memory_needed = 0; | ||||
usb_free(packet); | usb_free(packet); | ||||
return; | return; | ||||
} | } | ||||
void usb_isr(void) | |||||
void usb_isr() | |||||
{ | { | ||||
uint8_t status, stat, t; | uint8_t status, stat, t; | ||||
//serial_print("\n"); | //serial_print("\n"); | ||||
restart: | restart: | ||||
status = USB0_ISTAT; | status = USB0_ISTAT; | ||||
/* | |||||
print("USB ISR STATUS: "); | |||||
printHex( status ); | |||||
print( NL ); | |||||
*/ | |||||
if ((status & USB_INTEN_SOFTOKEN /* 04 */ )) { | if ((status & USB_INTEN_SOFTOKEN /* 04 */ )) { | ||||
if (usb_configuration) { | if (usb_configuration) { | ||||
void usb_init(void) | |||||
void usb_init() | |||||
{ | { | ||||
int i; | |||||
//serial_begin(BAUD2DIV(115200)); | |||||
//serial_print("usb_init\n"); | |||||
//usb_init_serialnumber(); | |||||
//print("USB INIT"); | |||||
for (i=0; i <= NUM_ENDPOINTS*4; i++) { | |||||
// Clear out endpoints table | |||||
for ( int i = 0; i <= NUM_ENDPOINTS * 4; i++ ) | |||||
{ | |||||
table[i].desc = 0; | table[i].desc = 0; | ||||
table[i].addr = 0; | table[i].addr = 0; | ||||
} | } | ||||
// reset USB module | // reset USB module | ||||
USB0_USBTRC0 = USB_USBTRC_USBRESET; | USB0_USBTRC0 = USB_USBTRC_USBRESET; | ||||
while ((USB0_USBTRC0 & USB_USBTRC_USBRESET) != 0) ; // wait for reset to end | |||||
while ( (USB0_USBTRC0 & USB_USBTRC_USBRESET) != 0 ); // wait for reset to end | |||||
// set desc table base addr | // set desc table base addr | ||||
USB0_BDTPAGE1 = ((uint32_t)table) >> 8; | USB0_BDTPAGE1 = ((uint32_t)table) >> 8; | ||||
USB0_INTEN = USB_INTEN_USBRSTEN; | USB0_INTEN = USB_INTEN_USBRSTEN; | ||||
// enable interrupt in NVIC... | // enable interrupt in NVIC... | ||||
NVIC_SET_PRIORITY(IRQ_USBOTG, 112); | |||||
NVIC_ENABLE_IRQ(IRQ_USBOTG); | |||||
NVIC_SET_PRIORITY( IRQ_USBOTG, 112 ); | |||||
NVIC_ENABLE_IRQ( IRQ_USBOTG ); | |||||
// enable d+ pullup | // enable d+ pullup | ||||
USB0_CONTROL = USB_CONTROL_DPPULLUPNONOTG; | USB0_CONTROL = USB_CONTROL_DPPULLUPNONOTG; | ||||
// return 0 if the USB is not configured, or the configuration | // return 0 if the USB is not configured, or the configuration | ||||
// number selected by the HOST | // number selected by the HOST | ||||
uint8_t usb_configured(void) | |||||
uint8_t usb_configured() | |||||
{ | { | ||||
return usb_configuration; | return usb_configuration; | ||||
} | } |
#include "usb_mem.h" | #include "usb_mem.h" | ||||
#include "usb_desc.h" | #include "usb_desc.h" | ||||
void usb_init(void); | |||||
uint8_t usb_configured(void); // is the USB port configured | |||||
void usb_isr(void); | |||||
void usb_init(); | |||||
uint8_t usb_configured(); // is the USB port configured | |||||
void usb_isr(); | |||||
usb_packet_t *usb_rx(uint32_t endpoint); | usb_packet_t *usb_rx(uint32_t endpoint); | ||||
uint32_t usb_tx_byte_count(uint32_t endpoint); | uint32_t usb_tx_byte_count(uint32_t endpoint); | ||||
uint32_t usb_tx_packet_count(uint32_t endpoint); | uint32_t usb_tx_packet_count(uint32_t endpoint); |
// If the Teensy is powered without a PC connected to the USB port, | // If the Teensy is powered without a PC connected to the USB port, | ||||
// this will wait forever. | // this will wait forever. | ||||
usb_init(); | usb_init(); | ||||
#include <led.h> | |||||
init_errorLED(); | |||||
errorLED( 1 ); | |||||
while(1); | |||||
while ( !usb_configured() ) /* wait */ ; | while ( !usb_configured() ) /* wait */ ; | ||||
// Register USB Output CLI dictionary | // Register USB Output CLI dictionary |
// If the Teensy is powered without a PC connected to the USB port, | // If the Teensy is powered without a PC connected to the USB port, | ||||
// this will wait forever. | // this will wait forever. | ||||
usb_init(); | usb_init(); | ||||
/* | |||||
#include <led.h> | |||||
init_errorLED(); | |||||
errorLED( 1 ); | |||||
while(1); | |||||
*/ | |||||
// Setup UART | // Setup UART | ||||
uart_serial_setup(); | uart_serial_setup(); | ||||