FreeEMS  0.2.0-SNAPSHOT-285-g028e24c
Macros | Functions
init.c File Reference

Initialise the devices state. More...

#include "inc/freeEMS.h"
#include "inc/interrupts.h"
#include "inc/utils.h"
#include "inc/commsISRs.h"
#include "inc/pagedLocationBuffers.h"
#include "inc/init.h"
#include "inc/decoderInterface.h"
#include "inc/xgateVectors.h"
#include <string.h>
Include dependency graph for init.c:

Go to the source code of this file.

Macros

#define INIT_C

Functions

void init ()
 The main top level init.
void initPLL ()
 Set the PLL clock frequency.
void enablePLL ()
 Switch to using PLL.
void initADC ()
 Set up the analogue inputs.
void initPWM ()
 Set up the PWM module from configuration.
void initGPIO ()
 Set up all the pin states as per configuration, but protect key states.
void initLookupAddresses ()
 Buffer lookup tables addresses.
void initFuelAddresses ()
 Buffer fuel tables addresses.
void initPagedRAMFuel (void)
 Copy fuel tables to RAM.
void initTimingAddresses ()
 Buffer timing tables addresses.
void initPagedRAMTime ()
 Copy timing tables to RAM.
void initTunableAddresses ()
 Buffer tunable tables addresses.
void initPagedRAMTune ()
void initAllPagedAddresses ()
 Buffer addresses of paged data.
void initAllPagedRAM ()
 Copies paged flash to RAM.
void initVariables ()
void initFlash ()
 Flash module setup.
void initECTTimer ()
void initPITTimer ()
void initSCIStuff ()
void initConfiguration ()
void initInterrupts ()

Detailed Description

Initialise the devices state.

Setup, configure and initialise all aspects of the devices state including but not limited to:

Definition in file init.c.

Macro Definition Documentation

#define INIT_C

Definition at line 43 of file init.c.

Function Documentation

void init ( void  )

The main top level init.

The main init function to be called from main.c before entering the main loop. This function is simply a delegator to the finer grained special purpose init functions.

Definition at line 61 of file init.c.

References ATOMIC_END, ATOMIC_START, initADC(), initAllPagedRAM(), initConfiguration(), initECTTimer(), initFlash(), initGPIO(), initInterrupts(), initPLL(), initPWM(), initSCIStuff(), and initVariables().

Referenced by decodePacketAndRespond(), and main().

{
ATOMIC_START(); /* Disable ALL interrupts while we configure the board ready for use */
initPLL(); /* Set up the PLL and use it */
initAllPagedRAM(); /* Copy table and config blocks of data from flash to the paged RAM blocks for fast data lookup */
initVariables(); /* Initialise the rest of the running variables etc */
initFlash(); /* TODO, finalise this */
initECTTimer(); /* TODO move this to inside config in an organised way. Set up the timer module and its various aspects */
// initPITTimer(); /* TODO ditto... */
initSCIStuff(); /* Setup the sci module(s) that we will use. */
initConfiguration(); /* TODO Set user/feature/config up here! */
#ifdef XGATE
initXgate(); /* Fred is a legend, for good reason as of now */
#endif
initInterrupts(); /* still last, reset timers, enable interrupts here TODO move this to inside config in an organised way. Set up the rest of the individual interrupts */
ATOMIC_END(); /* Re-enable any configured interrupts */
}

Here is the call graph for this function:

Here is the caller graph for this function:

void initPLL ( )

Set the PLL clock frequency.

Set the Phase Locked Loop to our desired frequency (80MHz) and enable PLL.

Definition at line 91 of file init.c.

References CLKSEL, enablePLL(), PLLCTL, PLLDIVISOR, PLLMULTIPLIER, PLLOFF, PLLON, PLLSELOFF, REFDV, and SYNR.

Referenced by init().

{
CLKSEL &= PLLSELOFF; /* Switches to base external OSCCLK to ensure PLL is not being used (off out of reset, but not sure if the monitor turns it on before passing control or not) */
PLLCTL &= PLLOFF; /* Turn the PLL device off to adjust its speed (on by default out of reset) */
REFDV = PLLDIVISOR; /* 16MHz / (3 + 1) = 4MHz Bus frequency */
SYNR = PLLMULTIPLIER; /* 4MHz * (9 + 1) = 40MHz Bus frequency */
PLLCTL |= PLLON; /* Turn the PLL device back on again at 80MHz */
}

Here is the call graph for this function:

Here is the caller graph for this function:

void enablePLL ( void  )

Switch to using PLL.

Switch to using PLL for clock (40MHz bus speed). Interrupt is enabled elsewhere.

Note: Requires busy wait loop, only for init and emergency use.

