diff --git a/firmware/include_stm/nokeep.ld b/firmware/include_stm/nokeep.ld index 62d2edd..e1e84b2 100644 --- a/firmware/include_stm/nokeep.ld +++ b/firmware/include_stm/nokeep.ld @@ -11,14 +11,18 @@ MEMORY /* $0000 0000 128KB of flash/sram depending on BOOT */ /* $0002 0000 ~128MB of system reserved */ /* $0800 0000 always flash size depends on part */ -/* FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 128K */ /* 0x20000 128K */ - FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 32K /* 0x20000 128K */ +/* FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 128K */ /* 0x20000 128K 070RB */ + FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 32K /* 0x08000 32K 070C6 */ +/* FLASH0 (rx) : ORIGIN = 0x08000000, LENGTH = 2K */ /* 0x0800 2K vectors, usb, firmware update, etc */ +/* FLASH1 (rx) : ORIGIN = 0x08000800, LENGTH = 30K */ /* 0x7800 30K reset, main, & application code */ +/* FLASH2 (rx) : ORIGIN = 0x08008000, LENGTH = 96K */ /* RB ONLY 0x18000 96K */ /* $0802 0000 ~384MB of system reserved */ - /* $1FFF C800 12KB of system memory (bootloader and etc) */ + /* $1FFF C400 13KB of system memory (bootloader and etc) 070C6 */ + /* $1FFF C800 12KB of system memory (bootloader and etc) 070RB */ /* $1FFF F800 2KB of option bytes */ /* $2000 0000 always SRAM size depends on part */ -/* RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 16K */ /* 0x04000 16K */ - RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 6K /* 0x04000 16K */ +/* RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 16K */ /* 0x04000 16K 070RB */ + RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 6K /* 0x01800 6K 070C6 */ /* $2000 4000 ~512MB of system reserved */ /* $4000 0000 128KB of APB perif regs & reserved */ /* $4002 0000 17KB of AHB1 perif regs & reserved */ @@ -65,7 +69,36 @@ SECTIONS { .text : { + /* First 2KByte of flash EXCLUDES all application & main code */ + /* start with vector table */ KEEP(*(.isr_vector)) + + /* then USB code & desc tables */ + *(.usb_driver) + *(.usb_desc) + + /* hardfault & dummy handlers */ + *(.hardfault) + + /* put firmware update code at end of first 2KByte + * should allow for easier updating of that code alone + * by the application code if desired */ + *(.fw_update) + + . = 0x0800; /*update the location counter to the 3rd KByte */ + /* reset handler fixed to 0x08000800 + * that way the vector table should always be accurate */ + *(.reset_handler) + + /* usbFunctionSetup & usbFunctionWrite must be in first 64KByte of flash + * make Write first, and Setup last since Write is less likely to change + * or maybe we just want to make them fixed addresses and avoid use of usb_buff + * function pointers, possible future TODO for speedup? */ + *(.usbFuncWrite) + *(.usbFuncSetup) + + /* then everything else (application code) follows */ + *(.text*) *(.init) @@ -168,6 +201,12 @@ SECTIONS *(.fini_array) PROVIDE_HIDDEN (__fini_array_end = .); + . = ALIGN(4); + *(.fastrun) /*Placing functions in .fastrun section in RAM */ + /* This kind of breaks arm-none-eabi-size look at .map file __data_end__ for actual data size*/ + /* Really size is just combining text & data together */ + + *(.jcr) . = ALIGN(4); /* All data end */ diff --git a/firmware/include_stm/startup_ARMCM0.S b/firmware/include_stm/startup_ARMCM0.S index 1209efe..4dc51d8 100644 --- a/firmware/include_stm/startup_ARMCM0.S +++ b/firmware/include_stm/startup_ARMCM0.S @@ -122,7 +122,12 @@ __isr_vector: .size __isr_vector, . - __isr_vector - .text + //;.text + //;want to move this to a fixed flash location so the lower + //;vector/usb section of flash doesn't need to be updated for + //;main/application firmware updates. + //;want the reset handler to always reside @ 0x08000800 + .section .reset_handler .thumb .thumb_func .align 1 @@ -268,6 +273,9 @@ Reset_Handler: .pool .size Reset_Handler, . - Reset_Handler + +//;want the default handler to be in same space as hardfault + .section .hardfault .align 1 .thumb_func .weak Default_Handler diff --git a/firmware/source/usb.c b/firmware/source/usb.c index 58d9792..9baca81 100644 --- a/firmware/source/usb.c +++ b/firmware/source/usb.c @@ -46,10 +46,10 @@ USB_PUBLIC usbMsgLen_t usbFunctionSetup(uchar data[8]) { #endif #ifdef STM_CORE -#define NOINLINE __attribute__ ((section (".text"), noinline, noclone)) -//NOINLINE should keep these functions at beinging of flash (.text) +#define USBSETUP __attribute__ ((section (".usbFuncSetup"), noinline, noclone)) +//noinline should keep these functions at beinging of flash (.text) //they need to be in the first 64KByte which is non issue with C6, but could prob with RB -NOINLINE uint16_t usbFunctionSetup(uint8_t data[8]) { +USBSETUP uint16_t usbFunctionSetup(uint8_t data[8]) { #endif @@ -279,7 +279,10 @@ USB_PUBLIC uchar usbFunctionWrite(uchar *data, uchar len) { #endif #ifdef STM_CORE -NOINLINE uint8_t usbFunctionWrite(uint8_t *data, uint8_t len) { +#define USBWRITE __attribute__ ((section (".usbFuncWrite"), noinline, noclone)) +//noinline should keep these functions at beinging of flash (.text) +//they need to be in the first 64KByte which is non issue with C6, but could prob with RB +USBWRITE uint8_t usbFunctionWrite(uint8_t *data, uint8_t len) { #endif //defined and controled by buffer.c diff --git a/firmware/source_stm_only/fwupdate.c b/firmware/source_stm_only/fwupdate.c new file mode 100644 index 0000000..c301665 --- /dev/null +++ b/firmware/source_stm_only/fwupdate.c @@ -0,0 +1,17 @@ +#include "fwupdate.h" + + +FWUPDATE void erase_main() +{ + //usb driver & this code resisdes in first 2KByte of last (0x0800_0800) + //The smaller STMF070C6 has 32KByte of flash, and larger STMF070RB has 128KByte + //C6 flash is split into 1KB pages + //RB flash is split into 2KB pages + //So the C6 must leave first two pages alone, and RB only the first page + //But they're both leaving the first 2KByte untouched + //And erasing the 30KByte that follows + //For now we're ignoring the extra 96KByte of additional flash that the RB contains + + while(1){ + } +} diff --git a/firmware/source_stm_only/fwupdate.h b/firmware/source_stm_only/fwupdate.h new file mode 100644 index 0000000..7753985 --- /dev/null +++ b/firmware/source_stm_only/fwupdate.h @@ -0,0 +1,15 @@ +#ifndef _fwupdate_h +#define _fwupdate_h + + +//include target chip port definition library files +#include + +//#define FWUPDATE __attribute__ ((section (".fw_update"))) +#define FWUPDATE __attribute__ ((section (".fw_update"), noinline, noclone)) + + +void erase_main(); + + +#endif diff --git a/firmware/source_stm_only/hardfault.c b/firmware/source_stm_only/hardfault.c new file mode 100644 index 0000000..f47d340 --- /dev/null +++ b/firmware/source_stm_only/hardfault.c @@ -0,0 +1,37 @@ + + +//want this to be in first 2KByte of USB boot space so the handler should typically be present +#define HARDFAULT __attribute__ ((section (".hardfault"))) +HARDFAULT void HardFault_Handler(void) +{ + + //TODO test out this function + //should retrieve PC of the instruction that follows whatever caused the hardfault + //This didn't work for me earlier bc the stack itself was broke +// asm( +// "movs r0, #4 \n" +// "movs r1, lr \n" +// "tst r0, r1 \n" +// "beq _MSP \n" +// "mrs r0, psp \n" +// "b _HALT \n" +// "_MSP: \n" +// " mrs r0, msp \n" +// "_HALT: \n" +// " ldr r1, [r0,#20] \n" +// //" bkpt #0 \n" +// ); + + asm( + "ldr r0, dead\n" + "b loop\n" + //"bkpt\n" + ".p2align 2\n" + "dead:\n" + ".word 0xDEAD0123\n" //MSP for bootloader + "loop:\n" + ); + + while (1) { + } +} diff --git a/firmware/source_stm_only/stm_init.c b/firmware/source_stm_only/stm_init.c index 752bd07..198ff26 100644 --- a/firmware/source_stm_only/stm_init.c +++ b/firmware/source_stm_only/stm_init.c @@ -1,29 +1,6 @@ #include "stm_init.h" -void HardFault_Handler(void) -{ - - //TODO test out this function - //should retrieve PC of the instruction that follows whatever caused the hardfault - //This didn't work for me earlier bc the stack itself was broke -// asm( -// "movs r0, #4 \n" -// "movs r1, lr \n" -// "tst r0, r1 \n" -// "beq _MSP \n" -// "mrs r0, psp \n" -// "b _HALT \n" -// "_MSP: \n" -// " mrs r0, msp \n" -// "_HALT: \n" -// " ldr r1, [r0,#20] \n" -// //" bkpt #0 \n" -// ); - - while (1) { - } -} /* stm32f0x2 devices have HSI48 available which isn't on stm32f0x0 devices * I'm primarily targetting f070 devices which will require external xtal diff --git a/firmware/source_stm_only/usb_descriptors.h b/firmware/source_stm_only/usb_descriptors.h index ff367d9..ff0563a 100644 --- a/firmware/source_stm_only/usb_descriptors.h +++ b/firmware/source_stm_only/usb_descriptors.h @@ -1,6 +1,8 @@ #ifndef _usb_descriptors_h #define _usb_descriptors_h +#define USBDESC __attribute__ ((section (".usb_desc"))) + /* Contains all the device, configuration, interface, endpoint, and string descriptor definitions * The excellent breakdown of the USB standard and field comments have been copy pasted from the * almighty documentation "USB in a Nutshell" article by BeyondLogic: @@ -19,7 +21,7 @@ #define DESC_TYPE_ENDPOINT 0x05 #define DEVICE_DESC_LEN 18 -const uint8_t device_desc[DEVICE_DESC_LEN] = { +USBDESC const uint8_t device_desc[DEVICE_DESC_LEN] = { // 0 bLength 1 Number Size of the Descriptor in Bytes (18 bytes) DEVICE_DESC_LEN, // 1 bDescriptorType 1 Constant Device Descriptor (0x01) @@ -93,7 +95,7 @@ const uint8_t device_desc[DEVICE_DESC_LEN] = { //NOTE: current table broken if total is greater 255 bytes!!! #define CONFIG_TOTAL_LEN (CONFIG_DESC_LEN + INTERFACE_DESC_LEN + ENDPOINT_DESC_LEN) #define wTotalLength 2 //offset of wTotalLength in descriptor array -const uint8_t config_desc[CONFIG_TOTAL_LEN] = { +USBDESC const uint8_t config_desc[CONFIG_TOTAL_LEN] = { // Off Field Size Value Description // 0 bLength 1 Number Size of Descriptor in Bytes CONFIG_DESC_LEN, @@ -224,7 +226,7 @@ const uint8_t config_desc[CONFIG_TOTAL_LEN] = { // Universal Serial Bus Language Identifiers (LANGIDs) version 1.0 // #define STRING0_DESC_LEN 4 -const uint8_t string0_desc[STRING0_DESC_LEN] = { +USBDESC const uint8_t string0_desc[STRING0_DESC_LEN] = { // Off Field Size Value Description // 0 bLength 1 Number Size of Descriptor in Bytes STRING0_DESC_LEN, @@ -255,7 +257,7 @@ const uint8_t string0_desc[STRING0_DESC_LEN] = { //Defining string arrays as uint16_t effectively makes the strings UTF-16 as required #define BYTES_PER_HWORD 2 #define STRING1_DESC_LEN (21*BYTES_PER_HWORD) //characters plus 1 for bLength & bDescriptorType -const uint16_t string1_desc[STRING1_DESC_LEN] = { +USBDESC const uint16_t string1_desc[STRING1_DESC_LEN] = { // 0 bLength 1 Number Size of Descriptor in Bytes // 1 bDescriptorType 1 Constant String Descriptor (0x03) ((uint16_t)DESC_TYPE_STRING<<8 | STRING1_DESC_LEN), @@ -263,7 +265,7 @@ const uint16_t string1_desc[STRING1_DESC_LEN] = { 'I','n','f','i','n','i','t','e','N','e','s','L','i','v','e','s','.','c','o','m'}; #define STRING2_DESC_LEN (15*BYTES_PER_HWORD) //characters plus 1 for bLength & bDescriptorType -const uint16_t string2_desc[STRING2_DESC_LEN] = { +USBDESC const uint16_t string2_desc[STRING2_DESC_LEN] = { // 0 bLength 1 Number Size of Descriptor in Bytes // 1 bDescriptorType 1 Constant String Descriptor (0x03) ((uint16_t)DESC_TYPE_STRING<<8 | STRING2_DESC_LEN), diff --git a/firmware/source_stm_only/usbstm.c b/firmware/source_stm_only/usbstm.c index d4033a7..5b069ad 100644 --- a/firmware/source_stm_only/usbstm.c +++ b/firmware/source_stm_only/usbstm.c @@ -6,7 +6,7 @@ //since usb drivers don't use any .data nor .bss space //static int log = 0; -void usb_reset_recovery(){ +USBDRIVER void usb_reset_recovery(){ // USB->CNTR |= USB_CNTR_FRES; // USB->CNTR &= ~USB_CNTR_FRES; @@ -165,7 +165,7 @@ void usb_reset_recovery(){ //uint16_t volatile (* const usb_buff)[512] = (void*)USB_PMAADDR; //this was suggestion by: http://a3f.at/articles/register-syntax-sugar //which errors on compilation due to assigning of type array -uint16_t volatile (* const usb_buff) = (void*)USB_PMAADDR; +USBDRIVER uint16_t volatile (* const usb_buff) = (void*)USB_PMAADDR; //static uint16_t num_bytes_req; @@ -207,7 +207,7 @@ uint16_t volatile (* const usb_buff) = (void*)USB_PMAADDR; //#define TSSOP20 //defined when using TSSOP-20 part to get PA11/12 alternate mapping to the pins //prereq: USB block's clock must be initialized prior to calling -void init_usb() +USBDRIVER void init_usb() { //initialize the clock @@ -433,7 +433,7 @@ void init_usb() //currently hardcoded for EP0 only //num_bytes_sending, num_bytes_xfrd, and *usbMsgPtr must be initialized prior to entry -static void control_xfr_in(){ +USBDRIVER static void control_xfr_in(){ //determine if have data remaining to be sent // We should never get to this point, if we did there was an error and should prob send STALL @@ -570,7 +570,7 @@ static void control_xfr_in(){ //return number of bytes expected -static uint16_t standard_req_out( usbRequest_t *spacket ){ +USBDRIVER static uint16_t standard_req_out( usbRequest_t *spacket ){ switch ( spacket->bRequest ) { @@ -614,7 +614,7 @@ static uint16_t standard_req_out( usbRequest_t *spacket ){ } -static uint16_t standard_req_in( usbRequest_t *spacket ){ +USBDRIVER static uint16_t standard_req_in( usbRequest_t *spacket ){ switch ( spacket->bRequest ) { @@ -694,7 +694,7 @@ static uint16_t standard_req_in( usbRequest_t *spacket ){ //USB IRQ handler calls this function after recieving a control setup packet //function is responsible for preparing follow on data/status transfers to complete control xfr //must set everything up for control_xfr_in/out functions to be called during data packets -static void control_xfr_init( usbRequest_t *spacket ) { +USBDRIVER static void control_xfr_init( usbRequest_t *spacket ) { //determine number of requested data payload bytes num_bytes_req = spacket->wLength; @@ -748,15 +748,29 @@ static void control_xfr_init( usbRequest_t *spacket ) { //to do this the usb code can't directly call application code (usbFunction Setup/Write) //need the application code to tell the usb code where the functions are using variables + //call the usbFunctionSetup function with some function pointer magic typedef uint16_t (*pFunction)(uint8_t data[8]); pFunction JumpToApplication; - JumpToApplication = (uint16_t (*)(uint8_t data[8])) ((0x08000000)); //base of flash - //application main makes the following assignment at powerup - //usbfuncsetup = (uint32_t) &usbFunctionSetup; //should only assign lower 16bits - JumpToApplication += usbfuncsetup; + + //but this is where we need to snoop on the setup packet to determine + //if it's a firmware update packet +// if (fwupdate logic) { +// //send this packet to the firmware updater +// erase_main(); +// } +// else { //normal setup packet send to application code + JumpToApplication = (uint16_t (*)(uint8_t data[8])) ((0x08000000)); //base of flash + //application main makes the following assignment at powerup + //usbfuncsetup = (uint32_t) &usbFunctionSetup; //should only assign lower 16bits + JumpToApplication += usbfuncsetup; + +// } + + //perform the actual jump/call num_bytes_sending = JumpToApplication( (uint8_t*) spacket ); + } @@ -866,7 +880,7 @@ static void control_xfr_init( usbRequest_t *spacket ) { //USB interrupt status register (USB_ISTR) //This register contains the status of all the interrupt sources allowing application //software to determine, which events caused an interrupt request. -void USB_IRQHandler(void) +USBDRIVER void USB_IRQHandler(void) { //communications between application code & USB to prevent direct calls diff --git a/firmware/source_stm_only/usbstm.h b/firmware/source_stm_only/usbstm.h index 07b89f7..5975814 100644 --- a/firmware/source_stm_only/usbstm.h +++ b/firmware/source_stm_only/usbstm.h @@ -5,6 +5,13 @@ //include target chip port definition library files #include +#include "fwupdate.h" + +#define USBDRIVER __attribute__ ((section (".usb_driver"))) +//let the compiler perform inline optization, it'll keep code smaller +//this code is all exactly where we want it anyway and separate from +//application code, so inlining is not just okay, it's good! +//#define USBDRIVER __attribute__ ((section (".usb_boot"), noinline, noclone)) //clear RX interrupt //set tx field to keep from accidentally clearing //mask out toggle feilds making them zero //clear rx bit removing active interrupt