diff --git a/platformio.ini b/platformio.ini index 934fe817..994f6b4c 100644 --- a/platformio.ini +++ b/platformio.ini @@ -58,10 +58,10 @@ platform = ststm32 framework = arduino ;board = genericSTM32F407VET6 board = black_f407ve -lib_deps = EEPROM +;lib_deps = EEPROM board_build.core = stm32 ;build_flags = -fpermissive -std=gnu++11 -UBOARD_NR_GPIO_PINS -DCORE_STM32_OFFICIAL -DSRAM_AS_EEPROM -build_flags = -fpermissive -std=gnu++11 -UBOARD_NR_GPIO_PINS -DCORE_STM32_OFFICIAL -DSPI_AS_EEPROM -DMENU_USB_SERIAL +build_flags = -fpermissive -std=gnu++11 -UBOARD_NR_GPIO_PINS -DCORE_STM32_OFFICIAL -DSPIFLASH_AS_EEPROM -DUSBCON -DUSBD_VID=0x0483 "-DUSB_MANUFACTURER=\"Unknown\"" "-DUSB_PRODUCT=\"BLACK_F407VE\"" -DHAL_PCD_MODULE_ENABLED -DUSBD_USE_CDC -DHAL_UART_MODULE_ENABLED upload_protocol = serial [env:bluepill_f103c8] diff --git a/reference/speeduino.ini b/reference/speeduino.ini index 03601a12..265408f1 100644 --- a/reference/speeduino.ini +++ b/reference/speeduino.ini @@ -213,7 +213,7 @@ page = 1 unused1-3c = bits, U08, 3, [2:7], "MAP", "TPS", "INVALID", "INVALID" wueRates = array, U08, 4, [10], "%", 1.0, 0.0, 0.0, 255, 0 crankingPct = scalar, U08, 14, "%", 1.0, 0.0, 0.0, 255, 0 - pinLayout = bits, U08, 15, [0:7], "Speeduino v0.1", "Speeduino v0.2", "Speeduino v0.3", "Speeduino v0.4", "INVALID", "INVALID", "01-05 MX5 PNP", "INVALID", "96-97 MX5 PNP", "NA6 MX5 PNP", "Turtana PCB", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "Plazomat I/O 0.1", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "Daz V6 Shield 0.1", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "NO2C", "UA4C", "INVALID", "INVALID", "INVALID", "DIY-EFI CORE4 v1.0", "INVALID", "INVALID", "INVALID", "INVALID", "dvjcodec Teensy RevA", "dvjcodec Teensy RevB", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID" + pinLayout = bits, U08, 15, [0:7], "Speeduino v0.1", "Speeduino v0.2", "Speeduino v0.3", "Speeduino v0.4", "INVALID", "INVALID", "01-05 MX5 PNP", "INVALID", "96-97 MX5 PNP", "NA6 MX5 PNP", "Turtana PCB", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "Plazomat I/O 0.1", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "Daz V6 Shield 0.1", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "NO2C", "UA4C", "INVALID", "INVALID", "INVALID", "DIY-EFI CORE4 v1.0", "INVALID", "INVALID", "INVALID", "INVALID", "dvjcodec Teensy RevA", "dvjcodec Teensy RevB", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "Black STM32F407VET6 V0.1", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID" tachoPin = bits, U08, 16, [0:5], "Board Default", "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", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID" tachoDiv = bits, U08, 16, [6:7], "Normal", "Half", "INVALID", "INVALID" tachoDuration = scalar, U08, 17, "ms", 1.0, 0.0, 1.0, 6.0, 0 diff --git a/speeduino/board_stm32_official.h b/speeduino/board_stm32_official.h index 96c3379d..a6b3def6 100644 --- a/speeduino/board_stm32_official.h +++ b/speeduino/board_stm32_official.h @@ -2,7 +2,8 @@ #define STM32F407VE_H #if defined(CORE_STM32_OFFICIAL) #include -#include +#include +#include #include "stm32f4xx_ll_tim.h" /* *********************************************************************************************************** @@ -15,7 +16,7 @@ #define micros_safe() micros() //timer5 method is not used on anything but AVR, the micros_safe() macro is simply an alias for the normal micros() #if defined(SRAM_AS_EEPROM) #define EEPROM_LIB_H "src/BackupSram/BackupSramAsEEPROM.h" -#elif defined(SPI_AS_EEPROM) +#elif defined(SPIFLASH_AS_EEPROM) #define EEPROM_LIB_H "src/SPIAsEEPROM/SPIAsEEPROM.h" #else #define EEPROM_LIB_H @@ -28,10 +29,10 @@ #define USE_SERIAL3 void initBoard(); uint16_t freeRam(); -extern void oneMSIntervalIRQ(stimer_t *Timer); -extern void EmptyIRQCallback(stimer_t *Timer, uint32_t channel); extern "C" char* sbrk(int incr); + + /* *********************************************************************************************************** * Schedules @@ -154,6 +155,26 @@ extern "C" char* sbrk(int incr); * Timers */ +HardwareTimer Timer1(TIM1); +HardwareTimer Timer2(TIM2); +HardwareTimer Timer3(TIM3); +HardwareTimer Timer4(TIM4); +HardwareTimer Timer5(TIM5); +HardwareTimer Timer8(TIM8); + +void oneMSInterval(HardwareTimer*); +void boostInterrupt(HardwareTimer*); +void fuelSchedule1Interrupt(HardwareTimer*); +void fuelSchedule2Interrupt(HardwareTimer*); +void fuelSchedule3Interrupt(HardwareTimer*); +void fuelSchedule4Interrupt(HardwareTimer*); +void idleInterrupt(HardwareTimer*); +void vvtInterrupt(HardwareTimer*); +void ignitionSchedule1Interrupt(HardwareTimer*); +void ignitionSchedule2Interrupt(HardwareTimer*); +void ignitionSchedule3Interrupt(HardwareTimer*); +void ignitionSchedule4Interrupt(HardwareTimer*); +void ignitionSchedule5Interrupt(HardwareTimer*); /* *********************************************************************************************************** diff --git a/speeduino/board_stm32_official.ino b/speeduino/board_stm32_official.ino index 95b41348..9f2b7df3 100644 --- a/speeduino/board_stm32_official.ino +++ b/speeduino/board_stm32_official.ino @@ -4,56 +4,21 @@ #include "auxiliaries.h" #include "idle.h" #include "scheduler.h" -#include +#include "HardwareTimer.h" + -#if defined(STM32F4) - #define NR_OFF_TIMERS 9 - //stimer_t HardwareTimers[NR_OFF_TIMERS + 1]; - stimer_t HardwareTimers_1; - stimer_t HardwareTimers_2; - stimer_t HardwareTimers_3; - stimer_t HardwareTimers_4; - stimer_t HardwareTimers_5; - stimer_t HardwareTimers_8; - //These should really be in the stm32GENERIC libs, but for somereason they only have timers 1-4 - // #include - // #include "src/HardwareTimers/HardwareTimer.h" - // HardwareTimer Timer5(TIM5, chip_tim5, sizeof(chip_tim5) / sizeof(chip_tim5[0])); - // HardwareTimer Timer8(TIM8, chip_tim8, sizeof(chip_tim8) / sizeof(chip_tim8[0])); -#else - #include "HardwareTimer.h" -#endif - extern void oneMSIntervalIRQ(stimer_t *Timer) - { - oneMSInterval(); - } - extern void EmptyIRQCallback(stimer_t *Timer, uint32_t channel) - { - - } void initBoard() { - /* - * Initialize timers - */ - - HardwareTimers_1.timer = TIM1; - HardwareTimers_2.timer = TIM2; - HardwareTimers_3.timer = TIM3; - HardwareTimers_4.timer = TIM4; - - HardwareTimers_5.timer = TIM5; - HardwareTimers_8.timer = TIM8; - - /* *********************************************************************************************************** * General */ - #define FLASH_LENGTH 8192 - + #ifndef FLASH_LENGTH + #define FLASH_LENGTH 8192 + #endif + delay(10); /* *********************************************************************************************************** * Idle @@ -64,14 +29,9 @@ } //This must happen at the end of the idle init - TimerPulseInit(&HardwareTimers_1, 0xFFFF, 0, EmptyIRQCallback); - //setTimerPrescalerRegister(&HardwareTimers_1, (uint32_t)(getTimerClkFreq(HardwareTimers_1.timer) / (500000)) - 1); - if(idle_pwm_max_count > 0) { attachIntHandleOC(&HardwareTimers_1, idleInterrupt, 4, 0);} //on first flash the configPage4.iacAlgorithm is invalid - //Timer1.setMode(4, TIMER_OUTPUT_COMPARE); + Timer1.setMode(4, TIMER_OUTPUT_COMPARE); //timer_set_mode(TIMER1, 4, TIMER_OUTPUT_COMPARE; - //on first flash the configPage4.iacAlgorithm is invalid: - //if(idle_pwm_max_count > 0) { Timer1.attachInterrupt(4, idleInterrupt);} - //Timer1.resume(); + if(idle_pwm_max_count > 0) { Timer1.attachInterrupt(4, idleInterrupt); } //on first flash the configPage4.iacAlgorithm is invalid /* @@ -79,10 +39,15 @@ * Timers */ #if defined(ARDUINO_BLACK_F407VE) || defined(STM32F4) || defined(_STM32F4_) - TimerHandleInit(&HardwareTimers_8, 1000, 168); - attachIntHandle(&HardwareTimers_8, oneMSIntervalIRQ); + Timer8.setOverflow(1000, MICROSEC_FORMAT); // Set up period + Timer8.setMode(1, TIMER_OUTPUT_COMPARE); + Timer8.attachInterrupt(1, oneMSInterval); + Timer8.resume(); //Start Timer #else - //Should do something here for other boards + Timer4.setOverflow(1000, MICROSEC_FORMAT); // Set up period + Timer4.setMode(1, TIMER_OUTPUT_COMPARE); + Timer4.attachInterrupt(1, oneMSInterval); + Timer4.resume(); //Start Timer #endif pinMode(LED_BUILTIN, OUTPUT); //Visual WDT @@ -95,72 +60,85 @@ vvt_pwm_max_count = 1000000L / (2 * configPage6.vvtFreq * 2); //Converts the frequency in Hz to the number of ticks (at 2uS) it takes to complete 1 cycle //Need to be initialised last due to instant interrupt - // Timer1.setMode(2, TIMER_OUTPUT_COMPARE); - // Timer1.setMode(3, TIMER_OUTPUT_COMPARE); - // if(boost_pwm_max_count > 0) { Timer1.attachInterrupt(2, boostInterrupt);} - // if(vvt_pwm_max_count > 0) { Timer1.attachInterrupt(3, vvtInterrupt);} - if(idle_pwm_max_count > 0) { attachIntHandleOC(&HardwareTimers_1, boostInterrupt, 2, 0);} - if(vvt_pwm_max_count > 0) { attachIntHandleOC(&HardwareTimers_1, vvtInterrupt, 3, 0);} - // Timer1.resume(); - - TimerPulseInit(&HardwareTimers_3, 0xFFFF, 0, EmptyIRQCallback); - attachIntHandleOC(&HardwareTimers_3, fuelSchedule1Interrupt, 1, 0); - attachIntHandleOC(&HardwareTimers_3, fuelSchedule2Interrupt, 2, 0); - attachIntHandleOC(&HardwareTimers_3, fuelSchedule3Interrupt, 3, 0); - attachIntHandleOC(&HardwareTimers_3, fuelSchedule4Interrupt, 4, 0); - + Timer1.setMode(2, TIMER_OUTPUT_COMPARE); + Timer1.setMode(3, TIMER_OUTPUT_COMPARE); + if(boost_pwm_max_count > 0) { Timer1.attachInterrupt(2, boostInterrupt);} + if(vvt_pwm_max_count > 0) { Timer1.attachInterrupt(3, vvtInterrupt);} - TimerPulseInit(&HardwareTimers_2, 0xFFFF, 0, EmptyIRQCallback); - attachIntHandleOC(&HardwareTimers_2, ignitionSchedule1Interrupt, 1, 0); - attachIntHandleOC(&HardwareTimers_2, ignitionSchedule2Interrupt, 2, 0); - attachIntHandleOC(&HardwareTimers_2, ignitionSchedule3Interrupt, 3, 0); - attachIntHandleOC(&HardwareTimers_2, ignitionSchedule4Interrupt, 4, 0); - - //Attach interupt functions - //Injection + /* + *********************************************************************************************************** + * Schedules + */ + Timer1.setOverflow(MAX_TIMER_PERIOD, MICROSEC_FORMAT); + Timer2.setOverflow(MAX_TIMER_PERIOD, MICROSEC_FORMAT); + Timer3.setOverflow(MAX_TIMER_PERIOD, MICROSEC_FORMAT); - TimerPulseInit(&HardwareTimers_5, 0xFFFF, 0, EmptyIRQCallback); - //setTimerPrescalerRegister(&HardwareTimers_5, (uint32_t)(getTimerClkFreq(HardwareTimers_5.timer) / (1000000)) - 1); - #if (INJ_CHANNELS >= 5) - attachIntHandleOC(&HardwareTimers_5, fuelSchedule5Interrupt, 1, 0); - //Timer5.attachInterrupt(1, fuelSchedule5Interrupt); - #endif - #if (INJ_CHANNELS >= 6) - attachIntHandleOC(&HardwareTimers_5, fuelSchedule6Interrupt, 2, 0); - //Timer5.attachInterrupt(2, fuelSchedule6Interrupt); - #endif - #if (INJ_CHANNELS >= 7) - attachIntHandleOC(&HardwareTimers_5, fuelSchedule7Interrupt, 3, 0); - //Timer5.attachInterrupt(3, fuelSchedule7Interrupt); - #endif - #if (INJ_CHANNELS >= 8) - attachIntHandleOC(&HardwareTimers_5, fuelSchedule8Interrupt, 4, 0); - //Timer5.attachInterrupt(4, fuelSchedule8Interrupt); - #endif - TimerPulseInit(&HardwareTimers_4, 0xFFFF, 0, EmptyIRQCallback); - //setTimerPrescalerRegister(&HardwareTimers_4, (uint32_t)(getTimerClkFreq(HardwareTimers_4.timer) / (1000000)) - 1); - #if (IGN_CHANNELS >= 5) - attachIntHandleOC(&HardwareTimers_4, ignitionSchedule5Interrupt, 1, 0); - //Timer4.attachInterrupt(1, ignitionSchedule5Interrupt); - #endif - #if (IGN_CHANNELS >= 6) - attachIntHandleOC(&HardwareTimers_4, ignitionSchedule6Interrupt, 2, 0); - //Timer4.attachInterrupt(2, ignitionSchedule6Interrupt); - #endif - #if (IGN_CHANNELS >= 7) - attachIntHandleOC(&HardwareTimers_4, ignitionSchedule7Interrupt, 3, 0); - //Timer4.attachInterrupt(3, ignitionSchedule7Interrupt); - #endif - #if (IGN_CHANNELS >= 8) - attachIntHandleOC(&HardwareTimers_4, ignitionSchedule8Interrupt, 4, 0); - //Timer4.attachInterrupt(4, ignitionSchedule8Interrupt); - #endif - - setTimerPrescalerRegister(&HardwareTimers_2, (uint32_t)(getTimerClkFreq(HardwareTimers_2.timer) / (250000)) - 1); - setTimerPrescalerRegister(&HardwareTimers_3, (uint32_t)(getTimerClkFreq(HardwareTimers_3.timer) / (250000)) - 1); - setTimerPrescalerRegister(&HardwareTimers_4, (uint32_t)(getTimerClkFreq(HardwareTimers_4.timer) / (250000)) - 1); - setTimerPrescalerRegister(&HardwareTimers_5, (uint32_t)(getTimerClkFreq(HardwareTimers_5.timer) / (250000)) - 1); + Timer2.setMode(1, TIMER_OUTPUT_COMPARE); + Timer2.setMode(2, TIMER_OUTPUT_COMPARE); + Timer2.setMode(3, TIMER_OUTPUT_COMPARE); + Timer2.setMode(4, TIMER_OUTPUT_COMPARE); + + Timer3.setMode(1, TIMER_OUTPUT_COMPARE); + Timer3.setMode(2, TIMER_OUTPUT_COMPARE); + Timer3.setMode(3, TIMER_OUTPUT_COMPARE); + Timer3.setMode(4, TIMER_OUTPUT_COMPARE); + Timer1.setMode(1, TIMER_OUTPUT_COMPARE); + + //Attach interupt functions + //Injection + Timer3.attachInterrupt(1, fuelSchedule1Interrupt); + Timer3.attachInterrupt(2, fuelSchedule2Interrupt); + Timer3.attachInterrupt(3, fuelSchedule3Interrupt); + Timer3.attachInterrupt(4, fuelSchedule4Interrupt); + #if (INJ_CHANNELS >= 5) + Timer5.setMode(1, TIMER_OUTPUT_COMPARE); + Timer5.attachInterrupt(1, fuelSchedule5Interrupt); + #endif + #if (INJ_CHANNELS >= 6) + Timer5.setMode(2, TIMER_OUTPUT_COMPARE); + Timer5.attachInterrupt(2, fuelSchedule6Interrupt); + #endif + #if (INJ_CHANNELS >= 7) + Timer5.setMode(3, TIMER_OUTPUT_COMPARE); + Timer5.attachInterrupt(3, fuelSchedule7Interrupt); + #endif + #if (INJ_CHANNELS >= 8) + Timer5.setMode(4, TIMER_OUTPUT_COMPARE); + Timer5.attachInterrupt(4, fuelSchedule8Interrupt); + #endif + + //Ignition + Timer2.attachInterrupt(1, ignitionSchedule1Interrupt); + Timer2.attachInterrupt(2, ignitionSchedule2Interrupt); + Timer2.attachInterrupt(3, ignitionSchedule3Interrupt); + Timer2.attachInterrupt(4, ignitionSchedule4Interrupt); + #if (IGN_CHANNELS >= 5) + Timer4.setMode(1, TIMER_OUTPUT_COMPARE); + Timer4.attachInterrupt(1, ignitionSchedule5Interrupt); + #endif + #if (IGN_CHANNELS >= 6) + Timer4.setMode(2, TIMER_OUTPUT_COMPARE); + Timer4.attachInterrupt(2, ignitionSchedule6Interrupt); + #endif + #if (IGN_CHANNELS >= 7) + Timer4.setMode(3, TIMER_OUTPUT_COMPARE); + Timer4.attachInterrupt(3, ignitionSchedule7Interrupt); + #endif + #if (IGN_CHANNELS >= 8) + Timer4.setMode(4, TIMER_OUTPUT_COMPARE); + Timer4.attachInterrupt(4, ignitionSchedule8Interrupt); + #endif + + Timer1.resume(); + Timer2.resume(); + Timer3.resume(); + #if (IGN_CHANNELS >= 5) + Timer4.resume(); + #endif + #if (INJ_CHANNELS >= 5) + Timer5.resume(); + #endif } uint16_t freeRam() @@ -169,7 +147,22 @@ return &top - reinterpret_cast(sbrk(0)); } - //pinmapping the STM32F407 for different boards, at this moment no board is desgined. - //All boards are set to the default just to be sure. - + /* + *********************************************************************************************************** + * Interrupt callback functions + */ + void oneMSInterval(HardwareTimer*){oneMSInterval();} + void boostInterrupt(HardwareTimer*){boostInterrupt();} + void fuelSchedule1Interrupt(HardwareTimer*){fuelSchedule1Interrupt();} + void fuelSchedule2Interrupt(HardwareTimer*){fuelSchedule2Interrupt();} + void fuelSchedule3Interrupt(HardwareTimer*){fuelSchedule3Interrupt();} + void fuelSchedule4Interrupt(HardwareTimer*){fuelSchedule4Interrupt();} + void idleInterrupt(HardwareTimer*){idleInterrupt();} + void vvtInterrupt(HardwareTimer*){vvtInterrupt();} + void ignitionSchedule1Interrupt(HardwareTimer*){ignitionSchedule1Interrupt();} + void ignitionSchedule2Interrupt(HardwareTimer*){ignitionSchedule2Interrupt();} + void ignitionSchedule3Interrupt(HardwareTimer*){ignitionSchedule3Interrupt();} + void ignitionSchedule4Interrupt(HardwareTimer*){ignitionSchedule4Interrupt();} + void ignitionSchedule5Interrupt(HardwareTimer*){ignitionSchedule5Interrupt();} + #endif diff --git a/speeduino/comms.ino b/speeduino/comms.ino index 70ddebb1..97bf8cf3 100644 --- a/speeduino/comms.ino +++ b/speeduino/comms.ino @@ -1641,9 +1641,10 @@ void receiveCalibration(byte tableID) bool every2nd = true; int x; int counter = 0; - pinMode(LED_BUILTIN, OUTPUT); //pinMode(13, OUTPUT); + // stm32 board has buildin led used as fuel pump + // pinMode(LED_BUILTIN, OUTPUT); //pinMode(13, OUTPUT); - digitalWrite(LED_BUILTIN, LOW); //digitalWrite(13, LOW); + // digitalWrite(LED_BUILTIN, LOW); //digitalWrite(13, LOW); for (x = 0; x < 1024; x++) { //UNlike what is listed in the protocol documentation, the O2 sensor values are sent as bytes rather than ints @@ -1682,6 +1683,8 @@ void receiveCalibration(byte tableID) every2nd = false; #if defined(CORE_STM32) digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN)); + #elif defined(CORE_STM32_OFFICIAL) + //Of core offical do nothing. led is reserved for fuel pump #else analogWrite(LED_BUILTIN, (counter % 50) ); //analogWrite(13, (counter % 50) ); #endif diff --git a/speeduino/init.ino b/speeduino/init.ino index 5b601ea2..633f662e 100644 --- a/speeduino/init.ino +++ b/speeduino/init.ino @@ -38,7 +38,7 @@ void initialiseAll() //Always start with a clean slate on the bootloader capabilities level //This should be 0 until we hear otherwise from the 16u2 configPage4.bootloaderCaps = 0; - + initBoard(); //This calls the current individual boards init function. See the board_xxx.ino files for these. initialiseTimers(); @@ -1020,46 +1020,108 @@ void setPinMapping(byte boardID) pinCoil3 = 30; pinO2 = A22; #elif defined(STM32F4) + //Pin definitions for experimental board Tjeerd //Black F407VE wiki.stm32duino.com/index.php?title=STM32F407 - //PC8~PC12 SDio - //PA13~PA15 & PB4 SWD(debug) pins - //PB0 EEPROM CS pin - //PA9 & PD10 Serial1 - //PD5 & PD6 Serial2 - pinInjector1 = PE7; //Output pin injector 1 is on - pinInjector2 = PE8; //Output pin injector 2 is on - pinInjector3 = PE9; //Output pin injector 3 is on - pinInjector4 = PE10; //Output pin injector 4 is on - pinInjector5 = PE11; //Output pin injector 5 is on - pinInjector6 = PE12; //Output pin injector 6 is on - pinCoil1 = PD0; //Pin for coil 1 - pinCoil2 = PD1; //Pin for coil 2 - pinCoil3 = PD2; //Pin for coil 3 - pinCoil4 = PD3; //Pin for coil 4 - pinCoil5 = PD4; //Pin for coil 5 - pinTPS = A0; //TPS input pin - pinMAP = A1; //MAP sensor pin - pinIAT = A2; //IAT sensor pin - pinCLT = A3; //CLT sensor pin - pinO2 = A4; //O2 Sensor pin - pinBat = A5; //Battery reference voltage pin - pinBaro = A9; - pinIdle1 = PB8; //Single wire idle control - pinIdle2 = PB9; //2 wire idle control - pinBoost = PE0; //Boost control - pinVVT_1 = PE1; //Default VVT output - pinStepperDir = PD8; //Direction pin for DRV8825 driver - pinStepperStep = PB15; //Step pin for DRV8825 driver - pinStepperEnable = PD9; //Enable pin for DRV8825 - pinDisplayReset = PE1; // OLED reset pin - pinFan = PE2; //Pin for the fan output - pinFuelPump = PC0; //Fuel pump output - pinTachOut = PC1; //Tacho output pin - //external interrupt enabled pins - //external interrupts could be enalbed in any pin, except same port numbers (PA4,PE4) - pinFlex = PE2; // Flex sensor (Must be external interrupt enabled) - pinTrigger = PE3; //The CAS pin - pinTrigger2 = PE4; //The Cam Sensor pin + + //****************************************** + //******** PORTA CONNECTIONS *************** + //****************************************** + // = PA0 //Wakeup ADC123 + pinTPS = PA1; //ADC123 + pinMAP = PA2; //ADC123 + pinIAT = PA3; //ADC123 + pinCLT = PA4; //ADC12 + pinO2 = PA5; //ADC12 + // = PA6; //ADC12 LED_BUILTIN_1 + pinFuelPump = PA7; //ADC12 LED_BUILTIN_2 + pinIdle1 = PA8; // + // = PA9 //TXD1 + // = PA10 //RXD1 + // = PA11 //(DO NOT USE FOR SPEEDUINO) USB + // = PA12 //(DO NOT USE FOR SPEEDUINO) USB + // = PA13 //(DO NOT USE FOR SPEEDUINO) //NOT ON GPIO //DEBUG ST-LINK + // = PA14 //(DO NOT USE FOR SPEEDUINO) //NOT ON GPIO //DEBUG ST-LINK + // = PA15 //(DO NOT USE FOR SPEEDUINO) //NOT ON GPIO //DEBUG ST-LINK + + //****************************************** + //******** PORTB CONNECTIONS *************** + //****************************************** + // = PB0; (DO NOT USE FOR SPEEDUINO)//ADC123 //SPI FLASH CHIP CS pin + pinBaro = PB1; //ADC12 + // = PB2; //(DO NOT USE FOR SPEEDUINO) BOOT1 + // = PB3; //(DO NOT USE FOR SPEEDUINO) SPI1_SCK FLASH CHIP + // = PB4; //(DO NOT USE FOR SPEEDUINO) SPI1_MISO FLASH CHIP + // = PB5; //(DO NOT USE FOR SPEEDUINO) SPI1_MOSI FLASH CHIP + // = PB6; //NRF_CE + // = PB7; //NRF_CS + // = PB8; //NRF_IRQ + pinIdle2 = PB9; // + // = PB10; //TXD3 + // = PB11; //RXD3 + pinBoost = PB12; // + // = PB13; //SPI2_SCK + // = PB14; //SPI2_MISO + // = PB15; //SPI2_MOSI + + //****************************************** + //******** PORTC CONNECTIONS *************** + //****************************************** + // = PC0; //ADC123 + pinBat = PC1; //ADC123 + // = PC2; //ADC123 + // = PC3; //ADC123 + // = PC4; //ADC12 + // = PC5; //ADC12 + pinVVT_1 = PC6; // + pinDisplayReset = PC7; // + // = PC8; //(DO NOT USE FOR SPEEDUINO) //SDIO_D0 + // = PC9; //(DO NOT USE FOR SPEEDUINO) //SDIO_D1 + // = PC10; //(DO NOT USE FOR SPEEDUINO) //SDIO_D2 + // = PC11; //(DO NOT USE FOR SPEEDUINO) //SDIO_D3 + // = PC12; //(DO NOT USE FOR SPEEDUINO) //SDIO_SCK + pinTachOut = PC13; // + // = PC14; //(DO NOT USE FOR SPEEDUINO) //OSC32_IN + // = PC15; //(DO NOT USE FOR SPEEDUINO) //OSC32_OUT + + //****************************************** + //******** PORTD CONNECTIONS *************** + //****************************************** + // = PD0; //CANRX + // = PD1; //CANTX + // = PD2; //(DO NOT USE FOR SPEEDUINO) //SDIO_CMD + pinCoil1 = PD3; // + pinCoil2 = PD4; // + // = PD5;//TXD2 + // = PD6; //RXD2 + pinCoil3 = PD7; // + pinCoil4 = PD8; // + pinCoil5 = PD9;// + pinFan = PD10; // + // = PD11; // + // = PD12; // + // = PD13; // + // = PD14; // + // = PD15; // + + //****************************************** + //******** PORTE CONNECTIONS *************** + //****************************************** + pinStepperDir = PE0; // + pinStepperStep = PE1; // + pinStepperEnable = PE2; // + // = PE3; //ONBOARD KEY1 + // = PE4; //ONBOARD KEY2 + pinFlex = PE5; // + pinTrigger = PE6; // + pinInjector1 = PE7; // + pinInjector2 = PE8; // + pinInjector3 = PE9; // + pinInjector4 = PE10; // + pinInjector5 = PE11; // + pinInjector6 = PE12; // + pinTrigger2 = PE13; // + // = PE14; // + // = PE15; // #elif defined(CORE_STM32) //blue pill wiki.stm32duino.com/index.php?title=Blue_Pill //Maple mini wiki.stm32duino.com/index.php?title=Maple_Mini @@ -1566,49 +1628,254 @@ void setPinMapping(byte boardID) pinSpareLOut1 = 21; //low current output spare1 break; #endif - - default: - #if defined(STM32F4) + + #if defined(STM32F4) + case 60: + //Pin definitions for experimental board Tjeerd //Black F407VE wiki.stm32duino.com/index.php?title=STM32F407 - //PC8~PC12 SDio - //PA13~PA15 & PB4 SWD(debug) pins - //PB0 EEPROM CS pin - //PA9 & PD10 Serial1 - //PD5 & PD6 Serial2 - pinInjector1 = PE7; //Output pin injector 1 is on - pinInjector2 = PE8; //Output pin injector 2 is on - pinInjector3 = PE9; //Output pin injector 3 is on - pinInjector4 = PE10; //Output pin injector 4 is on - pinInjector5 = PE11; //Output pin injector 5 is on - pinInjector6 = PE12; //Output pin injector 6 is on - pinCoil1 = PD0; //Pin for coil 1 - pinCoil2 = PD1; //Pin for coil 2 - pinCoil3 = PD2; //Pin for coil 3 - pinCoil4 = PD3; //Pin for coil 4 - pinCoil5 = PD4; //Pin for coil 5 + + //****************************************** + //******** PORTA CONNECTIONS *************** + //****************************************** + // = PA0 //Wakeup ADC123 + pinTPS = PA1; //ADC123 + pinMAP = PA2; //ADC123 + pinIAT = PA3; //ADC123 + pinCLT = PA4; //ADC12 + pinO2 = PA5; //ADC12 + // = PA6; //ADC12 LED_BUILTIN_1 + pinFuelPump = PA7; //ADC12 LED_BUILTIN_2 + pinIdle1 = PA8; // + // = PA9 //TXD1 + // = PA10 //RXD1 + // = PA11 //(DO NOT USE FOR SPEEDUINO) USB + // = PA12 //(DO NOT USE FOR SPEEDUINO) USB + // = PA13 //(DO NOT USE FOR SPEEDUINO) //NOT ON GPIO //DEBUG ST-LINK + // = PA14 //(DO NOT USE FOR SPEEDUINO) //NOT ON GPIO //DEBUG ST-LINK + // = PA15 //(DO NOT USE FOR SPEEDUINO) //NOT ON GPIO //DEBUG ST-LINK + + //****************************************** + //******** PORTB CONNECTIONS *************** + //****************************************** + // = PB0; (DO NOT USE FOR SPEEDUINO)//ADC123 //SPI FLASH CHIP CS pin + pinBaro = PB1; //ADC12 + // = PB2; //(DO NOT USE FOR SPEEDUINO) BOOT1 + // = PB3; //(DO NOT USE FOR SPEEDUINO) SPI1_SCK FLASH CHIP + // = PB4; //(DO NOT USE FOR SPEEDUINO) SPI1_MISO FLASH CHIP + // = PB5; //(DO NOT USE FOR SPEEDUINO) SPI1_MOSI FLASH CHIP + // = PB6; //NRF_CE + // = PB7; //NRF_CS + // = PB8; //NRF_IRQ + pinIdle2 = PB9; // + // = PB10; //TXD3 + // = PB11; //RXD3 + pinBoost = PB12; // + // = PB13; //SPI2_SCK + // = PB14; //SPI2_MISO + // = PB15; //SPI2_MOSI + + //****************************************** + //******** PORTC CONNECTIONS *************** + //****************************************** + // = PC0; //ADC123 + pinBat = PC1; //ADC123 + // = PC2; //ADC123 + // = PC3; //ADC123 + // = PC4; //ADC12 + // = PC5; //ADC12 + pinVVT_1 = PC6; // + pinDisplayReset = PC7; // + // = PC8; //(DO NOT USE FOR SPEEDUINO) //SDIO_D0 + // = PC9; //(DO NOT USE FOR SPEEDUINO) //SDIO_D1 + // = PC10; //(DO NOT USE FOR SPEEDUINO) //SDIO_D2 + // = PC11; //(DO NOT USE FOR SPEEDUINO) //SDIO_D3 + // = PC12; //(DO NOT USE FOR SPEEDUINO) //SDIO_SCK + pinTachOut = PC13; // + // = PC14; //(DO NOT USE FOR SPEEDUINO) //OSC32_IN + // = PC15; //(DO NOT USE FOR SPEEDUINO) //OSC32_OUT + + //****************************************** + //******** PORTD CONNECTIONS *************** + //****************************************** + // = PD0; //CANRX + // = PD1; //CANTX + // = PD2; //(DO NOT USE FOR SPEEDUINO) //SDIO_CMD + pinCoil1 = PD3; // + pinCoil2 = PD4; // + // = PD5;//TXD2 + // = PD6; //RXD2 + pinCoil3 = PD7; // + pinCoil4 = PD8; // + pinCoil5 = PD9;// + pinFan = PD10; // + // = PD11; // + // = PD12; // + // = PD13; // + // = PD14; // + // = PD15; // + + //****************************************** + //******** PORTE CONNECTIONS *************** + //****************************************** + pinStepperDir = PE0; // + pinStepperStep = PE1; // + pinStepperEnable = PE2; // + // = PE3; //ONBOARD KEY1 + // = PE4; //ONBOARD KEY2 + pinFlex = PE5; // + pinTrigger = PE6; // + pinInjector1 = PE7; // + pinInjector2 = PE8; // + pinInjector3 = PE9; // + pinInjector4 = PE10; // + pinInjector5 = PE11; // + pinInjector6 = PE12; // + pinTrigger2 = PE13; // + // = PE14; // + // = PE15; // + + #elif defined(CORE_STM32) + //blue pill wiki.stm32duino.com/index.php?title=Blue_Pill + //Maple mini wiki.stm32duino.com/index.php?title=Maple_Mini + //pins PA12, PA11 are used for USB or CAN couldn't be used for GPIO + pinInjector1 = PB7; //Output pin injector 1 is on + pinInjector2 = PB6; //Output pin injector 2 is on + pinInjector3 = PB5; //Output pin injector 3 is on + pinInjector4 = PB4; //Output pin injector 4 is on + pinCoil1 = PB3; //Pin for coil 1 + pinCoil2 = PA15; //Pin for coil 2 + pinCoil3 = PA14; //Pin for coil 3 + pinCoil4 = PA9; //Pin for coil 4 + pinCoil5 = PA8; //Pin for coil 5 pinTPS = A0; //TPS input pin pinMAP = A1; //MAP sensor pin pinIAT = A2; //IAT sensor pin - pinCLT = A3; //CLT sensor pin + pinCLT = A3; //CLS sensor pin pinO2 = A4; //O2 Sensor pin pinBat = A5; //Battery reference voltage pin - pinBaro = A9; - pinIdle1 = PB8; //Single wire idle control - pinIdle2 = PB9; //2 wire idle control - pinBoost = PE0; //Boost control - pinVVT_1 = PE1; //Default VVT output - pinStepperDir = PD8; //Direction pin for DRV8825 driver - pinStepperStep = PB15; //Step pin for DRV8825 driver - pinStepperEnable = PD9; //Enable pin for DRV8825 - pinDisplayReset = PE1; // OLED reset pin - pinFan = PE2; //Pin for the fan output - pinFuelPump = PC0; //Fuel pump output - pinTachOut = PC1; //Tacho output pin + pinBaro = pinMAP; + pinIdle1 = PB2; //Single wire idle control + pinIdle2 = PA2; //2 wire idle control + pinBoost = PA1; //Boost control + pinVVT_1 = PA0; //Default VVT output + pinStepperDir = PC15; //Direction pin for DRV8825 driver + pinStepperStep = PC14; //Step pin for DRV8825 driver + pinStepperEnable = PC13; //Enable pin for DRV8825 + pinDisplayReset = PB2; // OLED reset pin + pinFan = PB1; //Pin for the fan output + pinFuelPump = PB11; //Fuel pump output + pinTachOut = PB10; //Tacho output pin //external interrupt enabled pins - //external interrupts could be enalbed in any pin, except same port numbers (PA4,PE4) - pinFlex = PE2; // Flex sensor (Must be external interrupt enabled) - pinTrigger = PE3; //The CAS pin - pinTrigger2 = PE4; //The Cam Sensor pin + pinFlex = PB8; // Flex sensor (Must be external interrupt enabled) + pinTrigger = PA10; //The CAS pin + pinTrigger2 = PA13; //The Cam Sensor pin + + #endif + break; + default: + #if defined(STM32F4) + //Pin definitions for experimental board Tjeerd + //Black F407VE wiki.stm32duino.com/index.php?title=STM32F407 + + //****************************************** + //******** PORTA CONNECTIONS *************** + //****************************************** + // = PA0 //Wakeup ADC123 + pinTPS = PA1; //ADC123 + pinMAP = PA2; //ADC123 + pinIAT = PA3; //ADC123 + pinCLT = PA4; //ADC12 + pinO2 = PA5; //ADC12 + pinFan = PA6; //ADC12 LED_BUILTIN_1 + pinFuelPump = PA7; //ADC12 LED_BUILTIN_2 + pinIdle1 = PA8; // + // = PA9 //TXD1 + // = PA10 //RXD1 + // = PA11 //(DO NOT USE FOR SPEEDUINO) USB + // = PA12 //(DO NOT USE FOR SPEEDUINO) USB + // = PA13 //(DO NOT USE FOR SPEEDUINO) //NOT ON GPIO //DEBUG ST-LINK + // = PA14 //(DO NOT USE FOR SPEEDUINO) //NOT ON GPIO //DEBUG ST-LINK + // = PA15 //(DO NOT USE FOR SPEEDUINO) //NOT ON GPIO //DEBUG ST-LINK + + //****************************************** + //******** PORTB CONNECTIONS *************** + //****************************************** + // = PB0; (DO NOT USE FOR SPEEDUINO)//ADC123 //SPI FLASH CHIP CS pin + pinBaro = PB1; //ADC12 + // = PB2; //(DO NOT USE FOR SPEEDUINO) BOOT1 + // = PB3; //(DO NOT USE FOR SPEEDUINO) SPI1_SCK FLASH CHIP + // = PB4; //(DO NOT USE FOR SPEEDUINO) SPI1_MISO FLASH CHIP + // = PB5; //(DO NOT USE FOR SPEEDUINO) SPI1_MOSI FLASH CHIP + // = PB6; //NRF_CE + // = PB7; //NRF_CS + // = PB8; //NRF_IRQ + pinIdle2 = PB9; // + // = PB10; //TXD3 + // = PB11; //RXD3 + pinBoost = PB12; // + // = PB13; //SPI2_SCK + // = PB14; //SPI2_MISO + // = PB15; //SPI2_MOSI + + //****************************************** + //******** PORTC CONNECTIONS *************** + //****************************************** + // = PC0; //ADC123 + pinBat = PC1; //ADC123 + // = PC2; //ADC123 + // = PC3; //ADC123 + // = PC4; //ADC12 + // = PC5; //ADC12 + pinVVT_1 = PC6; // + pinDisplayReset = PC7; // + // = PC8; //(DO NOT USE FOR SPEEDUINO) //SDIO_D0 + // = PC9; //(DO NOT USE FOR SPEEDUINO) //SDIO_D1 + // = PC10; //(DO NOT USE FOR SPEEDUINO) //SDIO_D2 + // = PC11; //(DO NOT USE FOR SPEEDUINO) //SDIO_D3 + // = PC12; //(DO NOT USE FOR SPEEDUINO) //SDIO_SCK + pinTachOut = PC13; // + // = PC14; //(DO NOT USE FOR SPEEDUINO) //OSC32_IN + // = PC15; //(DO NOT USE FOR SPEEDUINO) //OSC32_OUT + + //****************************************** + //******** PORTD CONNECTIONS *************** + //****************************************** + // = PD0; //CANRX + // = PD1; //CANTX + // = PD2; //(DO NOT USE FOR SPEEDUINO) //SDIO_CMD + pinCoil1 = PD3; // + pinCoil2 = PD4; // + // = PD5;//TXD2 + // = PD6; //RXD2 + pinCoil3 = PD7; // + pinCoil4 = PD8; // + pinCoil5 = PD9;// + // = PD10; // + // = PD11; // + // = PD12; // + // = PD13; // + // = PD14; // + // = PD15; // + + //****************************************** + //******** PORTE CONNECTIONS *************** + //****************************************** + pinStepperDir = PE0; // + pinStepperStep = PE1; // + pinStepperEnable = PE2; // + // = PE3; //ONBOARD KEY1 + // = PE4; //ONBOARD KEY2 + pinFlex = PE5; // + pinTrigger = PE6; // + pinInjector1 = PE7; // + pinInjector2 = PE8; // + pinInjector3 = PE9; // + pinInjector4 = PE10; // + pinInjector5 = PE11; // + pinInjector6 = PE12; // + pinTrigger2 = PE13; // + // = PE14; // + // = PE15; // #else #ifndef SMALL_FLASH_MODE //No support for bluepill here anyway //Pin mappings as per the v0.2 shield diff --git a/speeduino/src/BackupSram/BackupSramAsEEPROM.h b/speeduino/src/BackupSram/BackupSramAsEEPROM.h index b79da490..4d996a56 100644 --- a/speeduino/src/BackupSram/BackupSramAsEEPROM.h +++ b/speeduino/src/BackupSram/BackupSramAsEEPROM.h @@ -12,7 +12,7 @@ class BackupSramAsEEPROM { private: - const uint16_t backup_size = 0x4000; //maximum of 4kb backuped sram available. + const uint16_t backup_size = 4096; //maximum of 4kb backuped sram available. int8_t write_byte( uint8_t *data, uint16_t bytes, uint16_t offset ); int8_t read_byte( uint8_t *data, uint16_t bytes, uint16_t offset ); diff --git a/speeduino/src/SPIAsEEPROM/SPIAsEEPROM.cpp b/speeduino/src/SPIAsEEPROM/SPIAsEEPROM.cpp index 0142a80a..4a7a9faf 100644 --- a/speeduino/src/SPIAsEEPROM/SPIAsEEPROM.cpp +++ b/speeduino/src/SPIAsEEPROM/SPIAsEEPROM.cpp @@ -1,43 +1,231 @@ -/* -* This file implements a shim layer for the SPIMemory library (https://github.com/Marzogh/SPIMemory) to mimic a minimal -* subset of the standard Arduino EEPROM library -*/ -#if defined(SPI_AS_EEPROM) +/* Speeduino SPIAsEEPROM Library v.1.0.0 + * Copyright (C) 2019 by Tjeerd Hoogendijk + * Created by Tjeerd Hoogendijk - 21/09/2019 + * + * This file is part of the Speeduino project. This library is for + * Winbond SPI flash memory modules. In its current form it enables reading + * and writing individual bytes as if it where an AVR EEPROM. It uses some + * wear leveling (256x). When the begin() fuction is called for the first time + * it will "format" the flash chip. + * !!!!THIS DISTROYS ANY EXISTING DATA ON THE SPI FLASH!!! + * + * 1245184 bytes used of the SPI flash resulting in 4228 bytes of usable EEPROM + * + * This Library 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 Library 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 v3.0 + * along with the Arduino SPIMemory Library. If not, see + * . + */ + +#if defined(CORE_STM32_OFFICIAL) && defined(SPIFLASH_AS_EEPROM) #include "SPIAsEEPROM.h" -#include "SPIMemory.h" -#include - -//SPIFlash flash; -SPIFlash flash(SS1, &SPI); //Use this constructor if using an SPI bus other than the default SPI. Only works with chips with more than one hardware SPI bus +#include "SPI.h" SPIAsEEPROM::SPIAsEEPROM() { - //Do some init stuff here + pinMode(PB0, OUTPUT); + magicbuf[0] = MAGICNUMBER1; + magicbuf[1] = MAGICNUMBER2; + magicbuf[2] = MAGICNUMBER3; + magicbuf[3] = 0x00; - flash.begin(); - //To use a custom flash memory size (if using memory from manufacturers not officially supported by the library) - declare a size variable according to the list in defines.h - //flash.begin(MB(1)); + } + uint8_t SPIAsEEPROM::begin() { + + SpiFlashAvialable = winbondSPIFlash.begin(_W25Q16,SPI,PB0); + uint8_t formatted = 0; + if(SpiFlashAvialable){ + //check for magic numbers + formatted = 1; + uint8_t buf[MAGICNUMBER_OFFSET]; + for(uint16_t i=0; i< FLASHSIZEUSED/SECTORSIZE; i++ ){ + winbondSPIFlash.read(sectorNumber*SECTORSIZE, buf, sizeof(buf) - 1); + if((buf[0] != MAGICNUMBER1) | (buf[1] != MAGICNUMBER2) | (buf[2] != MAGICNUMBER3)){ + //if one of the SECTORS has no magic numbers it is not formatted + formatted = 0; + } + } + //If not formatted format flash. This takes 10 seconds or more! + if(!formatted){ + formatFlashForUse(); + } -} + //check if format succeeded + formatted = 1; + for(uint16_t i=0; i< FLASHSIZEUSED/SECTORSIZE; i++ ){ + winbondSPIFlash.read(sectorNumber*SECTORSIZE, buf, sizeof(buf) - 1); + if((buf[0] != MAGICNUMBER1) | (buf[1] != MAGICNUMBER2) | (buf[2] != MAGICNUMBER3)){ + formatted = 0; + } + } + } + if(formatted & SpiFlashAvialable){return true;}else{return false;} + } -uint8_t SPIAsEEPROM::read(uint16_t address) { +int8_t SPIAsEEPROM::write(uint16_t addressEEPROM, uint8_t writeValue){ + uint8_t ByteBuf[1]; - uint8_t val = 0; + //Check if adress is in the EEPROM space + if (addressEEPROM >= FLASHSIZEUSED/SECTORSIZE * (SECTORSIZE/FLASH_PAGESIZE - 2)){addressEEPROM = FLASHSIZEUSED/SECTORSIZE * (SECTORSIZE/FLASH_PAGESIZE - 2);} - return val; + //read the current value + uint8_t readValue = read(addressEEPROM); + //After reading the current byte all global variables containing inforamtion about the address are set correctly. + + //only write if value is changed. + if (readValue != writeValue){ + + //Check if buffer is full and an erase must be performed. + if (nrOfOnes < 1){ + + //First read all the values in this sector that will get distroyed when erasing + uint8_t tempBuf[14]; + for(uint8_t i = 0; i<14; i++){ + tempBuf[i] = read((sectorNumber*14) + i); + } + + //now erase the sector + writeMagicNumber(sectorNumber); + + //write all the values back + for(uint8_t i=0; i<14; i++){ + write((sectorNumber*14) + i, tempBuf[i]); + } + + //also do not forget to write the new value! + write(addressEEPROM, writeValue); + return 0; + + } + + //determine the adress of the byte in the infoblock where one bit must be reset when writing new values + uint8_t RelativeAdressInInfoBlock = (nrOfOnes - 1)/8; + + //determine value of the infoblock byte after writing one more time. + uint8_t ValueInInfoBlock = 0xFF << (8 - (nrOfOnes - 1 - ((RelativeAdressInInfoBlock) * 8))); + + //write the new value at the new location + ByteBuf[0] = writeValue; + winbondSPIFlash.WE(); + winbondSPIFlash.writePage(dataFlashAddress - 1, ByteBuf, sizeof(ByteBuf)); + while(winbondSPIFlash.busy()); + + //write where read can find the new value + ByteBuf[0] = ValueInInfoBlock; + winbondSPIFlash.WE(); + winbondSPIFlash.writePage(infoFlashAddress + RelativeAdressInInfoBlock, ByteBuf, sizeof(ByteBuf)); + while(winbondSPIFlash.busy()); + + + return 0; + }else{ + return 0; + } } -int8_t SPIAsEEPROM::write(uint16_t address, uint8_t val) -{ +int8_t SPIAsEEPROM::update(uint16_t address, uint8_t val){ + //a write function call is already an update. + write(address, val); return 0; } -int8_t SPIAsEEPROM::update(uint16_t address, uint8_t val) -{ +uint8_t SPIAsEEPROM::writeMagicNumber(uint16_t sectorNumber){ + //sector adress is for 0 to (FLASHSIZEUSED/SECTORSIZE -1) + //Function is used to write a magic number at the start of each Sector. + //This number can be used to identify if the flash is formated for use as EEPROM + if (sectorNumber>=FLASHSIZEUSED/SECTORSIZE){ + sectorNumber = (FLASHSIZEUSED/SECTORSIZE - 1); + } + + //First erase the sector (4KiB at the time) + winbondSPIFlash.WE(); + winbondSPIFlash.eraseSector(sectorNumber*SECTORSIZE); + while(winbondSPIFlash.busy()); //if no spi flash present or accessible this hangs forever! + + //Write the magic numbers at the start of the sector for identification. + winbondSPIFlash.WE(); + winbondSPIFlash.writePage(sectorNumber*SECTORSIZE, magicbuf, MAGICNUMBER_OFFSET); + while(winbondSPIFlash.busy()); //if no spi flash present or accessible this hangs forever! + return 0; } +uint8_t SPIAsEEPROM::formatFlashForUse(){ + //Format the flash for use by erasing all sectors used and + //write the magic number at the start of each erased sector + for(uint16_t i = 0; i= FLASHSIZEUSED/SECTORSIZE * (SECTORSIZE/FLASH_PAGESIZE - 2)){addressEEPROM = FLASHSIZEUSED/SECTORSIZE * (SECTORSIZE/FLASH_PAGESIZE - 2);} + + //Check at what sector number the adress resides. 14 bytes per sector + sectorNumber = addressEEPROM/(SECTORSIZE/FLASH_PAGESIZE - 2); + + //Check at what page number in the sector the adress can be found (16 pages per sector, 14 used) + pageNumber = addressEEPROM - (sectorNumber * ((SECTORSIZE/FLASH_PAGESIZE) - 2)); + + //The absulute adress of the infoblock of the byte in flash adress + infoFlashAddress = sectorNumber*SECTORSIZE + pageNumber * INFOBYTES_PER_BYTE + MAGICNUMBER_OFFSET; + + //read the infoblock and put into the buffer + winbondSPIFlash.read(infoFlashAddress, buf, sizeof(buf)); + while(winbondSPIFlash.busy()); //if no spi flash present or accessible this hangs forever! + + //calculate actual flash address of the data + //Count de number of set bits in the infoblock + nrOfOnes = count(buf); + + //Calulate the adress from all previous information. + dataFlashAddress = sectorNumber*SECTORSIZE + (pageNumber * FLASH_PAGESIZE) + INFOBYTESSECTOROFFSET + nrOfOnes - 1; + + uint8_t ByteBuf[1]; + //read the actual byte with information + + winbondSPIFlash.read(dataFlashAddress, ByteBuf, sizeof(ByteBuf)); + while(winbondSPIFlash.busy()); //if no spi flash present or accessible this hangs forever! + + return ByteBuf[0]; +} + +uint16_t SPIAsEEPROM::count(uint8_t buf[FLASH_PAGESIZE/BITS_PER_BYTE]){ + uint16_t count=0; + for(uint8_t j=0; j < 32; j++) + for(uint8_t i=0; i<8; i++){ + if((buf[j] & 1) == 1){ //if current bit 1 + count++;//increase count + } + buf[j]=buf[j]>>1;//right shift + } + return count; +} + SPIAsEEPROM EEPROM; #endif \ No newline at end of file diff --git a/speeduino/src/SPIAsEEPROM/SPIAsEEPROM.h b/speeduino/src/SPIAsEEPROM/SPIAsEEPROM.h index 0acaf828..62dc1337 100644 --- a/speeduino/src/SPIAsEEPROM/SPIAsEEPROM.h +++ b/speeduino/src/SPIAsEEPROM/SPIAsEEPROM.h @@ -1,21 +1,82 @@ +/* Speeduino SPIAsEEPROM Library v.1.0.0 + * Copyright (C) 2019 by Tjeerd Hoogendijk + * Created by Tjeerd Hoogendijk - 21/09/2019 + * + * This file is part of the Speeduino project. This library is for + * Winbond SPI flash memory modules. In its current form it enables reading + * and writing individual bytes as if it where an AVR EEPROM. It uses some + * wear leveling (256x). When the begin() fuction is called for the first time + * it will "format" the flash chip. + * !!!!THIS DISTROYS ANY EXISTING DATA ON THE SPI FLASH!!! + * + * 1757184 bytes used of the SPI flash resulting in 6006 bytes of usable EEPROM + * + * This Library 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 Library 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 v3.0 + * along with the Arduino SPIMemory Library. If not, see + * . + */ + #ifndef SPI_AS_EEPROM_H #define SPI_AS_EEPROM_H -#if defined(SPI_AS_EEPROM) +#if defined(CORE_STM32_OFFICIAL) && defined(SPIFLASH_AS_EEPROM) + +#define FLASHSIZEUSED 1757184 //must be a multiple of sectorsize //1757184 = 6006 bytes of EEPROM +#define BYTESPERSECTOR 14 +#define SECTORSIZE 4096 +#define INFOBYTESSECTOROFFSET 512 +#define FLASH_PAGESIZE 256 +#define MAGICNUMBER1 0xC0 +#define MAGICNUMBER2 0xFF +#define MAGICNUMBER3 0xEE +#define MAGICNUMBER_OFFSET 4 +#define BITS_PER_BYTE 8 + +//Need one bit per byte to determine location actual data +//256bits/8 so 32 bytes +#define INFOBYTES_PER_BYTE FLASH_PAGESIZE/BITS_PER_BYTE #include +#include +#include "winbondflash.h" class SPIAsEEPROM { private: - + winbondFlashSPI winbondSPIFlash; + uint8_t SpiFlashAvialable = 0; + uint8_t ReadOutBuffer[BYTESPERSECTOR]; + uint8_t magicbuf[4]; + uint16_t sectorNumber; + uint16_t pageNumber; + uint16_t nrOfOnes; + uint32_t dataFlashAddress; + uint32_t infoFlashAddress; + uint8_t writeMagicNumber(uint16_t sectorNumber); + uint16_t count(uint8_t buf[FLASH_PAGESIZE/BITS_PER_BYTE]); + public: + SPIAsEEPROM(); - uint8_t read(uint16_t address); - int8_t write(uint16_t address, uint8_t val); + uint8_t begin(); + uint8_t formatFlashForUse(); + uint8_t read(uint16_t addressEEPROM); + int8_t write(uint16_t addressEEPROM, uint8_t val); int8_t update(uint16_t address, uint8_t val); }; extern SPIAsEEPROM EEPROM; #endif -#endif \ No newline at end of file +#endif + + diff --git a/speeduino/src/SPIAsEEPROM/winbondflash.cpp b/speeduino/src/SPIAsEEPROM/winbondflash.cpp new file mode 100644 index 00000000..ebc13a3d --- /dev/null +++ b/speeduino/src/SPIAsEEPROM/winbondflash.cpp @@ -0,0 +1,373 @@ +/* + Winbond spi flash memory chip operating library for Arduino + by WarMonkey (luoshumymail@gmail.com) + for more information, please visit bbs.kechuang.org + latest version available on http://code.google.com/p/winbondflash +*/ + +#include +#include +#include +#include "winbondflash.h" + +//COMMANDS +#define W_EN 0x06 //write enable +#define W_DE 0x04 //write disable +#define R_SR1 0x05 //read status reg 1 +#define R_SR2 0x35 //read status reg 2 +#define W_SR 0x01 //write status reg +#define PAGE_PGM 0x02 //page program +#define QPAGE_PGM 0x32 //quad input page program +#define BLK_E_64K 0xD8 //block erase 64KB +#define BLK_E_32K 0x52 //block erase 32KB +#define SECTOR_E 0x20 //sector erase 4KB +#define CHIP_ERASE 0xc7 //chip erase +#define CHIP_ERASE2 0x60 //=CHIP_ERASE +#define E_SUSPEND 0x75 //erase suspend +#define E_RESUME 0x7a //erase resume +#define PDWN 0xb9 //power down +#define HIGH_PERF_M 0xa3 //high performance mode +#define CONT_R_RST 0xff //continuous read mode reset +#define RELEASE 0xab //release power down or HPM/Dev ID (deprecated) +#define R_MANUF_ID 0x90 //read Manufacturer and Dev ID (deprecated) +#define R_UNIQUE_ID 0x4b //read unique ID (suggested) +#define R_JEDEC_ID 0x9f //read JEDEC ID = Manuf+ID (suggested) +#define READ 0x03 +#define FAST_READ 0x0b + +#define SR1_BUSY_MASK 0x01 +#define SR1_WEN_MASK 0x02 + +#define WINBOND_MANUF 0xef + +#define DEFAULT_TIMEOUT 200 + +typedef struct { + winbondFlashClass::partNumber pn; + uint16_t id; + uint32_t bytes; + uint32_t pages; + uint16_t sectors; + uint16_t blocks; +}pnListType; + +static const pnListType pnList[] PROGMEM = { + { winbondFlashClass::W25Q80, 0x4014,1048576, 4096, 256, 16 }, + { winbondFlashClass::W25Q16, 0x4015,2097152, 8192, 512, 32 }, + { winbondFlashClass::W25Q32, 0x4016,4194304, 16384,1024,64 }, + { winbondFlashClass::W25Q64, 0x4017,8388608, 32768,2048,128 }, + { winbondFlashClass::W25Q128,0x4018,16777216,65536,4096,256 } +}; + + +uint16_t winbondFlashClass::readSR() +{ + uint8_t r1,r2; + select(); + transfer(R_SR1); + r1 = transfer(0xff); + deselect(); + deselect();//some delay + select(); + transfer(R_SR2); + r2 = transfer(0xff); + deselect(); + return (((uint16_t)r2)<<8)|r1; +} + +uint8_t winbondFlashClass::readManufacturer() +{ + uint8_t c; + select(); + transfer(R_JEDEC_ID); + c = transfer(0x00); + transfer(0x00); + transfer(0x00); + deselect(); + return c; +} + +uint64_t winbondFlashClass::readUniqueID() +{ + uint64_t uid; + uint8_t *arr; + arr = (uint8_t*)&uid; + select(); + transfer(R_UNIQUE_ID); + transfer(0x00); + transfer(0x00); + transfer(0x00); + transfer(0x00); + //for little endian machine only + for(int i=7;i>=0;i--) + { + arr[i] = transfer(0x00); + } + deselect(); + return uid; +} + +uint16_t winbondFlashClass::readPartID() +{ + uint8_t a,b; + select(); + transfer(R_JEDEC_ID); + transfer(0x00); + a = transfer(0x00); + b = transfer(0x00); + deselect(); + return (a<<8)|b; +} + +bool winbondFlashClass::checkPartNo(partNumber _partno) +{ + uint8_t manuf; + uint16_t id; + + select(); + transfer(R_JEDEC_ID); + manuf = transfer(0x00); + id = transfer(0x00) << 8; + id |= transfer(0x00); + deselect(); + + if(manuf != WINBOND_MANUF){ + return false; + } + + if(_partno == custom) + return true; + + if(_partno == autoDetect) + { + for(uint32_t i=0;i3us + + if(!checkPartNo(_partno)) return false; + else return true; +} + +void winbondFlashClass::end() +{ + select(); + transfer(PDWN); + deselect(); + delayMicroseconds(15);//>3us +} + +uint16_t winbondFlashClass::read (uint32_t addr,uint8_t *buf,uint16_t n) +{ + if(busy()) + return 0; + + select(); + transfer(READ); + transfer(addr>>16); + transfer(addr>>8); + transfer(addr); + for(uint16_t i=0;i>16); + transfer(addr_start>>8); + transfer(addr_start); + + + for(uint16_t i=0; i < n; i++) + { + transfer(buf[i]); + } + + //uint8_t i=0; + //do { + // transfer(buf[i]); + // i++; + //}while(i!=0); + + deselect(); +} + +void winbondFlashClass::eraseSector(uint32_t addr_start) +{ + select(); + transfer(SECTOR_E); + transfer(addr_start>>16); + transfer(addr_start>>8); + transfer(addr_start); + deselect(); +} + +void winbondFlashClass::erase32kBlock(uint32_t addr_start) +{ + select(); + transfer(BLK_E_32K); + transfer(addr_start>>16); + transfer(addr_start>>8); + transfer(addr_start); + deselect(); +} + +void winbondFlashClass::erase64kBlock(uint32_t addr_start) +{ + select(); + transfer(BLK_E_64K); + transfer(addr_start>>16); + transfer(addr_start>>8); + transfer(addr_start); + deselect(); +} + +void winbondFlashClass::eraseAll() +{ + select(); + transfer(CHIP_ERASE); + deselect(); +} + +void winbondFlashClass::eraseSuspend() +{ + select(); + transfer(E_SUSPEND); + deselect(); +} + +void winbondFlashClass::eraseResume() +{ + select(); + transfer(E_RESUME); + deselect(); +} + +bool winbondFlashSPI::begin(partNumber _partno,SPIClass &_spi,uint8_t _nss) +{ + //spi = _spi; + nss = _nss; + + // pinMode(MISO,INPUT_PULLUP); + SPI.begin(); + SPI.setBitOrder(MSBFIRST); + SPI.setClockDivider(SPI_CLOCK_DIV2); + SPI.setDataMode(SPI_MODE0); + deselect(); + // Serial.println("SPI OK"); + + return winbondFlashClass::begin(_partno); +} + +void winbondFlashSPI::end() +{ + winbondFlashClass::end(); + SPI.end(); +} + + + diff --git a/speeduino/src/SPIAsEEPROM/winbondflash.h b/speeduino/src/SPIAsEEPROM/winbondflash.h new file mode 100644 index 00000000..0fda28b9 --- /dev/null +++ b/speeduino/src/SPIAsEEPROM/winbondflash.h @@ -0,0 +1,104 @@ +/* + Winbond spi flash memory chip operating library for Arduino + by WarMonkey (luoshumymail@gmail.com) + for more information, please visit bbs.kechuang.org + latest version available on http://code.google.com/p/winbondflash +*/ + +#ifndef _WINBONDFLASH_H__ +#define _WINBONDFLASH_H__ + +#include +#include + +//W25Q64 = 256_bytes_per_page * 16_pages_per_sector * 16_sectors_per_block * 128_blocks_per_chip +//= 256b*16*16*128 = 8Mbyte = 64MBits + +#define _W25Q80 winbondFlashClass::W25Q80 +#define _W25Q16 winbondFlashClass::W25Q16 +#define _W25Q32 winbondFlashClass::W25Q32 +#define _W25Q64 winbondFlashClass::W25Q64 +#define _W25Q128 winbondFlashClass::W25Q128 + +class winbondFlashClass { +public: + enum partNumber { + custom = -1, + autoDetect = 0, + W25Q80 = 1, + W25Q16 = 2, + W25Q32 = 4, + W25Q64 = 8, + W25Q128 = 16 + }; + + bool begin(partNumber _partno = autoDetect); + void end(); + + long bytes(); + uint16_t pages(); + uint16_t sectors(); + uint16_t blocks(); + + uint16_t read(uint32_t addr,uint8_t *buf,uint16_t n=256); + + void setWriteEnable(bool cmd = true); + inline void WE(bool cmd = true) {setWriteEnable(cmd);} + + //WE() every time before write or erase + void writePage(uint32_t addr_start,uint8_t *buf, uint16_t n);//addr is 8bit-aligned, 0x00ffff00 + //write a page, sizeof(buf) is 256 bytes + void eraseSector(uint32_t addr);//addr is 12bit-aligned, 0x00fff000 + //erase a sector ( 4096bytes ), return false if error + void erase32kBlock(uint32_t addr);//addr is 15bit-aligned, 0x00ff8000 + //erase a 32k block ( 32768b ) + void erase64kBlock(uint32_t addr);//addr is 16bit-aligned, 0x00ff0000 + //erase a 64k block ( 65536b ) + void eraseAll(); + //chip erase, return true if successfully started, busy()==false -> erase complete + + void eraseSuspend(); + void eraseResume(); + + bool busy(); + + uint8_t readManufacturer(); + uint16_t readPartID(); + uint64_t readUniqueID(); + uint16_t readSR(); + +private: + partNumber partno; + bool checkPartNo(partNumber _partno); + +protected: + virtual void select() = 0; + virtual uint8_t transfer(uint8_t x) = 0; + virtual void deselect() = 0; + +}; + +class winbondFlashSPI: public winbondFlashClass { +private: + uint8_t nss; + // SPIClass spi; + inline void select() { + digitalWrite(nss,LOW); + } + + inline uint8_t transfer(uint8_t x) { + byte y = SPI.transfer(x); + return y; + } + + inline void deselect() { + digitalWrite(nss,HIGH); + } + +public: + bool begin(partNumber _partno = autoDetect,SPIClass &_spi = SPI,uint8_t _nss = SS); + void end(); +}; + +#endif + diff --git a/speeduino/storage.ino b/speeduino/storage.ino index 0970bfc4..b39350d5 100644 --- a/speeduino/storage.ino +++ b/speeduino/storage.ino @@ -428,6 +428,7 @@ void writeConfig(byte tableNum) void loadConfig() { + int offset; //Create a pointer to the config page byte* pnt_configPage; diff --git a/speeduino/utils.h b/speeduino/utils.h index 34cde4a6..56f737f6 100644 --- a/speeduino/utils.h +++ b/speeduino/utils.h @@ -6,6 +6,7 @@ These are some utility functions and variables used through the main code #include +#define CONCATS(s1, s2) (s1" " s2) //needed for some reason. not defined correctly because of utils.h file of speeduino (same name as one in arduino core) void setResetControlPinState(); byte pinTranslate(byte); uint32_t calculateCRC32(byte);