Todo:
Should be limited, and have break out with error code and fall back mechanism.

Definition at line 108 of file init.c.

References CLKSEL, CRGFLG, PLLLOCK, and PLLSEL.

Referenced by initPLL(), and SelfClockISR().

{
while (!(CRGFLG & PLLLOCK)){
/* Do nothing while we wait till the PLL loop locks onto the target frequency. */
/* Target frequency is given by (2 * (crystal frequency / (REFDV + 1)) * (SYNR + 1)) */
/* Bus frequency is half PLL frequency and given by ((crystal frequency / (REFDV + 1)) * (SYNR + 1)) */
}
CLKSEL = PLLSEL; /* Switches to PLL clock for internal bus frequency */
/* from MC9S12XDP512V2.pdf Section 2.4.1.1.2 page 101 Third paragraph */
/* "This takes a MAXIMUM of 4 OSCCLK clock cylces PLUS 4 PLL clock cycles" */
/* "During this time ALL clocks freeze, and CPU activity ceases" */
/* Therefore there is no point waiting for this to occur, we already are... */
}

Here is the caller graph for this function:

void initADC ( )

Set up the analogue inputs.

Definition at line 124 of file init.c.

References ATD0CTL2, ATD0CTL3, ATD0CTL4, ATD0CTL5, ATD1CTL0, ATD1CTL2, ATD1CTL3, ATD1CTL4, and ATD1CTL5.

Referenced by init().

{
// Currently not true, and may never be: TODO When the port something uses
// is changed via the tuning interface, the configuration will be done on
// the fly, and the value burned to flash such that next boot happens
// correctly and current running devices are used in that way.
/* Digital input buffers on the ATD channels are off by default, leave them this way! */
//ATD0DIEN = ZEROS; /* You are out of your mind if you waste this on digital Inputs */
//ATD1DIEN0 = ZEROS; /* You are out of your mind if you waste this on digital Inputs (NOT-bonded, can't use) */
//ATD1DIEN1 = ZEROS; /* You are out of your mind if you waste this on digital Inputs */
/* And configure them all for analog input */
//ATD0CTL0 = 0x07/* With mult turned on this is required to be set to cause wrap around, but is correct out of reset */
//ATD0CTL1 = 0x07/* Trigger and interrupt configuration, unused for now. */
ATD0CTL2 = 0xC0; /* Turns on the ADC block and sets auto flag clear */
ATD0CTL3 = 0x40; /* Set sequence length = 8 */
ATD0CTL4 = 0x73; /* Set the ADC clock and sample period for best accuracy */
ATD0CTL5 = 0xB0; /* Sets justification to right, multiplex and scan all channels. Writing to this causes conversions to begin */
/* And configure them all for analog input */
ATD1CTL0 = 0x07; /* TODO bring this out of config based on chip variant variable. Sets wrap on 8th ADC because we can't use the other 8 on 112 pin version */
//ATD0CTL1 = 0x07/* Trigger and interrupt configuration, unused for now. */
ATD1CTL2 = 0xC0; /* Turns on the ADC block and sets auto flag clear */
ATD1CTL3 = 0x40; /* Set sequence length = 8 */
ATD1CTL4 = 0x73; /* Set the ADC clock and sample period for best accuracy */
ATD1CTL5 = 0xB0; /* Sets justification to right, multiplex and scan all channels. Writing to this causes conversions to begin */
}

Here is the caller graph for this function:

void initPWM ( )

Set up the PWM module from configuration.

Definition at line 154 of file init.c.

References fixedConfigs2, fixedConfig2::inputOutputSettings, PWMCAE, inputOutputSetting::PWMCenterAlign, PWMCLK, inputOutputSetting::PWMClock, inputOutputSetting::PWMClockPrescaler, inputOutputSetting::PWMControl, PWMCTL, PWMDTY0, PWMDTY1, PWMDTY2, PWMDTY3, PWMDTY4, PWMDTY5, PWMDTY6, PWMDTY7, PWME, inputOutputSetting::PWMEnable, inputOutputSetting::PWMInitialDuty0, inputOutputSetting::PWMInitialDuty1, inputOutputSetting::PWMInitialDuty2, inputOutputSetting::PWMInitialDuty3, inputOutputSetting::PWMInitialDuty4, inputOutputSetting::PWMInitialDuty5, inputOutputSetting::PWMInitialDuty6, inputOutputSetting::PWMInitialDuty7, PWMPER0, PWMPER1, PWMPER2, PWMPER3, PWMPER4, PWMPER5, PWMPER6, PWMPER7, inputOutputSetting::PWMPeriod0, inputOutputSetting::PWMPeriod1, inputOutputSetting::PWMPeriod2, inputOutputSetting::PWMPeriod3, inputOutputSetting::PWMPeriod4, inputOutputSetting::PWMPeriod5, inputOutputSetting::PWMPeriod6, inputOutputSetting::PWMPeriod7, PWMPOL, inputOutputSetting::PWMPolarity, PWMPRCLK, inputOutputSetting::PWMScalerA, inputOutputSetting::PWMScalerB, PWMSCLA, and PWMSCLB.

