Compile (but not link) cleanly on stm32

This commit is contained in:
Josh Stewart 2017-03-23 17:19:18 +11:00
parent d38a9584c5
commit a5e47cb3ff
8 changed files with 131 additions and 41 deletions

View File

@ -28,11 +28,19 @@ framework = energia
board = lptm4c1294ncpdt
lib_deps = EEPROM
[env:genericSTM32F103RB]
[env:genericSTM32F103R8]
platform = ststm32
framework = arduino
; framework-arduinoststm32
board = genericSTM32F103RB
board = genericSTM32F103R8
lib_deps = EEPROM
build_flags = -fpermissive -std=gnu++11
[env:bluepill_f103c8]
platform = ststm32
framework = arduino
; framework-arduinoststm32
board = bluepill_f103c8
lib_deps = EEPROM
build_flags = -fpermissive -std=gnu++11
@ -43,4 +51,5 @@ env_default = megaatmega2560
;The following lines are for testing / experimentation only. Comment the line above to try them out
;env_default = teensy35
;env_default = LaunchPad_tm4c1294ncpdt
;env_default = genericSTM32F103RB
;env_default = genericSTM32F103R8
;env_default = bluepill_f103c8

View File

@ -204,10 +204,13 @@ void sendValues(int packetlength, byte portNum)
if (portNum == 3)
{
//CAN serial
#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) //ATmega2561 does not have Serial3
//CAN serial
Serial3.write("A"); //confirm cmd type
Serial3.write(packetlength); //confirm no of byte to be sent
#elif defined(CORE_STM32)
Serial2.write("A"); //confirm cmd type
Serial2.write(packetlength); //confirm no of byte to be sent
#endif
}
else
@ -271,6 +274,8 @@ void sendValues(int packetlength, byte portNum)
if (portNum == 0) { Serial.write(response, (size_t)packetlength); }
#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) //ATmega2561 does not have Serial3
else if (portNum == 3) { Serial3.write(response, (size_t)packetlength); }
#elif defined(CORE_STM32)
else if (portNum == 3) { Serial2.write(response, (size_t)packetlength); }
#endif
//sei();
return;

View File

@ -9,7 +9,8 @@
#define CORE_STM32
inline unsigned char digitalPinToInterrupt(unsigned char Interrupt_pin) { return Interrupt_pin; } //This isn't included in the stm32duino libs (yet)
#define portOutputRegister(port) (volatile byte *)( &(port->regs->ODR) ) //Seems to be missing from stm32duino. Not even sure it's correct yet
#define portOutputRegister(port) (volatile byte *)( &(port->regs->ODR) ) //These are defined in STM32F1/variants/generic_stm32f103c/variant.h but return a non byte* value
#define portInputRegister(port) (volatile byte *)( &(port->regs->IDR) ) //These are defined in STM32F1/variants/generic_stm32f103c/variant.h but return a non byte* value
#endif
//Handy bitsetting macros

View File

