Merge branch 'FixTimers_STM32F4'

This commit is contained in:
hoogendijkta 2019-09-30 21:44:23 +02:00
commit a8bc25bd9d
13 changed files with 1242 additions and 230 deletions

View File

@ -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]

View File

@ -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

View File

@ -2,7 +2,8 @@
#define STM32F407VE_H
#if defined(CORE_STM32_OFFICIAL)
#include <Arduino.h>
#include <timer.h>
#include <HardwareTimer.h>
#include <HardwareSerial.h>
#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 <EEPROM.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*);
/*
***********************************************************************************************************

View File

@ -4,56 +4,21 @@
#include "auxiliaries.h"
#include "idle.h"
#include "scheduler.h"
#include <timer.h>
#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 <stm32_TIM_variant_11.h>
// #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<char*>(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

View File

@ -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

View File

@ -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

View File

@ -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 );

View File

@ -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
* <http://www.gnu.org/licenses/>.
*/
#if defined(CORE_STM32_OFFICIAL) && defined(SPIFLASH_AS_EEPROM)
#include "SPIAsEEPROM.h"
#include "SPIMemory.h"
#include <SPI.h>
//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; i++){
writeMagicNumber(i);
}
return 0;
}
uint8_t SPIAsEEPROM::read(uint16_t addressEEPROM){
//The infoblock is at the start of each sector
//The first two pages will be used for the infoblock
//The first 4 bytes of each page must have the magic number
//version 0.1 does not check magic number
if(!SpiFlashAvialable){
begin();
}
uint8_t buf[INFOBYTES_PER_BYTE];
//Check if address is outside of the maximum. limit to get inside maximum and continue as normal.
//Should be changed so that it returns -1 (error)
if (addressEEPROM >= 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

View File

@ -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
* <http://www.gnu.org/licenses/>.
*/
#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 <stdint.h>
#include <SPI.h>
#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
#endif

View File

@ -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 <Arduino.h>
#include <SPI.h>
#include <errno.h>
#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;i<sizeof(pnList)/sizeof(pnList[0]);i++)
{
if(id == pgm_read_word(&(pnList[i].id)))
{
_partno = (partNumber)pgm_read_byte(&(pnList[i].pn));
return true;
}
}
if(_partno == autoDetect)
{
return false;
}
}
//test chip id and partNo
for(uint32_t i=0;i<sizeof(pnList)/sizeof(pnList[0]);i++)
{
if(_partno == (partNumber)pgm_read_byte(&(pnList[i].pn)))
{
if(id == pgm_read_word(&(pnList[i].id)))//id equal
return true;
else
return false;
}
}
return false;//partNo not found
}
bool winbondFlashClass::busy()
{
uint8_t r1;
select();
transfer(R_SR1);
r1 = transfer(0xff);
deselect();
if(r1 & SR1_BUSY_MASK)
return true;
return false;
}
void winbondFlashClass::setWriteEnable(bool cmd)
{
select();
transfer( cmd ? W_EN : W_DE );
deselect();
}
long winbondFlashClass::bytes()
{
for(uint32_t i=0;i<sizeof(pnList)/sizeof(pnList[0]);i++)
{
if(partno == (partNumber)pgm_read_byte(&(pnList[i].pn)))
{
return pgm_read_dword(&(pnList[i].bytes));
}
}
return 0;
}
uint16_t winbondFlashClass::pages()
{
for(uint32_t i=0;i<sizeof(pnList)/sizeof(pnList[0]);i++)
{
if(partno == (partNumber)pgm_read_byte(&(pnList[i].pn)))
{
return pgm_read_word(&(pnList[i].pages));
}
}
return 0;
}
uint16_t winbondFlashClass::sectors()
{
for(uint32_t i=0;i<sizeof(pnList)/sizeof(pnList[0]);i++)
{
if(partno == (partNumber)pgm_read_byte(&(pnList[i].pn)))
{
return pgm_read_word(&(pnList[i].sectors));
}
}
return 0;
}
uint16_t winbondFlashClass::blocks()
{
for(uint32_t i=0;i<sizeof(pnList)/sizeof(pnList[0]);i++)
{
if(partno == (partNumber)pgm_read_byte(&(pnList[i].pn)))
{
return pgm_read_word(&(pnList[i].blocks));
}
}
return 0;
}
bool winbondFlashClass::begin(partNumber _partno)
{
select();
transfer(RELEASE);
deselect();
delayMicroseconds(15);//>3us
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<n;i++)
{
buf[i] = transfer(0x00);
}
deselect();
return n;
}
void winbondFlashClass::writePage(uint32_t addr_start,uint8_t *buf, uint16_t n)
{
select();
transfer(PAGE_PGM);
transfer(addr_start>>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();
}

View File

@ -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 <inttypes.h>
#include <SPI.h>
//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

View File

@ -428,6 +428,7 @@ void writeConfig(byte tableNum)
void loadConfig()
{
int offset;
//Create a pointer to the config page
byte* pnt_configPage;

View File

@ -6,6 +6,7 @@ These are some utility functions and variables used through the main code
#include <Arduino.h>
#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);