Referenced by init().

{
/* TODO PWM channel concatenation for high resolution */
// join channel pairs together here (needs 16 bit regs enabled too)
/* TODO Initialise pwm channels with frequency, and initial duty for real use */
// initial PWM settings for testing
PWMCTL = fixedConfigs2.inputOutputSettings.PWMControl & 0xF0; // Disallow access to power saving and reserved bits
PWME = fixedConfigs2.inputOutputSettings.PWMEnable; // MUST be done after concatenation with PWMCTL
}

Here is the caller graph for this function:

void initGPIO ( )

Set up all the pin states as per configuration, but protect key states.

Definition at line 190 of file init.c.

References BIT6, BIT7, DDRA, DDRB, DDRC, DDRD, DDRE, DDRH, DDRJ, DDRK, DDRM, DDRP, DDRS, DDRT, fixedConfigs2, fixedConfig2::inputOutputSettings, NBIT5, NBIT6, PORTA, PORTB, PORTC, PORTD, inputOutputSetting::PortDirectionA, inputOutputSetting::PortDirectionB, inputOutputSetting::PortDirectionC, inputOutputSetting::PortDirectionD, inputOutputSetting::PortDirectionE, inputOutputSetting::PortDirectionH, inputOutputSetting::PortDirectionJ, inputOutputSetting::PortDirectionK, inputOutputSetting::PortDirectionM, inputOutputSetting::PortDirectionP, inputOutputSetting::PortDirectionS, PORTE, PORTH, inputOutputSetting::PortInitialValueA, inputOutputSetting::PortInitialValueB, inputOutputSetting::PortInitialValueC, inputOutputSetting::PortInitialValueD, inputOutputSetting::PortInitialValueE, inputOutputSetting::PortInitialValueH, inputOutputSetting::PortInitialValueJ, inputOutputSetting::PortInitialValueK, inputOutputSetting::PortInitialValueM, inputOutputSetting::PortInitialValueP, inputOutputSetting::PortInitialValueS, PORTJ, PORTK, PORTM, PORTP, PORTS, and PORTT.

Referenced by init().

{
// Set the initial pin state of pins configured as output
PORTA = fixedConfigs2.inputOutputSettings.PortInitialValueA | BIT6 | BIT7; // Mask the fuel pump relay and CEL pins on
PORTE = (fixedConfigs2.inputOutputSettings.PortInitialValueE | BIT7) & (NBIT5 & NBIT6); // 7 should be high, and 5 and 6 low, to reduce current draw. The rest don't matter. 0 and 1 are not outputs.
PORTS = fixedConfigs2.inputOutputSettings.PortInitialValueS | 0x02; // Mask the SCI0 TX pin to high between transmissions!
PORTT = 0x00; // Set all ECT pins to off state, only matters for 2-7, and only if being used. TODO mask this dynamically based on decoder type and configured channels.
/* AD0PT1 You are out of your mind if you waste this on digital Inputs */
/* AD1PT1 You are out of your mind if you waste this on digital Inputs */
// Initialise the Data Direction Registers
DDRA = fixedConfigs2.inputOutputSettings.PortDirectionA | BIT6 | BIT7; // Mask the fuel pump relay and CEL pins as outputs
DDRE = fixedConfigs2.inputOutputSettings.PortDirectionE; // No need to mask off bits 0 and 1, they have no effect and are always inputs.
DDRS = fixedConfigs2.inputOutputSettings.PortDirectionS & 0xFE; // Mask the SCI0 RX pin as input between receiving
DDRT = 0xFC; // Set ECT pins 0,1 to IC and 2:7 to OC (8) TODO mask this dynamically based on decoder type and configured channels.
/* AD0DDR1 You are out of your mind if you waste this on digital Inputs */
/* AD1DDR1 You are out of your mind if you waste this on digital Inputs */
}

Here is the caller graph for this function:

void initLookupAddresses ( )

Buffer lookup tables addresses.

Save pointers to the lookup tables which live in paged flash.

Definition at line 229 of file init.c.

References CHTTransferTable, CHTTransferTableLocation, IATTransferTable, IATTransferTableLocation, MAFTransferTable, MAFTransferTableLocation, TestTransferTable, and TestTransferTableLocation.

Referenced by initAllPagedAddresses().