@ -157,8 +157,56 @@ See page 136 of the processors datasheet: http://www.atmel.com/Images/doc2549.pd
#elif defined(STM32_MCU_SERIES)
//Placeholders ONLY!
//https://github.com/rogerclarkmelbourne/Arduino_STM32/blob/master/STM32F4/cores/maple/libmaple/timer.h#L51
#define MAX_TIMER_PERIOD 139808 // 2.13333333uS * 65535
#define uS_TO_TIMER_COMPARE(uS) ((uS * 15) >> 5) //Converts a given number of uS into the required number of timer ticks until that time has passed.
#define FUEL1_COUNTER (TIMER2->regs).gen->CNT
#define FUEL2_COUNTER (TIMER2->regs).gen->CNT
#define FUEL3_COUNTER (TIMER2->regs).gen->CNT
#define FUEL4_COUNTER (TIMER2->regs).gen->CNT
#define IGN1_COUNTER (TIMER3->regs).gen->CNT
#define IGN2_COUNTER (TIMER3->regs).gen->CNT
#define IGN3_COUNTER (TIMER3->regs).gen->CNT
#define IGN4_COUNTER (TIMER3->regs).gen->CNT
#define IGN5_COUNTER (TIMER1->regs).gen->CNT
#define FUEL1_COMPARE (TIMER2->regs).gen->CCR1
#define FUEL2_COMPARE (TIMER2->regs).gen->CCR2
#define FUEL3_COMPARE (TIMER2->regs).gen->CCR3
#define FUEL4_COMPARE (TIMER2->regs).gen->CCR4
#define IGN1_COMPARE (TIMER3->regs).gen->CCR1
#define IGN2_COMPARE (TIMER3->regs).gen->CCR2
#define IGN3_COMPARE (TIMER3->regs).gen->CCR3
#define IGN4_COMPARE (TIMER3->regs).gen->CCR4
#define IGN5_COMPARE (TIMER1->regs).gen->CCR1
//https://github.com/rogerclarkmelbourne/Arduino_STM32/blob/754bc2969921f1ef262bd69e7faca80b19db7524/STM32F1/system/libmaple/include/libmaple/timer.h#L444
#define FUEL1_TIMER_ENABLE() (TIMER2->regs).gen->CCER |= TIMER_CCER_CC1E
#define FUEL2_TIMER_ENABLE() (TIMER2->regs).gen->CCER |= TIMER_CCER_CC2E
#define FUEL3_TIMER_ENABLE() (TIMER2->regs).gen->CCER |= TIMER_CCER_CC3E
#define FUEL4_TIMER_ENABLE() (TIMER2->regs).gen->CCER |= TIMER_CCER_CC4E
#define IGN1_TIMER_ENABLE() (TIMER3->regs).gen->CCER |= TIMER_CCER_CC1E
#define IGN2_TIMER_ENABLE() (TIMER3->regs).gen->CCER |= TIMER_CCER_CC2E
#define IGN3_TIMER_ENABLE() (TIMER3->regs).gen->CCER |= TIMER_CCER_CC3E
#define IGN4_TIMER_ENABLE() (TIMER3->regs).gen->CCER |= TIMER_CCER_CC4E
#define IGN5_TIMER_ENABLE() (TIMER1->regs).gen->CCER |= TIMER_CCER_CC1E
#define FUEL1_TIMER_DISABLE() (TIMER2->regs).gen->CCER &= ~TIMER_CCER_CC1E
#define FUEL2_TIMER_DISABLE() (TIMER2->regs).gen->CCER &= ~TIMER_CCER_CC2E
#define FUEL3_TIMER_DISABLE() (TIMER2->regs).gen->CCER &= ~TIMER_CCER_CC3E
#define FUEL4_TIMER_DISABLE() (TIMER2->regs).gen->CCER &= ~TIMER_CCER_CC4E
#define IGN1_TIMER_DISABLE() (TIMER3->regs).gen->CCER &= ~TIMER_CCER_CC1E
#define IGN2_TIMER_DISABLE() (TIMER3->regs).gen->CCER &= ~TIMER_CCER_CC2E
#define IGN3_TIMER_DISABLE() (TIMER3->regs).gen->CCER &= ~TIMER_CCER_CC3E
#define IGN4_TIMER_DISABLE() (TIMER3->regs).gen->CCER &= ~TIMER_CCER_CC4E
#define IGN5_TIMER_DISABLE() (TIMER1->regs).gen->CCER &= ~TIMER_CCER_CC1E
#endif
void initialiseSchedulers();

View File

