PageRenderTime 92ms CodeModel.GetById 29ms RepoModel.GetById 1ms app.codeStats 0ms

/src/init.c

https://github.com/alfredopalhares/freeems-vanilla
C | 682 lines | 296 code | 92 blank | 294 comment | 1 complexity | 4f36d1daf89087074641624b66e08fd3 MD5 | raw file
  1. /* FreeEMS - the open source engine management system
  2. *
  3. * Copyright 2008-2012 Fred Cooke
  4. *
  5. * This file is part of the FreeEMS project.
  6. *
  7. * FreeEMS software is free software: you can redistribute it and/or modify
  8. * it under the terms of the GNU General Public License as published by
  9. * the Free Software Foundation, either version 3 of the License, or
  10. * (at your option) any later version.
  11. *
  12. * FreeEMS software is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. * GNU General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU General Public License
  18. * along with any FreeEMS software. If not, see http://www.gnu.org/licenses/
  19. *
  20. * We ask that if you make any changes to this file you email them upstream to
  21. * us at admin(at)diyefi(dot)org or, even better, fork the code on github.com!
  22. *
  23. * Thank you for choosing FreeEMS to run your engine!
  24. */
  25. /** @file
  26. *
  27. * @brief Initialise the devices state
  28. *
  29. * Setup, configure and initialise all aspects of the devices state including
  30. * but not limited to:
  31. *
  32. * - Setup the bus clock speed
  33. * - Configuration based variable initialisation
  34. * - I/O register behaviour and initial state
  35. * - Configure and enable interrupts
  36. * - Copy tunable data up to RAM from flash
  37. * - Configure peripheral module behaviour
  38. */
  39. #define INIT_C
  40. #include "inc/freeEMS.h"
  41. #include "inc/interrupts.h"
  42. #include "inc/utils.h"
  43. #include "inc/commsISRs.h"
  44. #include "inc/pagedLocationBuffers.h"
  45. #include "inc/init.h"
  46. #include "inc/decoderInterface.h"
  47. #include "inc/xgateVectors.h"
  48. #include <string.h>
  49. /** @brief The main top level init
  50. *
  51. * The main init function to be called from main.c before entering the main
  52. * loop. This function is simply a delegator to the finer grained special
  53. * purpose init functions.
  54. */
  55. void init(){
  56. ATOMIC_START(); /* Disable ALL interrupts while we configure the board ready for use */
  57. initPLL(); /* Set up the PLL and use it */
  58. initGPIO();
  59. initPWM();
  60. initADC();
  61. initAllPagedRAM(); /* Copy table and config blocks of data from flash to the paged RAM blocks for fast data lookup */
  62. initVariables(); /* Initialise the rest of the running variables etc */
  63. initFlash(); /* TODO, finalise this */
  64. initECTTimer(); /* TODO move this to inside config in an organised way. Set up the timer module and its various aspects */
  65. // initPITTimer(); /* TODO ditto... */
  66. initSCIStuff(); /* Setup the sci module(s) that we will use. */
  67. initConfiguration(); /* TODO Set user/feature/config up here! */
  68. #ifdef XGATE
  69. initXgate(); /* Fred is a legend, for good reason as of now */
  70. #endif
  71. 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 */
  72. ATOMIC_END(); /* Re-enable any configured interrupts */
  73. }
  74. #ifdef XGATE
  75. #include "xgateInit.c"
  76. #endif
  77. /** @brief Set the PLL clock frequency
  78. *
  79. * Set the Phase Locked Loop to our desired frequency (80MHz) and switch to
  80. * using it for clock (40MHz bus speed).
  81. */
  82. void initPLL(){
  83. 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) */
  84. PLLCTL &= PLLOFF; /* Turn the PLL device off to adjust its speed (on by default out of reset) */
  85. REFDV = PLLDIVISOR; /* 16MHz / (3 + 1) = 4MHz Bus frequency */
  86. SYNR = PLLMULTIPLIER; /* 4MHz * (9 + 1) = 40MHz Bus frequency */
  87. PLLCTL |= PLLON; /* Turn the PLL device back on again at 80MHz */
  88. while (!(CRGFLG & PLLLOCK)){
  89. /* Do nothing while we wait till the PLL loop locks onto the target frequency. */
  90. /* Target frequency is given by (2 * (crystal frequency / (REFDV + 1)) * (SYNR + 1)) */
  91. /* Bus frequency is half PLL frequency and given by ((crystal frequency / (REFDV + 1)) * (SYNR + 1)) */
  92. }
  93. CLKSEL = PLLSELON; /* Switches to PLL clock for internal bus frequency */
  94. /* from MC9S12XDP512V2.pdf Section 2.4.1.1.2 page 101 Third paragraph */
  95. /* "This takes a MAXIMUM of 4 OSCCLK clock cylces PLUS 4 PLL clock cycles" */
  96. /* "During this time ALL clocks freeze, and CPU activity ceases" */
  97. /* Therefore there is no point waiting for this to occur, we already are... */
  98. }
  99. /// Set up the analogue inputs
  100. void initADC(){
  101. // Currently not true, and may never be: TODO When the port something uses
  102. // is changed via the tuning interface, the configuration will be done on
  103. // the fly, and the value burned to flash such that next boot happens
  104. // correctly and current running devices are used in that way.
  105. /* Digital input buffers on the ATD channels are off by default, leave them this way! */
  106. //ATD0DIEN = ZEROS; /* You are out of your mind if you waste this on digital Inputs */
  107. //ATD1DIEN0 = ZEROS; /* You are out of your mind if you waste this on digital Inputs (NOT-bonded, can't use) */
  108. //ATD1DIEN1 = ZEROS; /* You are out of your mind if you waste this on digital Inputs */
  109. /* And configure them all for analog input */
  110. //ATD0CTL0 = 0x07/* With mult turned on this is required to be set to cause wrap around, but is correct out of reset */
  111. //ATD0CTL1 = 0x07/* Trigger and interrupt configuration, unused for now. */
  112. ATD0CTL2 = 0xC0; /* Turns on the ADC block and sets auto flag clear */
  113. ATD0CTL3 = 0x40; /* Set sequence length = 8 */
  114. ATD0CTL4 = 0x73; /* Set the ADC clock and sample period for best accuracy */
  115. ATD0CTL5 = 0xB0; /* Sets justification to right, multiplex and scan all channels. Writing to this causes conversions to begin */
  116. /* And configure them all for analog input */
  117. 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 */
  118. //ATD0CTL1 = 0x07/* Trigger and interrupt configuration, unused for now. */
  119. ATD1CTL2 = 0xC0; /* Turns on the ADC block and sets auto flag clear */
  120. ATD1CTL3 = 0x40; /* Set sequence length = 8 */
  121. ATD0CTL4 = 0x73; /* Set the ADC clock and sample period for best accuracy */
  122. ATD0CTL5 = 0xB0; /* Sets justification to right, multiplex and scan all channels. Writing to this causes conversions to begin */
  123. }
  124. /// Set up the PWM module from configuration
  125. void initPWM(){
  126. /* TODO PWM channel concatenation for high resolution */
  127. // join channel pairs together here (needs 16 bit regs enabled too)
  128. /* TODO Initialise pwm channels with frequency, and initial duty for real use */
  129. // initial PWM settings for testing
  130. PWMPER0 = fixedConfigs2.inputOutputSettings.PWMPeriod0;
  131. PWMPER1 = fixedConfigs2.inputOutputSettings.PWMPeriod1;
  132. PWMPER2 = fixedConfigs2.inputOutputSettings.PWMPeriod2;
  133. PWMPER3 = fixedConfigs2.inputOutputSettings.PWMPeriod3;
  134. PWMPER4 = fixedConfigs2.inputOutputSettings.PWMPeriod4;
  135. PWMPER5 = fixedConfigs2.inputOutputSettings.PWMPeriod5;
  136. PWMPER6 = fixedConfigs2.inputOutputSettings.PWMPeriod6;
  137. PWMPER7 = fixedConfigs2.inputOutputSettings.PWMPeriod7;
  138. PWMDTY0 = fixedConfigs2.inputOutputSettings.PWMInitialDuty0;
  139. PWMDTY1 = fixedConfigs2.inputOutputSettings.PWMInitialDuty1;
  140. PWMDTY2 = fixedConfigs2.inputOutputSettings.PWMInitialDuty2;
  141. PWMDTY3 = fixedConfigs2.inputOutputSettings.PWMInitialDuty3;
  142. PWMDTY4 = fixedConfigs2.inputOutputSettings.PWMInitialDuty4;
  143. PWMDTY5 = fixedConfigs2.inputOutputSettings.PWMInitialDuty5;
  144. PWMDTY6 = fixedConfigs2.inputOutputSettings.PWMInitialDuty6;
  145. PWMDTY7 = fixedConfigs2.inputOutputSettings.PWMInitialDuty7;
  146. PWMCLK = fixedConfigs2.inputOutputSettings.PWMClock;
  147. PWMPRCLK = fixedConfigs2.inputOutputSettings.PWMClockPrescaler;
  148. PWMSCLA = fixedConfigs2.inputOutputSettings.PWMScalerA;
  149. PWMSCLB = fixedConfigs2.inputOutputSettings.PWMScalerB;
  150. PWMPOL = fixedConfigs2.inputOutputSettings.PWMPolarity;
  151. PWMCAE = fixedConfigs2.inputOutputSettings.PWMCenterAlign;
  152. PWMCTL = fixedConfigs2.inputOutputSettings.PWMControl & 0xF0; // Disallow access to power saving and reserved bits
  153. PWME = fixedConfigs2.inputOutputSettings.PWMEnable; // MUST be done after concatenation with PWMCTL
  154. }
  155. /// Set up all the pin states as per configuration, but protect key states.
  156. void initGPIO(){
  157. // Set the initial pin state of pins configured as output
  158. PORTA = fixedConfigs2.inputOutputSettings.PortInitialValueA | BIT6 | BIT7; // Mask the fuel pump relay and CEL pins on
  159. PORTB = fixedConfigs2.inputOutputSettings.PortInitialValueB;
  160. PORTC = fixedConfigs2.inputOutputSettings.PortInitialValueC;
  161. PORTD = fixedConfigs2.inputOutputSettings.PortInitialValueD;
  162. 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.
  163. PORTH = fixedConfigs2.inputOutputSettings.PortInitialValueH;
  164. PORTJ = fixedConfigs2.inputOutputSettings.PortInitialValueJ;
  165. PORTK = fixedConfigs2.inputOutputSettings.PortInitialValueK;
  166. PORTM = fixedConfigs2.inputOutputSettings.PortInitialValueM;
  167. PORTP = fixedConfigs2.inputOutputSettings.PortInitialValueP;
  168. PORTS = fixedConfigs2.inputOutputSettings.PortInitialValueS | 0x02; // Mask the SCI0 TX pin to high between transmissions!
  169. 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.
  170. /* AD0PT1 You are out of your mind if you waste this on digital Inputs */
  171. /* AD1PT1 You are out of your mind if you waste this on digital Inputs */
  172. // Initialise the Data Direction Registers
  173. DDRA = fixedConfigs2.inputOutputSettings.PortDirectionA | BIT6 | BIT7; // Mask the fuel pump relay and CEL pins as outputs
  174. DDRB = fixedConfigs2.inputOutputSettings.PortDirectionB;
  175. DDRC = fixedConfigs2.inputOutputSettings.PortDirectionC;
  176. DDRD = fixedConfigs2.inputOutputSettings.PortDirectionD;
  177. DDRE = fixedConfigs2.inputOutputSettings.PortDirectionE; // No need to mask off bits 0 and 1, they have no effect and are always inputs.
  178. DDRH = fixedConfigs2.inputOutputSettings.PortDirectionH;
  179. DDRJ = fixedConfigs2.inputOutputSettings.PortDirectionJ;
  180. DDRK = fixedConfigs2.inputOutputSettings.PortDirectionK;
  181. DDRM = fixedConfigs2.inputOutputSettings.PortDirectionM;
  182. DDRP = fixedConfigs2.inputOutputSettings.PortDirectionP;
  183. DDRS = fixedConfigs2.inputOutputSettings.PortDirectionS & 0xFE; // Mask the SCI0 RX pin as input between receiving
  184. 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.
  185. /* AD0DDR1 You are out of your mind if you waste this on digital Inputs */
  186. /* AD1DDR1 You are out of your mind if you waste this on digital Inputs */
  187. }
  188. /** @brief Buffer lookup tables addresses
  189. *
  190. * Save pointers to the lookup tables which live in paged flash.
  191. */
  192. void initLookupAddresses(){
  193. IATTransferTableLocation = (void*)&IATTransferTable;
  194. CHTTransferTableLocation = (void*)&CHTTransferTable;
  195. MAFTransferTableLocation = (void*)&MAFTransferTable;
  196. TestTransferTableLocation = (void*)&TestTransferTable;
  197. }
  198. /** @brief Buffer fuel tables addresses
  199. *
  200. * Save pointers to the fuel tables which live in paged flash.
  201. */
  202. void initFuelAddresses(){
  203. /* Setup addresses within the page to avoid warnings */
  204. VETableMainFlashLocation = (void*)&VETableMainFlash;
  205. VETableSecondaryFlashLocation = (void*)&VETableSecondaryFlash;
  206. VETableTertiaryFlashLocation = (void*)&VETableTertiaryFlash;
  207. LambdaTableFlashLocation = (void*)&LambdaTableFlash;
  208. VETableMainFlash2Location = (void*)&VETableMainFlash2;
  209. VETableSecondaryFlash2Location = (void*)&VETableSecondaryFlash2;
  210. VETableTertiaryFlash2Location = (void*)&VETableTertiaryFlash2;
  211. LambdaTableFlash2Location = (void*)&LambdaTableFlash2;
  212. }
  213. /** @brief Copy fuel tables to RAM
  214. *
  215. * Initialises the fuel tables in RAM by copying them up from flash.
  216. */
  217. void initPagedRAMFuel(void){
  218. /* Copy the tables from flash to RAM */
  219. RPAGE = RPAGE_FUEL_ONE;
  220. memcpy((void*)&TablesA, VETableMainFlashLocation, sizeof(mainTable));
  221. memcpy((void*)&TablesB, VETableSecondaryFlashLocation, sizeof(mainTable));
  222. memcpy((void*)&TablesC, VETableTertiaryFlashLocation, sizeof(mainTable));
  223. memcpy((void*)&TablesD, LambdaTableFlashLocation, sizeof(mainTable));
  224. RPAGE = RPAGE_FUEL_TWO;
  225. memcpy((void*)&TablesA, VETableMainFlash2Location, sizeof(mainTable));
  226. memcpy((void*)&TablesB, VETableSecondaryFlash2Location, sizeof(mainTable));
  227. memcpy((void*)&TablesC, VETableTertiaryFlash2Location, sizeof(mainTable));
  228. memcpy((void*)&TablesD, LambdaTableFlash2Location, sizeof(mainTable));
  229. }
  230. /** @brief Buffer timing tables addresses
  231. *
  232. * Save pointers to the timing tables which live in paged flash.
  233. */
  234. void initTimingAddresses(){
  235. /* Setup addresses within the page to avoid warnings */
  236. IgnitionAdvanceTableMainFlashLocation = (void*)&IgnitionAdvanceTableMainFlash;
  237. IgnitionAdvanceTableSecondaryFlashLocation = (void*)&IgnitionAdvanceTableSecondaryFlash;
  238. InjectionAdvanceTableMainFlashLocation = (void*)&InjectionAdvanceTableMainFlash;
  239. InjectionAdvanceTableSecondaryFlashLocation = (void*)&InjectionAdvanceTableSecondaryFlash;
  240. IgnitionAdvanceTableMainFlash2Location = (void*)&IgnitionAdvanceTableMainFlash2;
  241. IgnitionAdvanceTableSecondaryFlash2Location = (void*)&IgnitionAdvanceTableSecondaryFlash2;
  242. InjectionAdvanceTableMainFlash2Location = (void*)&InjectionAdvanceTableMainFlash2;
  243. InjectionAdvanceTableSecondaryFlash2Location = (void*)&InjectionAdvanceTableSecondaryFlash2;
  244. }
  245. /** @brief Copy timing tables to RAM
  246. *
  247. * Initialises the timing tables in RAM by copying them up from flash.
  248. */
  249. void initPagedRAMTime(){
  250. /* Copy the tables from flash to RAM */
  251. RPAGE = RPAGE_TIME_ONE;
  252. memcpy((void*)&TablesA, IgnitionAdvanceTableMainFlashLocation, sizeof(mainTable));
  253. memcpy((void*)&TablesB, IgnitionAdvanceTableSecondaryFlashLocation, sizeof(mainTable));
  254. memcpy((void*)&TablesC, InjectionAdvanceTableMainFlashLocation, sizeof(mainTable));
  255. memcpy((void*)&TablesD, InjectionAdvanceTableSecondaryFlashLocation, sizeof(mainTable));
  256. RPAGE = RPAGE_TIME_TWO;
  257. memcpy((void*)&TablesA, IgnitionAdvanceTableMainFlash2Location, sizeof(mainTable));
  258. memcpy((void*)&TablesB, IgnitionAdvanceTableSecondaryFlash2Location, sizeof(mainTable));
  259. memcpy((void*)&TablesC, InjectionAdvanceTableMainFlash2Location, sizeof(mainTable));
  260. memcpy((void*)&TablesD, InjectionAdvanceTableSecondaryFlash2Location, sizeof(mainTable));
  261. }
  262. /** @brief Buffer tunable tables addresses
  263. *
  264. * Save pointers to the tunable tables which live in paged flash and their
  265. * sub-sections too.
  266. */
  267. void initTunableAddresses(){
  268. /* Setup addresses within the page to avoid warnings */
  269. SmallTablesAFlashLocation = (void*)&SmallTablesAFlash;
  270. SmallTablesBFlashLocation = (void*)&SmallTablesBFlash;
  271. SmallTablesCFlashLocation = (void*)&SmallTablesCFlash;
  272. SmallTablesDFlashLocation = (void*)&SmallTablesDFlash;
  273. SmallTablesAFlash2Location = (void*)&SmallTablesAFlash2;
  274. SmallTablesBFlash2Location = (void*)&SmallTablesBFlash2;
  275. SmallTablesCFlash2Location = (void*)&SmallTablesCFlash2;
  276. SmallTablesDFlash2Location = (void*)&SmallTablesDFlash2;
  277. /* TablesA */
  278. dwellDesiredVersusVoltageTableLocation = (void*)&SmallTablesAFlash.dwellDesiredVersusVoltageTable;
  279. dwellDesiredVersusVoltageTable2Location = (void*)&SmallTablesAFlash2.dwellDesiredVersusVoltageTable;
  280. injectorDeadTimeTableLocation = (void*)&SmallTablesAFlash.injectorDeadTimeTable;
  281. injectorDeadTimeTable2Location = (void*)&SmallTablesAFlash2.injectorDeadTimeTable;
  282. postStartEnrichmentTableLocation = (void*)&SmallTablesAFlash.postStartEnrichmentTable;
  283. postStartEnrichmentTable2Location = (void*)&SmallTablesAFlash2.postStartEnrichmentTable;
  284. engineTempEnrichmentTableFixedLocation = (void*)&SmallTablesAFlash.engineTempEnrichmentTableFixed;
  285. engineTempEnrichmentTableFixed2Location = (void*)&SmallTablesAFlash2.engineTempEnrichmentTableFixed;
  286. primingVolumeTableLocation = (void*)&SmallTablesAFlash.primingVolumeTable;
  287. primingVolumeTable2Location = (void*)&SmallTablesAFlash2.primingVolumeTable;
  288. engineTempEnrichmentTablePercentLocation = (void*)&SmallTablesAFlash.engineTempEnrichmentTablePercent;
  289. engineTempEnrichmentTablePercent2Location = (void*)&SmallTablesAFlash2.engineTempEnrichmentTablePercent;
  290. dwellVersusRPMTableLocation = (void*)&SmallTablesAFlash.dwellVersusRPMTable;
  291. dwellVersusRPMTable2Location = (void*)&SmallTablesAFlash2.dwellVersusRPMTable;
  292. /* TablesB */
  293. loggingSettingsLocation = (void*)&SmallTablesBFlash.loggingSettings;
  294. loggingSettings2Location = (void*)&SmallTablesBFlash2.loggingSettings;
  295. perCylinderFuelTrimsLocation = (void*)&SmallTablesBFlash.perCylinderFuelTrims;
  296. perCylinderFuelTrims2Location = (void*)&SmallTablesBFlash2.perCylinderFuelTrims;
  297. /* TablesC */
  298. // TODO
  299. /* TablesD */
  300. // TODO
  301. /* filler defs */
  302. fillerALocation = (void*)&SmallTablesAFlash.filler;
  303. fillerA2Location = (void*)&SmallTablesAFlash2.filler;
  304. fillerBLocation = (void*)&SmallTablesBFlash.filler;
  305. fillerB2Location = (void*)&SmallTablesBFlash2.filler;
  306. fillerCLocation = (void*)&SmallTablesCFlash.filler;
  307. fillerC2Location = (void*)&SmallTablesCFlash2.filler;
  308. fillerDLocation = (void*)&SmallTablesDFlash.filler;
  309. fillerD2Location = (void*)&SmallTablesDFlash2.filler;
  310. }
  311. /**
  312. *
  313. */
  314. void initPagedRAMTune(){
  315. /* Copy the tables from flash to RAM */
  316. RPAGE = RPAGE_TUNE_ONE;
  317. memcpy((void*)&TablesA, SmallTablesAFlashLocation, sizeof(mainTable));
  318. memcpy((void*)&TablesB, SmallTablesBFlashLocation, sizeof(mainTable));
  319. memcpy((void*)&TablesC, SmallTablesCFlashLocation, sizeof(mainTable));
  320. memcpy((void*)&TablesD, SmallTablesDFlashLocation, sizeof(mainTable));
  321. RPAGE = RPAGE_TUNE_TWO;
  322. // &&&&&&&&&&&&&&&&&&&&&&&&&&&&&& WARNING &&&&&&&&&&&&&&&&&&&&&&&&&&&&&& //
  323. // You will get garbage if you use table switching at this time!!! //
  324. // XGATE code being run from this region temporarily!!! //
  325. // Writing to these tables WILL corrupt XGATE code/kill your engine! //
  326. // &&&&&&&&&&&&&&&&&&&&&&&&&&&&&& WARNING &&&&&&&&&&&&&&&&&&&&&&&&&&&&&& //
  327. //memcpy(xgateSchedRAMAddress, xgateSchedFlashAddress, (xgateSchedEnd - xgateSched));
  328. //memcpy(xgateInjectorsOnRAMAddress, xgateInjectorsOnFlashAddress, (xgateInjectorsOnEnd - xgateInjectorsOn));
  329. //memcpy(xgateInjectorsOffRAMAddress, xgateInjectorsOffFlashAddress, (xgateInjectorsOffEnd - xgateInjectorsOff));
  330. // memcpy((void*)&TablesA, SmallTablesAFlash2Location, sizeof(mainTable));
  331. // memcpy((void*)&TablesB, SmallTablesBFlash2Location, sizeof(mainTable));
  332. // memcpy((void*)&TablesC, SmallTablesCFlash2Location, sizeof(mainTable));
  333. // memcpy((void*)&TablesD, SmallTablesDFlash2Location, sizeof(mainTable));
  334. }
  335. /** @brief Buffer addresses of paged data
  336. *
  337. * Save the paged memory addresses to variables such that we can access them
  338. * from another paged block with no warnings.
  339. *
  340. * If you try to access paged data from the wrong place you get nasty warnings.
  341. * These calls to functions that live in the same page that they are addressing
  342. * prevent those warnings.
  343. *
  344. * @note Many thanks to Jean BĂ©langer for the inspiration/idea to do this!
  345. */
  346. void initAllPagedAddresses(){
  347. /* Setup pointers to lookup tables */
  348. initLookupAddresses();
  349. /* Setup pointers to the main tables */
  350. initFuelAddresses();
  351. initTimingAddresses();
  352. initTunableAddresses();
  353. }
  354. /** @brief Copies paged flash to RAM
  355. *
  356. * Take the tables and config from flash up to RAM to allow live tuning.
  357. *
  358. * For the main tables and other paged config we need to adjust
  359. * the RPAGE value to the appropriate one before copying up.
  360. *
  361. * This function is simply a delegator to the ones for each flash page. Each
  362. * one lives in the same paged space as the data it is copying up.
  363. */
  364. void initAllPagedRAM(){
  365. /* Setup the flash block pointers before copying flash to RAM using them */
  366. initAllPagedAddresses();
  367. /* Copy the tables up to their paged RAM blocks through the window from flash */
  368. initPagedRAMFuel();
  369. initPagedRAMTime();
  370. initPagedRAMTune();
  371. /* Default to page one for now, perhaps read the configured port straight out of reset in future? TODO */
  372. setupPagedRAM(TRUE); // probably something like (PORTA & TableSwitchingMask)
  373. }
  374. /* Initialise and set up all running variables that require a non-zero start value here */
  375. /* All other variables are initialised to zero by the premain built in code */
  376. void initVariables(){
  377. /* And the opposite for the other halves */
  378. CoreVars = &CoreVars0;
  379. DerivedVars = &DerivedVars0;
  380. ADCBuffers = &ADCBuffers0;
  381. ADCBuffersRecord = &ADCBuffers1;
  382. ticksPerDegree = &ticksPerDegree0; // TODO temp, remove, maybe
  383. ticksPerDegreeRecord = &ticksPerDegree1; // TODO temp, remove, maybe
  384. /* Setup the pointers to the registers for fueling use, this does NOT work if done in global.c, I still don't know why. */
  385. injectorMainTimeRegisters[0] = TC2_ADDR;
  386. injectorMainTimeRegisters[1] = TC3_ADDR;
  387. injectorMainTimeRegisters[2] = TC4_ADDR;
  388. injectorMainTimeRegisters[3] = TC5_ADDR;
  389. injectorMainTimeRegisters[4] = TC6_ADDR;
  390. injectorMainTimeRegisters[5] = TC7_ADDR;
  391. injectorMainControlRegisters[0] = TCTL2_ADDR;
  392. injectorMainControlRegisters[1] = TCTL2_ADDR;
  393. injectorMainControlRegisters[2] = TCTL1_ADDR;
  394. injectorMainControlRegisters[3] = TCTL1_ADDR;
  395. injectorMainControlRegisters[4] = TCTL1_ADDR;
  396. injectorMainControlRegisters[5] = TCTL1_ADDR;
  397. coreStatusA |= FUEL_PUMP_PRIME;
  398. // Initial state is NOT to fire... can be configured by scheduler if required.
  399. outputEventInputEventNumbers[0] = 0xFF;
  400. outputEventInputEventNumbers[1] = 0xFF;
  401. outputEventInputEventNumbers[2] = 0xFF;
  402. outputEventInputEventNumbers[3] = 0xFF;
  403. outputEventInputEventNumbers[4] = 0xFF;
  404. outputEventInputEventNumbers[5] = 0xFF;
  405. outputEventInputEventNumbers[6] = 0xFF;
  406. outputEventInputEventNumbers[7] = 0xFF;
  407. outputEventInputEventNumbers[8] = 0xFF;
  408. outputEventInputEventNumbers[9] = 0xFF;
  409. outputEventInputEventNumbers[10] = 0xFF;
  410. outputEventInputEventNumbers[11] = 0xFF;
  411. outputEventInputEventNumbers[12] = 0xFF;
  412. outputEventInputEventNumbers[13] = 0xFF;
  413. outputEventInputEventNumbers[14] = 0xFF;
  414. outputEventInputEventNumbers[15] = 0xFF;
  415. outputEventInputEventNumbers[16] = 0xFF;
  416. outputEventInputEventNumbers[17] = 0xFF;
  417. outputEventInputEventNumbers[18] = 0xFF;
  418. outputEventInputEventNumbers[19] = 0xFF;
  419. outputEventInputEventNumbers[20] = 0xFF;
  420. outputEventInputEventNumbers[21] = 0xFF;
  421. outputEventInputEventNumbers[22] = 0xFF;
  422. outputEventInputEventNumbers[23] = 0xFF;
  423. // 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
  424. }
  425. /** @brief Flash module setup
  426. *
  427. * Initialise configuration registers for the flash module to allow burning of
  428. * non-volatile flash memory from within the firmware.
  429. *
  430. * The FCLKDIV register can be written once only after reset, thus the lower
  431. * seven bits and the PRDIV8 bit must be set at the same time.
  432. *
  433. * We want to put the flash clock as high as possible between 150kHz and 200kHz
  434. *
  435. * The oscillator clock is 16MHz and because that is above 12.8MHz we will set
  436. * the PRDIV8 bit to further divide by 8 bits as per the manual.
  437. *
  438. * 16MHz = 16000KHz which pre-divided by 8 is 2000kHz
  439. *
  440. * 2000kHz / 200kHz = 10 thus we want to set the divide register to 10 or 0x0A
  441. *
  442. * Combining 0x0A with PRDIV8 gives us 0x4A (0x0A | 0x40 = 0x4A) so we use that
  443. *
  444. * @author Sean Keys
  445. *
  446. * @note If you use a different crystal lower than 12.8MHz PRDIV8 should not be set.
  447. *
  448. * @warning If the frequency you end up with is outside 150kHz - 200kHz you may
  449. * damage your flash module or get corrupt data written to it.
  450. */
  451. void initFlash(){
  452. FCLKDIV = 0x4A; /* Set the flash clock frequency */
  453. FPROT = 0xFF; /* Disable all flash protection */
  454. FSTAT = FSTAT | (PVIOL | ACCERR); /* Clear any errors */
  455. }
  456. /* Set up the timer module and its various interrupts */
  457. void initECTTimer(){
  458. /** @todo TODO Take the configuration from the decoder (as is) and mask it such that it does not affect the 6 other channels.
  459. * Take the the number of output channels required from configuration and configure that many as outputs
  460. * Configure the balance in whatever way is specified in the GPIO configuration - allow second input to be reused as GPI only.
  461. *
  462. * This stuff affects:
  463. * - TIE = 0x01 or 0x03, only. OC channels enabled as required and IC only for RPM/position.
  464. * - TIOS = nope, always 0xFC for 2 IC and 6 OC
  465. * - TCTL (1,2,3,4) 4 = 0x0? mask off high 4 bits and allow low 4 to come from decoder config/init
  466. * - PORTT = zeros, with balance from config
  467. * - DDRT = 0,1 inputs, or if unused by decoder, from config
  468. */
  469. // TODO rearrange the order of this stuff and pull enable and interrupt enable out to the last function call of init.
  470. /* Timer channel interrupts */
  471. 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 */
  472. TFLG = ONES; /* Clear all the flags such that we are up and running before they first occur */
  473. TFLGOF = ONES; /* Clear all the flags such that we are up and running before they first occur */
  474. /* TODO Turn the timer on and set the rate and overflow interrupt */
  475. // DLYCT = 0xFF; /* max noise filtering as experiment for volvo this will come from flash config */ // just hiding a wiring/circuit issue...
  476. TSCR1 = 0x88; /* 0b_1000_1000 Timer enabled, and precision timer turned on */
  477. TSCR2 = 0x87; /* 0b_1000_0111 Overflow interrupt enable, divide by 256 if precision turned off */
  478. // PTPSR = 0x03; /* 4 prescaler gives .1uS resolution and max period of 7ms measured */
  479. PTPSR = 0x1F; /* 32 prescaler gives 0.8uS resolution and max period of 52.4288ms measured */
  480. // PTPSR = 0x3F; /* 64 prescaler gives 1.6uS resolution and max period of 105ms measured */
  481. // PTPSR = 0xFF; /* 256 prescaler gives 6.4uS resolution and max period of 400ms measured */
  482. // PTPSR = 0x7F; /* 128 prescaler gives 3.2uS resolution and max period of 200ms measured */
  483. /* http://duckduckgo.com/?q=1+%2F+%2840MHz+%2F+32+%29 */
  484. /* http://duckduckgo.com/?q=%281+%2F+%2840MHz+%2F+32+%29%29+*+2^16 */
  485. /* www.mecheng.adelaide.edu.au/robotics_novell/WWW_Devs/Dragon12/LM4_Timer.pdf */
  486. /* Initial actions */
  487. TIOS = 0xFC; /* 0b_1111_1100 0 and 1 are input capture, 2 through 7 are output compare */
  488. TCTL1 = ZEROS; /* Set disabled at startup time, use these and other flags to switch fueling on and off inside the decoder */
  489. TCTL2 = ZEROS; /* 0,1 have compare turned off regardless as they are in IC mode. */
  490. TCTL3 = ZEROS; /* Capture off for 4 - 7 */
  491. TCTL4 = 0x0F; /* Capture on both edges of two pins for IC (0,1), capture off for 2,3 */
  492. // TODO setup delay counters on 0 and 1 to filter noise (nice feature!)
  493. //DLYCT = ??; built in noise filter
  494. // PTMCPSR = 0xFF // Precision prescaler - fastest is 1 represented by 0, slowest/longest possible is 256 represented by 255 or 0xFF
  495. // MCCNT = ONES16; // init to slowest possible, first
  496. // MCCTL = 0xC4; // turn on and setup the mod down counter
  497. // MCFLG = 0x80; // clear the flag up front
  498. decoderInitPreliminary();
  499. }
  500. /* Configure the PIT timers for their various uses. */
  501. void initPITTimer(){
  502. // // set micro periods
  503. // PITMTLD0 = 0x1F; /* 32 prescaler gives 0.8uS resolution and max period of 52.4288ms measured */
  504. // PITMTLD1 = 0x1F; /* ditto */
  505. // /* http://duckduckgo.com/?q=1+%2F+%2840MHz+%2F+32+%29 Exactly the same as for ECT */
  506. //
  507. // // set timers running
  508. // PITLD0 = dwellPeriod;
  509. // // enable module
  510. // PITCFLMT = 0x80;
  511. // // enable channels
  512. // //PITCE = 0x03;
  513. // // enable interrupt
  514. // PITINTE = 0x01;
  515. // // clear flags
  516. // //PITFLT = ONES;
  517. }
  518. /* Setup the sci module(s) that we need to use. */
  519. void initSCIStuff(){
  520. /* The alternative register set selector defaults to zero */
  521. // set the baud/data speed
  522. SCI0BD = fixedConfigs1.serialSettings.baudDivisor;
  523. // etc
  524. /* Switch to alternative register set? */
  525. // etc
  526. /* Switch back again? */
  527. /*
  528. * 0 = LOOPS (normal two wire operation)
  529. * 0 = SCISWAI (Wait mode on)
  530. * 0 = RSRC (if loops=1, int/ext wiring)
  531. * 1 = M MODE (9 bit operation)
  532. * 0 = WAKE (idle line wakeup)
  533. * 0 = ILT (idle line type count start pos)
  534. * 1 = PE (parity on)
  535. * 1 = PT (odd parity)
  536. *
  537. * 0x13 = ODD (default)
  538. * 0x12 = EVEN
  539. * 0x00 = NONE
  540. */
  541. SCI0CR1 = 0x13;
  542. /*
  543. * 0 = TIE (tx data empty isr disabled)
  544. * 0 = TCIE (tx complete isr disabled)
  545. * 1 = RIE (rx full isr enabled)
  546. * 0 = ILIE (idle line isr disabled)
  547. * 0 = TE (transmit disabled)
  548. * 1 = RE (receive enabled)
  549. * 0 = RWU (rx wake up normal)
  550. * 0 = SBK (send break off)
  551. */
  552. SCI0CR2 = 0x24;
  553. }
  554. /* TODO Load and calculate all configuration data required to run */
  555. void initConfiguration(){
  556. // // 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.
  557. /* Add in tunable physical parameters at boot time TODO move to init.c TODO duplicate for secondary fuel? or split somehow?
  558. *nstant = ((masterConst * perCylinderVolume) / (stoichiometricAFR * injectorFlow));
  559. *nstant = ((139371764 * 16384) / (15053 * 4096));
  560. * OR
  561. *nstant = ((masterConst / injectorFlow) * perCylinderVolume) / stoichiometricAFR;
  562. *nstant = ((139371764 / 4096) * 16384) / 15053;
  563. * http://duckduckgo.com/?q=%28%28139371764++%2F+4096%29+*+16384%29+%2F+15053 */
  564. bootFuelConst = ((unsigned long)(masterFuelConstant / fixedConfigs1.engineSettings.injectorFlow) * fixedConfigs1.engineSettings.perCylinderVolume) / fixedConfigs1.engineSettings.stoichiometricAFR;
  565. /* The ADC range used to generate TPS percentage */
  566. TPSADCRange = fixedConfigs2.sensorRanges.TPSMaximumADC - fixedConfigs2.sensorRanges.TPSMinimumADC;
  567. }
  568. /* Set up all the remaining interrupts */
  569. void initInterrupts(){
  570. /* IMPORTANT : Set the s12x vector base register (Thanks Karsten!!) */
  571. IVBR = 0xF7; /* Without this the interrupts will never find your code! */
  572. /* Set up the Real Time Interrupt */
  573. RTICTL = 0x81; /* 0b_1000_0001 0.125ms/125us period http://duckduckgo.com/?q=1+%2F+%2816MHz+%2F+%282+*+10^3%29+%29 */
  574. // RTICTL = 0xF9; /* 0b_1111_1001 0.125s/125ms period http://duckduckgo.com/?q=1+%2F+%2816MHz+%2F+%282*10^6%29+%29 */
  575. CRGINT |= 0x80; /* Enable the RTI */
  576. CRGFLG = 0x80; /* Clear the RTI flag */
  577. // set up port H for testing
  578. PPSH = ZEROS; // falling edge/pull up for all
  579. PIEH = ONES; // enable all pins interrupts
  580. PIFH = ONES; // clear all port H interrupt flags
  581. // TODO set up irq and xirq for testing
  582. // IRQCR for IRQ
  583. /* VReg API setup (only for wait mode? i think so) */
  584. // VREGAPIR = 0x09C3; /* For 500ms period : (500ms - 0.2ms) / 0.2ms = 0b100111000011 = 2499 */
  585. // VREGAPICL = 0x02; /* Enable the interrupt */
  586. // VREGAPICL = 0x04; /* Start the counter running */
  587. /* 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 */
  588. /* LVI Low Voltage Interrupt enable */
  589. VREGCTRL = 0x02; // Counts bad power events for diagnosis reasons
  590. }