Here is the caller graph for this function:

void initFuelAddresses ( )
void initPagedRAMFuel ( void  )

Copy fuel tables to RAM.

Initialises the fuel tables in RAM by copying them up from flash.

Definition at line 258 of file init.c.

References AirflowTableFlash2Location, AirflowTableFlashLocation, LambdaTableFlash2Location, LambdaTableFlashLocation, RPAGE, RPAGE_FUEL_ONE, RPAGE_FUEL_TWO, VETableMainFlash2Location, VETableMainFlashLocation, VETableSecondaryFlash2Location, and VETableSecondaryFlashLocation.

Referenced by initAllPagedRAM().

{
/* Copy the tables from flash to RAM */
memcpy((void*)&TablesA, VETableMainFlashLocation, sizeof(mainTable));
memcpy((void*)&TablesB, VETableSecondaryFlashLocation, sizeof(mainTable));
memcpy((void*)&TablesC, AirflowTableFlashLocation, sizeof(mainTable));
memcpy((void*)&TablesD, LambdaTableFlashLocation, sizeof(mainTable));
memcpy((void*)&TablesA, VETableMainFlash2Location, sizeof(mainTable));
memcpy((void*)&TablesB, VETableSecondaryFlash2Location, sizeof(mainTable));
memcpy((void*)&TablesC, AirflowTableFlash2Location, sizeof(mainTable));
memcpy((void*)&TablesD, LambdaTableFlash2Location, sizeof(mainTable));
}

Here is the caller graph for this function:

void initTimingAddresses ( )

Buffer timing tables addresses.

Save pointers to the timing tables which live in paged flash.

Definition at line 277 of file init.c.

References IgnitionAdvanceTableMainFlash, IgnitionAdvanceTableMainFlash2, IgnitionAdvanceTableMainFlash2Location, IgnitionAdvanceTableMainFlashLocation, IgnitionAdvanceTableSecondaryFlash, IgnitionAdvanceTableSecondaryFlash2, IgnitionAdvanceTableSecondaryFlash2Location, IgnitionAdvanceTableSecondaryFlashLocation, InjectionAdvanceTableMainFlash, InjectionAdvanceTableMainFlash2, InjectionAdvanceTableMainFlash2Location, InjectionAdvanceTableMainFlashLocation, InjectionAdvanceTableSecondaryFlash, InjectionAdvanceTableSecondaryFlash2, InjectionAdvanceTableSecondaryFlash2Location, and InjectionAdvanceTableSecondaryFlashLocation.

Referenced by initAllPagedAddresses().

Here is the caller graph for this function:

void initPagedRAMTime ( )

Copy timing tables to RAM.

Initialises the timing tables in RAM by copying them up from flash.

Definition at line 294 of file init.c.

References IgnitionAdvanceTableMainFlash2Location, IgnitionAdvanceTableMainFlashLocation, IgnitionAdvanceTableSecondaryFlash2Location, IgnitionAdvanceTableSecondaryFlashLocation, InjectionAdvanceTableMainFlash2Location, InjectionAdvanceTableMainFlashLocation, InjectionAdvanceTableSecondaryFlash2Location, InjectionAdvanceTableSecondaryFlashLocation, RPAGE, RPAGE_TIME_ONE, and RPAGE_TIME_TWO.

Referenced by initAllPagedRAM().

{
/* Copy the tables from flash to RAM */
memcpy((void*)&TablesA, IgnitionAdvanceTableMainFlashLocation, sizeof(mainTable));
memcpy((void*)&TablesB, IgnitionAdvanceTableSecondaryFlashLocation, sizeof(mainTable));
memcpy((void*)&TablesC, InjectionAdvanceTableMainFlashLocation, sizeof(mainTable));
memcpy((void*)&TablesD, InjectionAdvanceTableSecondaryFlashLocation, sizeof(mainTable));
memcpy((void*)&TablesA, IgnitionAdvanceTableMainFlash2Location, sizeof(mainTable));
memcpy((void*)&TablesB, IgnitionAdvanceTableSecondaryFlash2Location, sizeof(mainTable));
memcpy((void*)&TablesC, InjectionAdvanceTableMainFlash2Location, sizeof(mainTable));
memcpy((void*)&TablesD, InjectionAdvanceTableSecondaryFlash2Location, sizeof(mainTable));
}

Here is the caller graph for this function:

void initTunableAddresses ( )

Buffer tunable tables addresses.

Save pointers to the tunable tables which live in paged flash and their sub-sections too.

Definition at line 314 of file init.c.

References SmallTables1::blendVersusRPMTable, blendVersusRPMTable2Location, blendVersusRPMTableLocation, SmallTables1::dwellDesiredVersusVoltageTable, dwellDesiredVersusVoltageTable2Location, dwellDesiredVersusVoltageTableLocation, SmallTables1::dwellVersusRPMTable, dwellVersusRPMTable2Location, dwellVersusRPMTableLocation, SmallTables1::engineTempEnrichmentTableFixed, engineTempEnrichmentTableFixed2Location, engineTempEnrichmentTableFixedLocation, SmallTables1::engineTempEnrichmentTablePercent, engineTempEnrichmentTablePercent2Location, engineTempEnrichmentTablePercentLocation, SmallTables1::filler, SmallTables2::filler, SmallTables3::filler, SmallTables4::filler, fillerA2Location, fillerALocation, fillerB2Location, fillerBLocation, fillerC2Location, fillerCLocation, fillerD2Location, fillerDLocation, SmallTables1::injectorDeadTimeTable, injectorDeadTimeTable2Location, injectorDeadTimeTableLocation, SmallTables2::loggingSettings, loggingSettings2Location, loggingSettingsLocation, SmallTables2::perCylinderFuelTrims, perCylinderFuelTrims2Location, perCylinderFuelTrimsLocation, SmallTables1::postStartEnrichmentTable, postStartEnrichmentTable2Location, postStartEnrichmentTableLocation, SmallTables1::primingVolumeTable, primingVolumeTable2Location, primingVolumeTableLocation, SmallTablesAFlash, SmallTablesAFlash2, SmallTablesAFlash2Location, SmallTablesAFlashLocation, SmallTablesBFlash, SmallTablesBFlash2, SmallTablesBFlash2Location, SmallTablesBFlashLocation, SmallTablesCFlash, SmallTablesCFlash2, SmallTablesCFlash2Location, SmallTablesCFlashLocation, SmallTablesDFlash, SmallTablesDFlash2, SmallTablesDFlash2Location, and SmallTablesDFlashLocation.

Referenced by initAllPagedAddresses().

{
/* Setup addresses within the page to avoid warnings */
/* TablesA */
/* TablesB */
/* TablesC */
// TODO
/* TablesD */
// TODO
/* filler defs */
}

Here is the caller graph for this function:

void initPagedRAMTune ( )

Definition at line 370 of file init.c.

References RPAGE, RPAGE_TUNE_ONE, RPAGE_TUNE_TWO, SmallTablesAFlashLocation, SmallTablesBFlashLocation, SmallTablesCFlashLocation, and SmallTablesDFlashLocation.

Referenced by initAllPagedRAM().

{
/* Copy the tables from flash to RAM */
memcpy((void*)&TablesA, SmallTablesAFlashLocation, sizeof(mainTable));
memcpy((void*)&TablesB, SmallTablesBFlashLocation, sizeof(mainTable));
memcpy((void*)&TablesC, SmallTablesCFlashLocation, sizeof(mainTable));
memcpy((void*)&TablesD, SmallTablesDFlashLocation, sizeof(mainTable));
// &&&&&&&&&&&&&&&&&&&&&&&&&&&&&& WARNING &&&&&&&&&&&&&&&&&&&&&&&&&&&&&& //
// You will get garbage if you use table switching at this time!!! //
// XGATE code being run from this region temporarily!!! //
// Writing to these tables WILL corrupt XGATE code/kill your engine! //
// &&&&&&&&&&&&&&&&&&&&&&&&&&&&&& WARNING &&&&&&&&&&&&&&&&&&&&&&&&&&&&&& //
//memcpy(xgateSchedRAMAddress, xgateSchedFlashAddress, (xgateSchedEnd - xgateSched));
//memcpy(xgateInjectorsOnRAMAddress, xgateInjectorsOnFlashAddress, (xgateInjectorsOnEnd - xgateInjectorsOn));
//memcpy(xgateInjectorsOffRAMAddress, xgateInjectorsOffFlashAddress, (xgateInjectorsOffEnd - xgateInjectorsOff));
// memcpy((void*)&TablesA, SmallTablesAFlash2Location, sizeof(mainTable));
// memcpy((void*)&TablesB, SmallTablesBFlash2Location, sizeof(mainTable));
// memcpy((void*)&TablesC, SmallTablesCFlash2Location, sizeof(mainTable));
// memcpy((void*)&TablesD, SmallTablesDFlash2Location, sizeof(mainTable));
}

Here is the caller graph for this function:

void initAllPagedAddresses ( )

Buffer addresses of paged data.

Save the paged memory addresses to variables such that we can access them from another paged block with no warnings.

If you try to access paged data from the wrong place you get nasty warnings. These calls to functions that live in the same page that they are addressing prevent those warnings.

Note
Many thanks to Jean BĂ©langer for the inspiration/idea to do this!

Definition at line 404 of file init.c.

References initFuelAddresses(), initLookupAddresses(), initTimingAddresses(), and initTunableAddresses().

Referenced by initAllPagedRAM().

{
/* Setup pointers to lookup tables */
/* Setup pointers to the main tables */
}

Here is the call graph for this function:

Here is the caller graph for this function:

void initAllPagedRAM ( )

Copies paged flash to RAM.

Take the tables and config from flash up to RAM to allow live tuning.

For the main tables and other paged config we need to adjust the RPAGE value to the appropriate one before copying up.

This function is simply a delegator to the ones for each flash page. Each one lives in the same paged space as the data it is copying up.

Definition at line 424 of file init.c.

References initAllPagedAddresses(), initPagedRAMFuel(), initPagedRAMTime(), initPagedRAMTune(), setupPagedRAM(), and TRUE.

Referenced by init().

{
/* Setup the flash block pointers before copying flash to RAM using them */
/* Copy the tables up to their paged RAM blocks through the window from flash */
/* Default to page one for now, perhaps read the configured port straight out of reset in future? TODO */
setupPagedRAM(TRUE); // probably something like (PORTA & TableSwitchingMask)
}

Here is the call graph for this function:

Here is the caller graph for this function:

void initVariables ( )

Definition at line 440 of file init.c.

References ADCBuffers, ADCBuffers0, ADCBuffers1, ADCBuffersRecord, coreStatusA, CoreVars, CoreVars0, DerivedVars, DerivedVars0, descheduleAll(), ectMainControlRegisters, ectMainTimeRegisters, FUEL_PUMP_PRIME, TC2_ADDR, TC3_ADDR, TC4_ADDR, TC5_ADDR, TC6_ADDR, TC7_ADDR, TCTL1_ADDR, TCTL2_ADDR, ticksPerDegree, ticksPerDegree0, ticksPerDegree1, and ticksPerDegreeRecord.

Referenced by init().

{
/* And the opposite for the other halves */
ticksPerDegree = &ticksPerDegree0; // TODO temp, remove, maybe
ticksPerDegreeRecord = &ticksPerDegree1; // TODO temp, remove, maybe
/* Setup the pointers to the registers for fueling use, this does NOT work if done in global.c, I still don't know why. */
// Preset all schedules to be disabled. Can be configured by scheduler if required.
// TODO perhaps read from the ds1302 once at start up and init the values or different ones with the actual time and date then update them in RTI
}

Here is the call graph for this function:

Here is the caller graph for this function:

void initFlash ( )

Flash module setup.

Initialise configuration registers for the flash module to allow burning of non-volatile flash memory from within the firmware.

The FCLKDIV register can be written once only after reset, thus the lower seven bits and the PRDIV8 bit must be set at the same time.

We want to put the flash clock as high as possible between 150kHz and 200kHz

The oscillator clock is 16MHz and because that is above 12.8MHz we will set the PRDIV8 bit to further divide by 8 bits as per the manual.

16MHz = 16000KHz which pre-divided by 8 is 2000kHz

2000kHz / 200kHz = 10 thus we want to set the divide register to 10 or 0x0A

Combining 0x0A with PRDIV8 gives us 0x4A (0x0A | 0x40 = 0x4A) so we use that

Author
Sean Keys
Note
If you use a different crystal lower than 12.8MHz PRDIV8 should not be set.
Warning
If the frequency you end up with is outside 150kHz - 200kHz you may damage your flash module or get corrupt data written to it.

Definition at line 499 of file init.c.

References ACCERR, FCLKDIV, FPROT, FSTAT, and PVIOL.

Referenced by init().

{
FCLKDIV = 0x4A; /* Set the flash clock frequency */
FPROT = 0xFF; /* Disable all flash protection */
FSTAT = FSTAT | (PVIOL | ACCERR); /* Clear any errors */
}

Here is the caller graph for this function:

void initECTTimer ( )
Todo:
TODO Take the configuration from the decoder (as is) and mask it such that it does not affect the 6 other channels. Take the the number of output channels required from configuration and configure that many as outputs Configure the balance in whatever way is specified in the GPIO configuration - allow second input to be reused as GPI only.

This stuff affects:

  • TIE = 0x01 or 0x03, only. OC channels enabled as required and IC only for RPM/position.
  • TIOS = nope, always 0xFC for 2 IC and 6 OC
  • TCTL (1,2,3,4) 4 = 0x0? mask off high 4 bits and allow low 4 to come from decoder config/init
  • PORTT = zeros, with balance from config
  • DDRT = 0,1 inputs, or if unused by decoder, from config

Definition at line 507 of file init.c.

References decoderInitPreliminary(), ONES, PTPSR, TCTL1, TCTL2, TCTL3, TCTL4, TFLG, TFLGOF, TIE, TIOS, TSCR1, TSCR2, and ZEROS.

Referenced by init().

{
/** @todo TODO Take the configuration from the decoder (as is) and mask it such that it does not affect the 6 other channels.
* Take the the number of output channels required from configuration and configure that many as outputs
* Configure the balance in whatever way is specified in the GPIO configuration - allow second input to be reused as GPI only.
*
* This stuff affects:
* - TIE = 0x01 or 0x03, only. OC channels enabled as required and IC only for RPM/position.
* - TIOS = nope, always 0xFC for 2 IC and 6 OC
* - TCTL (1,2,3,4) 4 = 0x0? mask off high 4 bits and allow low 4 to come from decoder config/init
* - PORTT = zeros, with balance from config
* - DDRT = 0,1 inputs, or if unused by decoder, from config
*/
// TODO rearrange the order of this stuff and pull enable and interrupt enable out to the last function call of init.
/* Timer channel interrupts */
TIE = 0x03; /* 0,1 IC interrupts enabled for reading engine position and RPM, 6 OC channels disabled such that no injector switching happens till scheduled */
TFLG = ONES; /* Clear all the flags such that we are up and running before they first occur */
TFLGOF = ONES; /* Clear all the flags such that we are up and running before they first occur */
/* TODO Turn the timer on and set the rate and overflow interrupt */
// DLYCT = 0xFF; /* max noise filtering as experiment for volvo this will come from flash config */ // just hiding a wiring/circuit issue...
TSCR1 = 0x88; /* 0b_1000_1000 Timer enabled, and precision timer turned on */
TSCR2 = 0x87; /* 0b_1000_0111 Overflow interrupt enable, divide by 256 if precision turned off */
// PTPSR = 0x03; /* 4 prescaler gives .1uS resolution and max period of 7ms measured */
PTPSR = 0x1F; /* 32 prescaler gives 0.8uS resolution and max period of 52.4288ms measured */
// PTPSR = 0x3F; /* 64 prescaler gives 1.6uS resolution and max period of 105ms measured */
// PTPSR = 0xFF; /* 256 prescaler gives 6.4uS resolution and max period of 400ms measured */
// PTPSR = 0x7F; /* 128 prescaler gives 3.2uS resolution and max period of 200ms measured */
/* http://duckduckgo.com/?q=1+%2F+%2840MHz+%2F+32+%29 */
/* http://duckduckgo.com/?q=%281+%2F+%2840MHz+%2F+32+%29%29+*+2^16 */
/* www.mecheng.adelaide.edu.au/robotics_novell/WWW_Devs/Dragon12/LM4_Timer.pdf */
/* Initial actions */
TIOS = 0xFC; /* 0b_1111_1100 0 and 1 are input capture, 2 through 7 are output compare */
TCTL1 = ZEROS; /* Set disabled at startup time, use these and other flags to switch fueling on and off inside the decoder */
TCTL2 = ZEROS; /* 0,1 have compare turned off regardless as they are in IC mode. */
TCTL3 = ZEROS; /* Capture off for 4 - 7 */
TCTL4 = 0x0F; /* Capture on both edges of two pins for IC (0,1), capture off for 2,3 */
// TODO setup delay counters on 0 and 1 to filter noise (nice feature!)
//DLYCT = ??; built in noise filter
// PTMCPSR = 0xFF // Precision prescaler - fastest is 1 represented by 0, slowest/longest possible is 256 represented by 255 or 0xFF
// MCCNT = ONES16; // init to slowest possible, first
// MCCTL = 0xC4; // turn on and setup the mod down counter
// MCFLG = 0x80; // clear the flag up front
}

Here is the call graph for this function:

Here is the caller graph for this function:

void initPITTimer ( )

Definition at line 563 of file init.c.

{
// // set micro periods
// PITMTLD0 = 0x1F; /* 32 prescaler gives 0.8uS resolution and max period of 52.4288ms measured */
// PITMTLD1 = 0x1F; /* ditto */
// /* http://duckduckgo.com/?q=1+%2F+%2840MHz+%2F+32+%29 Exactly the same as for ECT */
//
// // set timers running
// PITLD0 = dwellPeriod;
// // enable module
// PITCFLMT = 0x80;
// // enable channels
// //PITCE = 0x03;
// // enable interrupt
// PITINTE = 0x01;
// // clear flags
// //PITFLT = ONES;
}
void initSCIStuff ( )

Definition at line 582 of file init.c.

References serialSetting::baudDivisor, fixedConfigs1, SCI0BD, SCI0CR1, SCI0CR2, and fixedConfig1::serialSettings.