@ -428,7 +428,7 @@ void setIgnitionSchedule5(void (*startCallback)(), unsigned long timeout, unsign
//Timer3A (fuel schedule 1) Compare Vector
#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) || defined(__AVR_ATmega2561__) //AVR chips use the ISR for this
ISR(TIMER3_COMPA_vect, ISR_NOBLOCK) //fuelSchedules 1 and 5
#elif defined (CORE_TEENSY)
#elif defined (CORE_TEENSY) || defined(CORE_STM32)
static inline void fuelSchedule1Interrupt() //Most ARM chips can simply call a function
#endif
{
@ -450,7 +450,7 @@ static inline void fuelSchedule1Interrupt() //Most ARM chips can simply call a f
#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) || defined(__AVR_ATmega2561__) //AVR chips use the ISR for this
ISR(TIMER3_COMPB_vect, ISR_NOBLOCK) //fuelSchedule2
#elif defined (CORE_TEENSY)
#elif defined (CORE_TEENSY) || defined(CORE_STM32)
static inline void fuelSchedule2Interrupt() //Most ARM chips can simply call a function
#endif
{
@ -471,7 +471,7 @@ static inline void fuelSchedule2Interrupt() //Most ARM chips can simply call a f
#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) || defined(__AVR_ATmega2561__) //AVR chips use the ISR for this
ISR(TIMER3_COMPC_vect, ISR_NOBLOCK) //fuelSchedule3
#elif defined (CORE_TEENSY)
#elif defined (CORE_TEENSY) || defined(CORE_STM32)
static inline void fuelSchedule3Interrupt() //Most ARM chips can simply call a function
#endif
{
@ -492,7 +492,7 @@ static inline void fuelSchedule3Interrupt() //Most ARM chips can simply call a f
#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) || defined(__AVR_ATmega2561__) //AVR chips use the ISR for this
ISR(TIMER4_COMPB_vect, ISR_NOBLOCK) //fuelSchedule4
#elif defined (CORE_TEENSY)
#elif defined (CORE_TEENSY) || defined(CORE_STM32)
static inline void fuelSchedule4Interrupt() //Most ARM chips can simply call a function
#endif
{
@ -513,7 +513,7 @@ static inline void fuelSchedule4Interrupt() //Most ARM chips can simply call a f
#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) || defined(__AVR_ATmega2561__) //AVR chips use the ISR for this
ISR(TIMER5_COMPA_vect) //ignitionSchedule1
#elif defined (CORE_TEENSY)
#elif defined (CORE_TEENSY) || defined(CORE_STM32)
static inline void ignitionSchedule1Interrupt() //Most ARM chips can simply call a function
#endif
{
@ -537,7 +537,7 @@ static inline void ignitionSchedule1Interrupt() //Most ARM chips can simply call
#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) || defined(__AVR_ATmega2561__) //AVR chips use the ISR for this
ISR(TIMER5_COMPB_vect) //ignitionSchedule2
#elif defined (CORE_TEENSY)
#elif defined (CORE_TEENSY) || defined(CORE_STM32)
static inline void ignitionSchedule2Interrupt() //Most ARM chips can simply call a function
#endif
{
@ -561,7 +561,7 @@ static inline void ignitionSchedule2Interrupt() //Most ARM chips can simply call
#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) || defined(__AVR_ATmega2561__) //AVR chips use the ISR for this
ISR(TIMER5_COMPC_vect) //ignitionSchedule3
#elif defined (CORE_TEENSY)
#elif defined (CORE_TEENSY) || defined(CORE_STM32)
static inline void ignitionSchedule3Interrupt() //Most ARM chips can simply call a function
#endif
{
@ -585,7 +585,7 @@ static inline void ignitionSchedule3Interrupt() //Most ARM chips can simply call
#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) || defined(__AVR_ATmega2561__) //AVR chips use the ISR for this
ISR(TIMER4_COMPA_vect) //ignitionSchedule4
#elif defined (CORE_TEENSY)
#elif defined (CORE_TEENSY) || defined(CORE_STM32)
static inline void ignitionSchedule4Interrupt() //Most ARM chips can simply call a function
#endif
{
@ -609,7 +609,7 @@ static inline void ignitionSchedule4Interrupt() //Most ARM chips can simply call
#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) || defined(__AVR_ATmega2561__) //AVR chips use the ISR for this
ISR(TIMER1_COMPC_vect) //ignitionSchedule5
#elif defined (CORE_TEENSY)
#elif defined (CORE_TEENSY) || defined(CORE_STM32)
static inline void ignitionSchedule5Interrupt() //Most ARM chips can simply call a function
#endif
{

View File

@ -4,7 +4,7 @@
NOTE - This file and it's associated functions need a CLEARER NAME
//Purpose
We're implementing a lower frequency interrupt loop to perform calculations that are needed less often, some of which depend on time having passed (delta/time) to be meaningful.
We're implementing a lower frequency interrupt loop to perform calculations that are needed less often, some of which depend on time having passed (delta/time) to be meaningful.
//Technical
@ -12,7 +12,7 @@ Timer2 is only 8bit so we are setting the prescaler to 128 to get the most out o
Max Period = (Prescale)*(1/Frequency)*(2^8)
(See http://arduinomega.blogspot.com.au/2011/05/timer2-and-overflow-interrupt-lets-get.html)
We're after a 1ms interval so we'll need 131 intervals to reach this ( 1ms / 0.008ms per tick = 125).
We're after a 1ms interval so we'll need 131 intervals to reach this ( 1ms / 0.008ms per tick = 125).
Hence we will preload the timer with 131 cycles to leave 125 until overflow (1ms).
*/
@ -29,6 +29,8 @@ volatile uint16_t lastRPM_100ms; //Need to record this for rpmDOT calculation
#if defined (CORE_TEENSY)
IntervalTimer lowResTimer;
void oneMSInterval();
#elif defined(CORE_STM32)
void oneMSInterval();
#endif
void initialiseTimers();

View File

@ -18,10 +18,10 @@ Timers are typically low resolution (Compared to Schedulers), with maximum frequ
#include <avr/wdt.h>
#endif
void initialiseTimers()
{
void initialiseTimers()
{
#if defined(CORE_AVR) //AVR chips use the ISR for this
//Configure Timer2 for our low-freq interrupt code.
//Configure Timer2 for our low-freq interrupt code.
TCCR2B = 0x00; //Disbale Timer2 while we set it up
TCNT2 = 131; //Preload timer2 with 131 cycles, leaving 125 till overflow. As the timer runs at 125Khz, this causes overflow to occur at 1Khz = 1ms
TIFR2 = 0x00; //Timer2 INT Flag Reg: Clear Timer Overflow Flag
@ -33,10 +33,15 @@ void initialiseTimers()
//Enable the watchdog timer for 2 second resets (Good reference: https://tushev.org/articles/arduino/5/arduino-and-watchdog-timer)
//wdt_enable(WDTO_2S); //Boooooooooo WDT is currently broken on Mega 2560 bootloaders :(
#elif defined (CORE_TEENSY)
//Uses the PIT timer on Teensy.
lowResTimer.begin(oneMSInterval, 1000);
#elif defined(CORE_STM32)
Timer4.setChannel1Mode(TIMER_OUTPUTCOMPARE);
Timer4.setPeriod(1000);
Timer4.attachCompare1Interrupt(oneMSInterval);
#endif
dwellLimit_uS = (1000 * configPage2.dwellLimit);
@ -47,27 +52,27 @@ void initialiseTimers()
//Timer2 Overflow Interrupt Vector, called when the timer overflows.
//Executes every ~1ms.
#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) //AVR chips use the ISR for this
ISR(TIMER2_OVF_vect, ISR_NOBLOCK)
#elif defined (CORE_TEENSY)
ISR(TIMER2_OVF_vect, ISR_NOBLOCK)
#elif defined (CORE_TEENSY) || defined(CORE_STM32)
void oneMSInterval() //Most ARM chips can simply call a function
#endif
{
//Increment Loop Counters
loop100ms++;
loop250ms++;
loopSec++;
unsigned long targetOverdwellTime;
//Overdwell check
targetOverdwellTime = micros() - dwellLimit_uS; //Set a target time in the past that all coil charging must have begun after. If the coil charge began before this time, it's been running too long
//Check first whether each spark output is currently on. Only check it's dwell time if it is
if(ignitionSchedule1.Status == RUNNING) { if(ignitionSchedule1.startTime < targetOverdwellTime && configPage2.useDwellLim) { endCoil1Charge(); } }
if(ignitionSchedule2.Status == RUNNING) { if(ignitionSchedule2.startTime < targetOverdwellTime && configPage2.useDwellLim) { endCoil2Charge(); } }
if(ignitionSchedule3.Status == RUNNING) { if(ignitionSchedule3.startTime < targetOverdwellTime && configPage2.useDwellLim) { endCoil3Charge(); } }
if(ignitionSchedule4.Status == RUNNING) { if(ignitionSchedule4.startTime < targetOverdwellTime && configPage2.useDwellLim) { endCoil4Charge(); } }
if(ignitionSchedule4.Status == RUNNING) { if(ignitionSchedule4.startTime < targetOverdwellTime && configPage2.useDwellLim) { endCoil4Charge(); } }
if(ignitionSchedule5.Status == RUNNING) { if(ignitionSchedule5.startTime < targetOverdwellTime && configPage2.useDwellLim) { endCoil5Charge(); } }
//Loop executed every 100ms loop
@ -79,30 +84,30 @@ void oneMSInterval() //Most ARM chips can simply call a function
currentStatus.rpmDOT = (currentStatus.RPM - lastRPM_100ms) * 10; //This is the RPM per second that the engine has accelerated/decelleratedin the last loop
lastRPM_100ms = currentStatus.RPM; //Record the current RPM for next calc
}
//Loop executed every 250ms loop (1ms x 250 = 250ms)
//Anything inside this if statement will run every 250ms.
if (loop250ms == 250)
if (loop250ms == 250)
{
loop250ms = 0; //Reset Counter.
#if defined(CORE_AVR)
//wdt_reset(); //Reset watchdog timer
#endif
}
//Loop executed every 1 second (1ms x 1000 = 1000ms)
if (loopSec == 1000)
if (loopSec == 1000)
{
loopSec = 0; //Reset counter.
dwellLimit_uS = (1000 * configPage2.dwellLimit); //Update uS value incase setting has changed
if ( configPage2.ignCranklock && BIT_CHECK(currentStatus.engine, BIT_ENGINE_CRANK)) { dwellLimit_uS = dwellLimit_uS * 3; } //Make sure the overdwell doesn't clobber the fixed ignition cranking if enabled.
if ( configPage2.ignCranklock && BIT_CHECK(currentStatus.engine, BIT_ENGINE_CRANK)) { dwellLimit_uS = dwellLimit_uS * 3; } //Make sure the overdwell doesn't clobber the fixed ignition cranking if enabled.
//**************************************************************************************************************************************************
//This updates the runSecs variable
//If the engine is running or cranking, we need ot update the run time counter.
if (BIT_CHECK(currentStatus.engine, BIT_ENGINE_RUN))
{ //NOTE - There is a potential for a ~1sec gap between engine crank starting and ths runSec number being incremented. This may delay ASE!
{ //NOTE - There is a potential for a ~1sec gap between engine crank starting and ths runSec number being incremented. This may delay ASE!
if (currentStatus.runSecs <= 254) //Ensure we cap out at 255 and don't overflow. (which would reset ASE)
{ currentStatus.runSecs++; } //Increment our run counter by 1 second.
}
@ -116,14 +121,14 @@ void oneMSInterval() //Most ARM chips can simply call a function
//**************************************************************************************************************************************************
//Check the fan output status
if (configPage4.fanEnable == 1)
{
fanControl(); // Fucntion to turn the cooling fan on/off
{
fanControl(); // Fucntion to turn the cooling fan on/off
}
//Check whether fuel pump priming is complete
if(!fpPrimed)
{
if(currentStatus.secl >= configPage1.fpPrime)
if(currentStatus.secl >= configPage1.fpPrime)
{
fpPrimed = true; //Mark the priming as being completed
if(currentStatus.RPM == 0) { digitalWrite(pinFuelPump, LOW); fuelPumpOn = false; } //If we reach here then the priming is complete, however only turn off the fuel pump if the engine isn't running
@ -140,7 +145,7 @@ void oneMSInterval() //Most ARM chips can simply call a function
}
else if (flexCounter > 151) //1 pulse buffer
{
if(flexCounter < 169)
{
currentStatus.ethanolPct = 100;
@ -161,13 +166,13 @@ void oneMSInterval() //Most ARM chips can simply call a function
//Off by 1 error check
if (currentStatus.ethanolPct == 1) { currentStatus.ethanolPct = 0; }
}
}
#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) //AVR chips use the ISR for this
//Reset Timer2 to trigger in another ~1ms
//Reset Timer2 to trigger in another ~1ms
TCNT2 = 131; //Preload timer2 with 100 cycles, leaving 156 till overflow.
TIFR2 = 0x00; //Timer2 INT Flag Reg: Clear Timer Overflow Flag
#endif
#endif
}

View File

@ -30,11 +30,31 @@ int freeRam ()
// The difference is the free, available ram.
return (uint16_t)stackTop - heapTop;
#elif defined(CORE_STM32)
//Figure this out some_time
return 0;
#endif
}
void setPinMapping(byte boardID)
{
//This is dumb, but it'll do for now to get things compiling
#if defined(CORE_STM32)
#define A0 0
#define A1 1
#define A2 2
#define A3 3
#define A4 4
#define A5 5
#define A6 6
#define A7 7
#define A8 8
#define A9 9
#define A13 13
#define A14 14
#define A15 15
#endif
switch (boardID)
{
case 0: