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 framework = arduino
;board = genericSTM32F407VET6 ;board = genericSTM32F407VET6
board = black_f407ve board = black_f407ve
lib_deps = EEPROM ;lib_deps = EEPROM
board_build.core = stm32 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 -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 upload_protocol = serial
[env:bluepill_f103c8] [env:bluepill_f103c8]

View File

@ -213,7 +213,7 @@ page = 1
unused1-3c = bits, U08, 3, [2:7], "MAP", "TPS", "INVALID", "INVALID" unused1-3c = bits, U08, 3, [2:7], "MAP", "TPS", "INVALID", "INVALID"
wueRates = array, U08, 4, [10], "%", 1.0, 0.0, 0.0, 255, 0 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 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" 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" tachoDiv = bits, U08, 16, [6:7], "Normal", "Half", "INVALID", "INVALID"
tachoDuration = scalar, U08, 17, "ms", 1.0, 0.0, 1.0, 6.0, 0 tachoDuration = scalar, U08, 17, "ms", 1.0, 0.0, 1.0, 6.0, 0

View File

@ -2,7 +2,8 @@
#define STM32F407VE_H #define STM32F407VE_H
#if defined(CORE_STM32_OFFICIAL) #if defined(CORE_STM32_OFFICIAL)
#include <Arduino.h> #include <Arduino.h>
#include <timer.h> #include <HardwareTimer.h>
#include <HardwareSerial.h>
#include "stm32f4xx_ll_tim.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() #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) #if defined(SRAM_AS_EEPROM)
#define EEPROM_LIB_H "src/BackupSram/BackupSramAsEEPROM.h" #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" #define EEPROM_LIB_H "src/SPIAsEEPROM/SPIAsEEPROM.h"
#else #else
#define EEPROM_LIB_H <EEPROM.h> #define EEPROM_LIB_H <EEPROM.h>
@ -28,10 +29,10 @@
#define USE_SERIAL3 #define USE_SERIAL3
void initBoard(); void initBoard();
uint16_t freeRam(); uint16_t freeRam();
extern void oneMSIntervalIRQ(stimer_t *Timer);
extern void EmptyIRQCallback(stimer_t *Timer, uint32_t channel);
extern "C" char* sbrk(int incr); extern "C" char* sbrk(int incr);
/* /*
*********************************************************************************************************** ***********************************************************************************************************
* Schedules * Schedules
@ -154,6 +155,26 @@ extern "C" char* sbrk(int incr);
* Timers * 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 "auxiliaries.h"
#include "idle.h" #include "idle.h"
#include "scheduler.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() 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 * General
*/ */
#define FLASH_LENGTH 8192 #ifndef FLASH_LENGTH
#define FLASH_LENGTH 8192
#endif
delay(10);
/* /*
*********************************************************************************************************** ***********************************************************************************************************
* Idle * Idle
@ -64,14 +29,9 @@
} }
//This must happen at the end of the idle init //This must happen at the end of the idle init
TimerPulseInit(&HardwareTimers_1, 0xFFFF, 0, EmptyIRQCallback); Timer1.setMode(4, TIMER_OUTPUT_COMPARE);
//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);
//timer_set_mode(TIMER1, 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); } //on first flash the configPage4.iacAlgorithm is invalid
//if(idle_pwm_max_count > 0) { Timer1.attachInterrupt(4, idleInterrupt);}
//Timer1.resume();
/* /*
@ -79,10 +39,15 @@
* Timers * Timers
*/ */
#if defined(ARDUINO_BLACK_F407VE) || defined(STM32F4) || defined(_STM32F4_) #if defined(ARDUINO_BLACK_F407VE) || defined(STM32F4) || defined(_STM32F4_)
TimerHandleInit(&HardwareTimers_8, 1000, 168); Timer8.setOverflow(1000, MICROSEC_FORMAT); // Set up period
attachIntHandle(&HardwareTimers_8, oneMSIntervalIRQ); Timer8.setMode(1, TIMER_OUTPUT_COMPARE);
Timer8.attachInterrupt(1, oneMSInterval);
Timer8.resume(); //Start Timer
#else #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 #endif
pinMode(LED_BUILTIN, OUTPUT); //Visual WDT 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 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 //Need to be initialised last due to instant interrupt
// Timer1.setMode(2, TIMER_OUTPUT_COMPARE); Timer1.setMode(2, TIMER_OUTPUT_COMPARE);
// Timer1.setMode(3, TIMER_OUTPUT_COMPARE); Timer1.setMode(3, TIMER_OUTPUT_COMPARE);
// if(boost_pwm_max_count > 0) { Timer1.attachInterrupt(2, boostInterrupt);} if(boost_pwm_max_count > 0) { Timer1.attachInterrupt(2, boostInterrupt);}
// if(vvt_pwm_max_count > 0) { Timer1.attachInterrupt(3, vvtInterrupt);} 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);
TimerPulseInit(&HardwareTimers_2, 0xFFFF, 0, EmptyIRQCallback); /*
attachIntHandleOC(&HardwareTimers_2, ignitionSchedule1Interrupt, 1, 0); ***********************************************************************************************************
attachIntHandleOC(&HardwareTimers_2, ignitionSchedule2Interrupt, 2, 0); * Schedules
attachIntHandleOC(&HardwareTimers_2, ignitionSchedule3Interrupt, 3, 0); */
attachIntHandleOC(&HardwareTimers_2, ignitionSchedule4Interrupt, 4, 0); Timer1.setOverflow(MAX_TIMER_PERIOD, MICROSEC_FORMAT);
Timer2.setOverflow(MAX_TIMER_PERIOD, MICROSEC_FORMAT);
//Attach interupt functions Timer3.setOverflow(MAX_TIMER_PERIOD, MICROSEC_FORMAT);
//Injection
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); Timer2.setMode(1, TIMER_OUTPUT_COMPARE);
//setTimerPrescalerRegister(&HardwareTimers_4, (uint32_t)(getTimerClkFreq(HardwareTimers_4.timer) / (1000000)) - 1); Timer2.setMode(2, TIMER_OUTPUT_COMPARE);
#if (IGN_CHANNELS >= 5) Timer2.setMode(3, TIMER_OUTPUT_COMPARE);
attachIntHandleOC(&HardwareTimers_4, ignitionSchedule5Interrupt, 1, 0); Timer2.setMode(4, TIMER_OUTPUT_COMPARE);
//Timer4.attachInterrupt(1, ignitionSchedule5Interrupt);
#endif Timer3.setMode(1, TIMER_OUTPUT_COMPARE);
#if (IGN_CHANNELS >= 6) Timer3.setMode(2, TIMER_OUTPUT_COMPARE);
attachIntHandleOC(&HardwareTimers_4, ignitionSchedule6Interrupt, 2, 0); Timer3.setMode(3, TIMER_OUTPUT_COMPARE);
//Timer4.attachInterrupt(2, ignitionSchedule6Interrupt); Timer3.setMode(4, TIMER_OUTPUT_COMPARE);
#endif Timer1.setMode(1, TIMER_OUTPUT_COMPARE);
#if (IGN_CHANNELS >= 7)
attachIntHandleOC(&HardwareTimers_4, ignitionSchedule7Interrupt, 3, 0); //Attach interupt functions
//Timer4.attachInterrupt(3, ignitionSchedule7Interrupt); //Injection
#endif Timer3.attachInterrupt(1, fuelSchedule1Interrupt);
#if (IGN_CHANNELS >= 8) Timer3.attachInterrupt(2, fuelSchedule2Interrupt);
attachIntHandleOC(&HardwareTimers_4, ignitionSchedule8Interrupt, 4, 0); Timer3.attachInterrupt(3, fuelSchedule3Interrupt);
//Timer4.attachInterrupt(4, ignitionSchedule8Interrupt); Timer3.attachInterrupt(4, fuelSchedule4Interrupt);
#endif #if (INJ_CHANNELS >= 5)
Timer5.setMode(1, TIMER_OUTPUT_COMPARE);
setTimerPrescalerRegister(&HardwareTimers_2, (uint32_t)(getTimerClkFreq(HardwareTimers_2.timer) / (250000)) - 1); Timer5.attachInterrupt(1, fuelSchedule5Interrupt);
setTimerPrescalerRegister(&HardwareTimers_3, (uint32_t)(getTimerClkFreq(HardwareTimers_3.timer) / (250000)) - 1); #endif
setTimerPrescalerRegister(&HardwareTimers_4, (uint32_t)(getTimerClkFreq(HardwareTimers_4.timer) / (250000)) - 1); #if (INJ_CHANNELS >= 6)
setTimerPrescalerRegister(&HardwareTimers_5, (uint32_t)(getTimerClkFreq(HardwareTimers_5.timer) / (250000)) - 1); 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() uint16_t freeRam()
@ -169,7 +147,22 @@
return &top - reinterpret_cast<char*>(sbrk(0)); 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 #endif

View File

@ -1641,9 +1641,10 @@ void receiveCalibration(byte tableID)
bool every2nd = true; bool every2nd = true;
int x; int x;
int counter = 0; 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++) 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 //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; every2nd = false;
#if defined(CORE_STM32) #if defined(CORE_STM32)
digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN)); digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN));
#elif defined(CORE_STM32_OFFICIAL)
//Of core offical do nothing. led is reserved for fuel pump
#else #else
analogWrite(LED_BUILTIN, (counter % 50) ); //analogWrite(13, (counter % 50) ); analogWrite(LED_BUILTIN, (counter % 50) ); //analogWrite(13, (counter % 50) );
#endif #endif

View File

@ -38,7 +38,7 @@ void initialiseAll()
//Always start with a clean slate on the bootloader capabilities level //Always start with a clean slate on the bootloader capabilities level
//This should be 0 until we hear otherwise from the 16u2 //This should be 0 until we hear otherwise from the 16u2
configPage4.bootloaderCaps = 0; configPage4.bootloaderCaps = 0;
initBoard(); //This calls the current individual boards init function. See the board_xxx.ino files for these. initBoard(); //This calls the current individual boards init function. See the board_xxx.ino files for these.
initialiseTimers(); initialiseTimers();
@ -1020,46 +1020,108 @@ void setPinMapping(byte boardID)
pinCoil3 = 30; pinCoil3 = 30;
pinO2 = A22; pinO2 = A22;
#elif defined(STM32F4) #elif defined(STM32F4)
//Pin definitions for experimental board Tjeerd
//Black F407VE wiki.stm32duino.com/index.php?title=STM32F407 //Black F407VE wiki.stm32duino.com/index.php?title=STM32F407
//PC8~PC12 SDio
//PA13~PA15 & PB4 SWD(debug) pins //******************************************
//PB0 EEPROM CS pin //******** PORTA CONNECTIONS ***************
//PA9 & PD10 Serial1 //******************************************
//PD5 & PD6 Serial2 // = PA0 //Wakeup ADC123
pinInjector1 = PE7; //Output pin injector 1 is on pinTPS = PA1; //ADC123
pinInjector2 = PE8; //Output pin injector 2 is on pinMAP = PA2; //ADC123
pinInjector3 = PE9; //Output pin injector 3 is on pinIAT = PA3; //ADC123
pinInjector4 = PE10; //Output pin injector 4 is on pinCLT = PA4; //ADC12
pinInjector5 = PE11; //Output pin injector 5 is on pinO2 = PA5; //ADC12
pinInjector6 = PE12; //Output pin injector 6 is on // = PA6; //ADC12 LED_BUILTIN_1
pinCoil1 = PD0; //Pin for coil 1 pinFuelPump = PA7; //ADC12 LED_BUILTIN_2
pinCoil2 = PD1; //Pin for coil 2 pinIdle1 = PA8; //
pinCoil3 = PD2; //Pin for coil 3 // = PA9 //TXD1
pinCoil4 = PD3; //Pin for coil 4 // = PA10 //RXD1
pinCoil5 = PD4; //Pin for coil 5 // = PA11 //(DO NOT USE FOR SPEEDUINO) USB
pinTPS = A0; //TPS input pin // = PA12 //(DO NOT USE FOR SPEEDUINO) USB
pinMAP = A1; //MAP sensor pin // = PA13 //(DO NOT USE FOR SPEEDUINO) //NOT ON GPIO //DEBUG ST-LINK
pinIAT = A2; //IAT sensor pin // = PA14 //(DO NOT USE FOR SPEEDUINO) //NOT ON GPIO //DEBUG ST-LINK
pinCLT = A3; //CLT sensor pin // = PA15 //(DO NOT USE FOR SPEEDUINO) //NOT ON GPIO //DEBUG ST-LINK
pinO2 = A4; //O2 Sensor pin
pinBat = A5; //Battery reference voltage pin //******************************************
pinBaro = A9; //******** PORTB CONNECTIONS ***************
pinIdle1 = PB8; //Single wire idle control //******************************************
pinIdle2 = PB9; //2 wire idle control // = PB0; (DO NOT USE FOR SPEEDUINO)//ADC123 //SPI FLASH CHIP CS pin
pinBoost = PE0; //Boost control pinBaro = PB1; //ADC12
pinVVT_1 = PE1; //Default VVT output // = PB2; //(DO NOT USE FOR SPEEDUINO) BOOT1
pinStepperDir = PD8; //Direction pin for DRV8825 driver // = PB3; //(DO NOT USE FOR SPEEDUINO) SPI1_SCK FLASH CHIP
pinStepperStep = PB15; //Step pin for DRV8825 driver // = PB4; //(DO NOT USE FOR SPEEDUINO) SPI1_MISO FLASH CHIP
pinStepperEnable = PD9; //Enable pin for DRV8825 // = PB5; //(DO NOT USE FOR SPEEDUINO) SPI1_MOSI FLASH CHIP
pinDisplayReset = PE1; // OLED reset pin // = PB6; //NRF_CE
pinFan = PE2; //Pin for the fan output // = PB7; //NRF_CS
pinFuelPump = PC0; //Fuel pump output // = PB8; //NRF_IRQ
pinTachOut = PC1; //Tacho output pin pinIdle2 = PB9; //
//external interrupt enabled pins // = PB10; //TXD3
//external interrupts could be enalbed in any pin, except same port numbers (PA4,PE4) // = PB11; //RXD3
pinFlex = PE2; // Flex sensor (Must be external interrupt enabled) pinBoost = PB12; //
pinTrigger = PE3; //The CAS pin // = PB13; //SPI2_SCK
pinTrigger2 = PE4; //The Cam Sensor pin // = 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) #elif defined(CORE_STM32)
//blue pill wiki.stm32duino.com/index.php?title=Blue_Pill //blue pill wiki.stm32duino.com/index.php?title=Blue_Pill
//Maple mini wiki.stm32duino.com/index.php?title=Maple_Mini //Maple mini wiki.stm32duino.com/index.php?title=Maple_Mini
@ -1566,49 +1628,254 @@ void setPinMapping(byte boardID)
pinSpareLOut1 = 21; //low current output spare1 pinSpareLOut1 = 21; //low current output spare1
break; break;
#endif #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 //Black F407VE wiki.stm32duino.com/index.php?title=STM32F407
//PC8~PC12 SDio
//PA13~PA15 & PB4 SWD(debug) pins //******************************************
//PB0 EEPROM CS pin //******** PORTA CONNECTIONS ***************
//PA9 & PD10 Serial1 //******************************************
//PD5 & PD6 Serial2 // = PA0 //Wakeup ADC123
pinInjector1 = PE7; //Output pin injector 1 is on pinTPS = PA1; //ADC123
pinInjector2 = PE8; //Output pin injector 2 is on pinMAP = PA2; //ADC123
pinInjector3 = PE9; //Output pin injector 3 is on pinIAT = PA3; //ADC123
pinInjector4 = PE10; //Output pin injector 4 is on pinCLT = PA4; //ADC12
pinInjector5 = PE11; //Output pin injector 5 is on pinO2 = PA5; //ADC12
pinInjector6 = PE12; //Output pin injector 6 is on // = PA6; //ADC12 LED_BUILTIN_1
pinCoil1 = PD0; //Pin for coil 1 pinFuelPump = PA7; //ADC12 LED_BUILTIN_2
pinCoil2 = PD1; //Pin for coil 2 pinIdle1 = PA8; //
pinCoil3 = PD2; //Pin for coil 3 // = PA9 //TXD1
pinCoil4 = PD3; //Pin for coil 4 // = PA10 //RXD1
pinCoil5 = PD4; //Pin for coil 5 // = 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 pinTPS = A0; //TPS input pin
pinMAP = A1; //MAP sensor pin pinMAP = A1; //MAP sensor pin
pinIAT = A2; //IAT sensor pin pinIAT = A2; //IAT sensor pin
pinCLT = A3; //CLT sensor pin pinCLT = A3; //CLS sensor pin
pinO2 = A4; //O2 Sensor pin pinO2 = A4; //O2 Sensor pin
pinBat = A5; //Battery reference voltage pin pinBat = A5; //Battery reference voltage pin
pinBaro = A9; pinBaro = pinMAP;
pinIdle1 = PB8; //Single wire idle control pinIdle1 = PB2; //Single wire idle control
pinIdle2 = PB9; //2 wire idle control pinIdle2 = PA2; //2 wire idle control
pinBoost = PE0; //Boost control pinBoost = PA1; //Boost control
pinVVT_1 = PE1; //Default VVT output pinVVT_1 = PA0; //Default VVT output
pinStepperDir = PD8; //Direction pin for DRV8825 driver pinStepperDir = PC15; //Direction pin for DRV8825 driver
pinStepperStep = PB15; //Step pin for DRV8825 driver pinStepperStep = PC14; //Step pin for DRV8825 driver
pinStepperEnable = PD9; //Enable pin for DRV8825 pinStepperEnable = PC13; //Enable pin for DRV8825
pinDisplayReset = PE1; // OLED reset pin pinDisplayReset = PB2; // OLED reset pin
pinFan = PE2; //Pin for the fan output pinFan = PB1; //Pin for the fan output
pinFuelPump = PC0; //Fuel pump output pinFuelPump = PB11; //Fuel pump output
pinTachOut = PC1; //Tacho output pin pinTachOut = PB10; //Tacho output pin
//external interrupt enabled pins //external interrupt enabled pins
//external interrupts could be enalbed in any pin, except same port numbers (PA4,PE4) pinFlex = PB8; // Flex sensor (Must be external interrupt enabled)
pinFlex = PE2; // Flex sensor (Must be external interrupt enabled) pinTrigger = PA10; //The CAS pin
pinTrigger = PE3; //The CAS pin pinTrigger2 = PA13; //The Cam Sensor pin
pinTrigger2 = PE4; //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 #else
#ifndef SMALL_FLASH_MODE //No support for bluepill here anyway #ifndef SMALL_FLASH_MODE //No support for bluepill here anyway
//Pin mappings as per the v0.2 shield //Pin mappings as per the v0.2 shield

View File

@ -12,7 +12,7 @@
class BackupSramAsEEPROM { class BackupSramAsEEPROM {
private: 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 write_byte( uint8_t *data, uint16_t bytes, uint16_t offset );
int8_t read_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 @@
/* /* Speeduino SPIAsEEPROM Library v.1.0.0
* This file implements a shim layer for the SPIMemory library (https://github.com/Marzogh/SPIMemory) to mimic a minimal * Copyright (C) 2019 by Tjeerd Hoogendijk
* subset of the standard Arduino EEPROM library * Created by Tjeerd Hoogendijk - 21/09/2019
*/ *
#if defined(SPI_AS_EEPROM) * 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 "SPIAsEEPROM.h"
#include "SPIMemory.h" #include "SPI.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
SPIAsEEPROM::SPIAsEEPROM() 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 uint8_t SPIAsEEPROM::begin() {
//flash.begin(MB(1));
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; 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; 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; SPIAsEEPROM EEPROM;
#endif #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 #ifndef SPI_AS_EEPROM_H
#define 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 <stdint.h>
#include <SPI.h>
#include "winbondflash.h"
class SPIAsEEPROM { class SPIAsEEPROM {
private: 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: public:
SPIAsEEPROM(); SPIAsEEPROM();
uint8_t read(uint16_t address); uint8_t begin();
int8_t write(uint16_t address, uint8_t val); 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); int8_t update(uint16_t address, uint8_t val);
}; };
extern SPIAsEEPROM EEPROM; extern SPIAsEEPROM EEPROM;
#endif #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() void loadConfig()
{ {
int offset; int offset;
//Create a pointer to the config page //Create a pointer to the config page
byte* pnt_configPage; byte* pnt_configPage;

View File

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