Referenced by init().

{
/* The alternative register set selector defaults to zero */
// set the baud/data speed
// etc
/* Switch to alternative register set? */
// etc
/* Switch back again? */
/*
* 0 = LOOPS (normal two wire operation)
* 0 = SCISWAI (Wait mode on)
* 0 = RSRC (if loops=1, int/ext wiring)
* 1 = M MODE (9 bit operation)
* 0 = WAKE (idle line wakeup)
* 0 = ILT (idle line type count start pos)
* 1 = PE (parity on)
* 1 = PT (odd parity)
*
* 0x13 = ODD (default)
* 0x12 = EVEN
* 0x00 = NONE
*/
SCI0CR1 = 0x13;
/*
* 0 = TIE (tx data empty isr disabled)
* 0 = TCIE (tx complete isr disabled)
* 1 = RIE (rx full isr enabled)
* 0 = ILIE (idle line isr disabled)
* 0 = TE (transmit disabled)
* 1 = RE (receive enabled)
* 0 = RWU (rx wake up normal)
* 0 = SBK (send break off)
*/
SCI0CR2 = 0x24;
}

Here is the caller graph for this function:

void initConfiguration ( )

Definition at line 626 of file init.c.

References bootFuelConst, fixedConfig1::engineSettings, fixedConfigs1, fixedConfigs2, engineSetting::injectorFlow, masterFuelConstant, engineSetting::perCylinderVolume, fixedConfig2::sensorRanges, engineSetting::stoichiometricAFR, TPSADCRange, sensorRange::TPSMaximumADC, and sensorRange::TPSMinimumADC.

Referenced by init().

{
// // TODO Calc TPS ADC range on startup or every time? this depends on whether we ensure that things work without a re init or reset or not.
/* Add in tunable physical parameters at boot time TODO move to init.c TODO duplicate for secondary fuel? or split somehow?
*nstant = ((masterConst * perCylinderVolume) / (stoichiometricAFR * injectorFlow));
*nstant = ((139371764 * 16384) / (15053 * 4096));
* OR
*nstant = ((masterConst / injectorFlow) * perCylinderVolume) / stoichiometricAFR;
*nstant = ((139371764 / 4096) * 16384) / 15053;
* http://duckduckgo.com/?q=%28%28139371764++%2F+4096%29+*+16384%29+%2F+15053 */
/* The ADC range used to generate TPS percentage */
}else{
}
}

Here is the caller graph for this function:

void initInterrupts ( )

Definition at line 649 of file init.c.

References AVIE, CRGFLG, CRGINT, IVBR, ONES, PIEH, PIFH, PLLLOCKIE, PLLLOCKIF, PPSH, RAMWPC, RTICTL, RTIE, RTIF, SCMIE, SCMIF, VREGCTRL, and ZEROS.

Referenced by init().

{
/* IMPORTANT : Set the s12x vector base register (Thanks Karsten!!) */
IVBR = 0xF7; /* Without this the interrupts will never find your code! */
/* Set up the Real Time Interrupt */
RTICTL = 0x81; /* 0b_1000_0001 0.125ms/125us period http://duckduckgo.com/?q=1+%2F+%2816MHz+%2F+%282+*+10^3%29+%29 */
// RTICTL = 0xF9; /* 0b_1111_1001 0.125s/125ms period http://duckduckgo.com/?q=1+%2F+%2816MHz+%2F+%282*10^6%29+%29 */
CRGINT |= (RTIE | PLLLOCKIE | SCMIE); /* Enable the Real Time Interrupt, PLL Lock Interrupt, and Self Clock Mode Interrupt */
CRGFLG = (RTIF | PLLLOCKIF | SCMIF); /* Clear the RTI, LOCKI, and SCMI flags */
RAMWPC |= AVIE; // Enable the access protection interrupt for XGATE RAM
// set up port H for testing
PPSH = ZEROS; // falling edge/pull up for all
PIEH = ONES; // enable all pins interrupts
PIFH = ONES; // clear all port H interrupt flags
// TODO set up irq and xirq for testing
// IRQCR for IRQ
/* VReg API setup (only for wait mode? i think so) */
// VREGAPIR = 0x09C3; /* For 500ms period : (500ms - 0.2ms) / 0.2ms = 0b100111000011 = 2499 */
// VREGAPICL = 0x02; /* Enable the interrupt */
// VREGAPICL = 0x04; /* Start the counter running */
/* Writing a one to the flag will set it if it is unset, so best not to mess with it here as it probably starts off unset */
/* LVI Low Voltage Interrupt enable */
VREGCTRL = 0x02; // Counts bad power events for diagnosis reasons
}

Here is the caller graph for this function: