Hi, I thought I would start a new thread to both document my steps as well as to possibly get some help and suggestions on this issue. Feel free to add some info if you have any ideas that i could try.
So what i am trying to do is to speed up the rate at which we can log Engine Data from the ecu via the serial interface.
My goal is to be able to consistently log engine data at around 20 hz (i.e. every 50ms). This should allow us to log a good amount of data for the auto tune process as well as allowing drag racing guys to log runs and get a meaningful amount of data from a pass.
I will add separate posts for the different things i have tried so far.
The standard serial Baud rate for the Serial Interface SIO4 used for the engine data communications is 10,400. This is controlled predominately by the SIO4 Baud Rate Register located at 0x00800A17. There are other registers that affect the Baud Rate but I have chosen to concentrate on this register. see the hardware manual for details on the other registers.
The default value of the SIO4 Baud Rate Register is 0x17 (23) which gives a Baud Rate of 10,400.
With the baud rate set at 10,400 the fastest you can reliably retrieve engine data is around every 150ms.
I have changed this setting by modifying initialization routine at &H13259 and setting the value to 0x4 which gives a Baud Rate of 50,000.
With the baud rate set at 50,000 the fastest you can reliably retrieve engine data is around every 100ms.
Everything else being equal, I would expect to see this rate speed up by around 5 times (i.e. to around 30ms) but unfortunately this is not the case.
Based on the above something else seems to be restricting the rate at which we can request the data over the serial interface... I have tried other baud rates including 125000, 250000 etc but i was unable to make a stable connection to the ecu at these rates.
The process for requesting engine data from the ecu involves the requesting application initiating communications and then sending a request for particular data by sending a series of bytes which specify which set of engine data to send back.
This code runs on the ecu as an Interrupt. When the external application sends a request an interrupt is fired on the ecu.
The interrupt routine is specified in the interrupt vector table at 0x000000FC
The interrupt routine processes the request to determine which group of data (kwp packet) to send back.
The way interrupts work is when an external event happens (i.e. client application send request over serial line) the relevant interrupt fires and the code from the interrupt vector table runs. When (i.e. how soon) this happens is controlled by the interrupt priority. On the m32R there are 8 different priorities with lower numbers being higher priority. The highest priority interrupts run first followed by the next highest priority interrupt etc etc.
By default the SIO4 receive interrupt is set to priority 6, so I have tried setting it to a lower priority by changing the initialization code at 0x000127E8 to set the priority to 3.
This had no effect on speeding up the engine data serial communications... So i conclude from this that the serial communication speed is not being limited by the Interrupt Priority of the SIO4 request Interrupt handler.
The next thing i have tried is to use a smaller data package. Currently the main data is requested from the engine with the following sequence of bytes
0x80 0x12 0xF1 0x2 0x21 0x8 0xAE
This returns 128 bytes of data which has a theoretical transfer time of around 125 ms at 10400 baud.
the calculation for this is
128 bytes in kwp package
8 bit per byte plus start and stop bits => 1280 bits
10400 baud = 10400 bits per sec => 8.125 packages per second
theoretical transfer time= approx every 125 ms
so i figure if i use one of the smaller kwp packages with less bytes of data to transfer it should be faster.
So i tried to use the kwp package requested with the following byte sequence
0x80 0x12 0xF1 0x2 0x21 0x40 0xFF
this kwp package is around 28 bytes long. The maximum stable engine data transfer rate i could get using this smaller data package is around 80ms. Based on a calculation similar to above it should be much faster at below 30 ms....
28 bytes in kwp package
8 bit per byte plus start and stop bits => 280 bits
10400 baud = 10400 bits per sec => 37.14 packages per second
Hi Justin, the baudrate ist not the only goal, take a look at at 800A01 and 800A16, i think the receive interrupt is only every 100ms enable.
Boerd
Hi Boerd, thanks for contributing, this is exactly the type of into I was looking for, So if i understand correctly the important bit is bit 9 at 800A01 (R4MASK) which enables/disables the interrupt. and bit 3 at 800A16 which Enables reception on SI04?
i have traced through some of the references to these registers, there seem to be quite a few references. do you have any suggestions on the best way to enable the receive interrupt to process requests at a faster rate?
I have now watched not just in the code, but I would have to program something I would do it this way: KWP received, prevent receipt and return the requested data, released after a certain time, the reception again. If you could share just after sending the data to receive back one block to the ECU.
For me, you must make first one flow chart of the ECU program to understand all the functions.
I have now watched not just in the code, but I would have to program something I would do it this way: KWP received, prevent receipt and return the requested data, released after a certain time, the reception again. If you could share just after sending the data to receive back one block to the ECU.
For me, you must make first one flow chart of the ECU program to understand all the functions.
Boerd
Hi Boerd, If I understand you correctly you mean
1) When KWP Received => Return requested KWP Data
2) Dont allow SIO4 to be disabled
3) Process next KWP request
I was also thinking about it slightly differently. It looks like the SIO4 is enabled in MJT input interrupt 0, which is a input multi junction timer. I think if i am reading the assembly correctly, this timer enables to SIO4 interrupt after a certain amount of time after the last KWP request and this may be what stops up from requesting data faster than every 100ms.
Do you think it would be a valid approach to decrease the timer duration so it enables SIO4 faster after each KWP request?
jkwool wrote:I was also thinking about it slightly differently. It looks like the SIO4 is enabled in MJT input interrupt 0, which is a input multi junction timer. I think if i am reading the assembly correctly, this timer enables to SIO4 interrupt after a certain amount of time after the last KWP request and this may be what stops up from requesting data faster than every 100ms.
Do you think it would be a valid approach to decrease the timer duration so it enables SIO4 faster after each KWP request?
This is exactly what I wanted to say, but do not decrease the timer too much the ECU need a little bit time for other things
This is exactly what I wanted to say, but do not decrease the timer too much the ECU need a little bit time for other things
I am trying to get my head around the timers, is there a specific setting that i can change to decrease the time for this function to run? or is it controlled within the function itself.
I can see in the code for the function that some comparisons are done before the SIO4 enable code is run
0x258 and 0x3FC
are these the numbers i should adjust or is there another way to change this?
I have not tested this yet but I think the 2 values i need to change are at locations in the busa.bin file.
ROM_:0000EC50 cmpui R0, #0x2CEC
and
ROM_:0000EC60 cmpui R0, #0x34BD
If i am reading the assembly code correctly when unk_80452C is greater than these 2 values the following code runs which i think enables SIO4 so it can receive a new engine data request? So if i reduce these 2 values it should enable SIO4 more often which will allow more frequent engine data requests.
ROM_:0000EC88 mv R0, R1 || nop
ROM_:0000EC8C ld24 R1, #SIO45SEL_unk_800A02
ROM_:0000EC90 stb R0, @R1 || nop
ROM_:0000EC94 ld24 R0, #SIO45MASK_unk_800A01
ROM_:0000EC98 ldub R1, @R0 || nop
ROM_:0000EC9C and3 R1, R1, #0xBF
ROM_:0000ECA0 or3 R0, R1, #0x40
ROM_:0000ECA4 ld24 R1, #SIO45MASK_unk_800A01
ROM_:0000ECA8 stb R0, @R1 || nop
ROM_:0000ECAC ld24 R0, #SIO4RCNT_unk_800A16
ROM_:0000ECB0 ldub R1, @R0 || nop
ROM_:0000ECB4 and3 R1, R1, #0xEF
ROM_:0000ECB8 or3 R0, R1, #0x10
ROM_:0000ECBC ld24 R1, #SIO4RCNT_unk_800A16
ROM_:0000ECC0 stb R0, @R1 || nop
ROM_:0000ECC4 ld24 R1, #unk_804CBC
ROM_:0000ECC8 ldi R0, #1
ROM_:0000ECCA stb R0, @R1
ROM_:0000ECCC ld24 R1, #unk_804CB6
ROM_:0000ECD0 ldi R0, #2
ROM_:0000ECD2 stb R0, @R1
ROM_:0000ECD4 bra loc_ECE0 || nop
I am still on a big learning curve with reading assembly so I could be very wrong on this, can anyone with more experience verify that i am on the right path?
Hi Justin, sorry i have no much time for go through the code, but some infos: the timer is the TIO2 the reload value is 0x27F the timer counts down, is the timer 0 the timer interrupt is raised and the timer starts from 0x27F, i have not looking at the clock source but i think is easy.
Boerd
-- Edited by Boerd on Wednesday 8th of September 2010 07:31:46 AM
Hi Justin, sorry i have no much time for go through the code, but some infos: the timer is the TIO2 the reload value is 0x27F the timer counts down, is the timer 0 the timer interrupt is raised and the timer starts from 0x27F, i have not looking at the clock source but i think is easy.
Boerd
-- Edited by Boerd on Wednesday 8th of September 2010 07:31:46 AM
No problems Boerd, I appreciate you taking the time to provide some useful info!
Ok, I am still trying to work this out as i am determined to get a faster data logging for Auto Tune :)
Here is some more info i have found, I will try to explain what i have found as i go. I am not sure if i am on the right track here. I dont know if the info below only relates to the initialization hand shake between the PC and the ECU or if its part of the main KWP processing to enable the SIO4 each time a new request is made?
I have found that the S4RCNT 00800A16 enable code runs in this interrupt vector
So what i am thinking is that MJT Input Interrupt 0 Handler is called from TIN8 which is called from P44. The SIO4 enabling code runs at location 0xEC68 (gen 2 busa) or location 0xEC68 (B-King) when the the difference between 2 Ram variables is between 0x2CEC and 0x34BD
maybe this is just for the initialization sequence?
Justin, I believe you have spent more time than anyone else with SIO so dont know if can help you, but these two things hopefully can be food for thought:
1) In gen1 the timer calls a subroutine that sends enginedata, this happens at a certain interval. So I believe that the sio can not be real time response, rather the output must be limited to keep the more important ecu functions to run.
2) In the main loop the KWP protocol gets called by ROM_:000022B0 bl.l KWP_SIO_processing_sub_EEE0m, at least what I gather at first sight. Maybe there is something to be looked at for how often the SIO rutines get called ?
__________________
When asking a question, you can also consider posting it to facebook:
PetriK wrote:1) In gen1 the timer calls a subroutine that sends enginedata, this happens at a certain interval. So I believe that the sio can not be real time response, rather the output must be limited to keep the more important ecu functions to run.
2) In the main loop the KWP protocol gets called by ROM_:000022B0 bl.l KWP_SIO_processing_sub_EEE0m, at least what I gather at first sight. Maybe there is something to be looked at for how often the SIO rutines get called ?
Hi, the ecu send the data over DMA, the cpu set only start and end adress for the ram and a start bit, that requires a very little time.
but for me it seems that the communication is time controlled.
In gen1 the DMA is separate to actual push the bits out function, not really sure about gen2. Gen1 push bits out was on a timer call, DMA was when packet is ready if I recall correctly.
But these functions above refer to main loop in gen2 and seem to have some kind of counters when to access SIO, have not had time to hack what it exactly does.
__________________
When asking a question, you can also consider posting it to facebook:
I have tried changing the values in the functions that run in the main loop that look like they could be counters used to control when the SIO4 is enabled.
I have tried changing these values individually and using different combinations but none of the changes seemed to make any difference to the rate at which i can request data from the ecu.
Do you think i am looking in the correct place? Are there any other things we could try?
After doing this sudoku for 30 minutes for now, I start to think that the send out data is only performed after Multijunction timer irq 5 interrupt. The current run rate is 8Hz was it ? The chain for innovate runs at 10Hz if I remember correctly so not so far off ?
After doing this sudoku for 30 minutes for now, I start to think that the send out data is only performed after Multijunction timer irq 5 interrupt. The current run rate is 8Hz was it ? The chain for innovate runs at 10Hz if I remember correctly so not so far off ?
Yes this is very much a puzzle :) and one worth solving!
Current engine data is only reliable at around 150 ms = 6.67 hz , by increasing the baud rate to 50, 000 i have been able to request engine data every 100ms = 10hz but this is only working on the bench and not when ecu is in bikes.
LC-1 data rate is approximately every 82ms or 12.2 Hz. We are not restricted by the LC-1 data bus as we are taking a direct 0-5v feed from the LC-1 so my goal is to be able to request data every 50ms = 20Hz
Do you think that we should be looking in the MJT output interrupt 5 IRQ5 interrupt routine? or the code that enables or controls this interrupt?
Petri, I followed your logic through and I changed the counter for MJT IRQ5 and also the reset value for this counter at the following locations
TOP10CT : 0x000012B70 - 0x1F4 => 0xFA
TOP10RL : 0x000012BEE - 0x1F3 => 0xF9
AND IT WORKED!!!!!!
I have been able to log engine data, both on the bench and on my bike, with a timer setting of 50ms which translates to about every 65ms when data processing is taken into account!!!
I have not been able to test the logging with the engine running as it is getting too late here to start my bike up, I plan to do some proper real world testing tomorrow and if all goes well i will do a release over the weekend.
Thanks heaps for putting me in the right direction Petri, your help is really appreciated!
Thanks also to Boerd for contributing to this hack!
Cheers
-Justin.
-- Edited by jkwool on Friday 24th of September 2010 10:17:48 AM
please make the first test also with high rpm without driving!!!!
You have also speed up many other function.
After this test and all is working i change the timing into the primer and send you the code.
Boerd
Hi Boerd,
I agree, that is why i have not done a release yet as i want to check that the engine is functioning correctly first before unleashing the code. Fingers crossed!
When testing on bike with engine running, there is no effect on engine with the timer MJT IRQ 5 set to a higher rate, i warmed the bike up and revved it and it ran clean with no mis fires etc.
Unfortunately when the engine running the data logging at the faster rate is not working correctly, its like the timer function is affected when the engine is started. With the engine not running the faster log rate works 100% but as soon as the engine is started it does not seem to work.
My thoughts are
the IRQ 5 timer may be disabled or controlled elsewhere in the code
There could be interrupts with higher priorities that prevent the timer from running when the engine is running
There could be electrical interference that is affecting the serial signal
This may be too basic questions, but have you looked into searching (ctrl T) for the ram adress 80xxxx which is MJT5 downcount timer or alike ?
Well done with all the progress !!!
Hi Petri,
I have not searched for the text but i have right clicked on the variables and clicked "Jump to xref to operand" which generally shows all code locations that reference the variable/memory location. There is only one reference for the counter and one reference for the reload for TOP10 both of which are in the function init_TOP_sub_12AC4
8002E0 TOP10CT -> 00012B6C
8002E2 TOP10RL -> 00012BE8
I am still not certain if the problem i am having is related to electrical interference etc so i would like to see if this works for others with the engine running. Rolf has been able to run the fast baud rate and log data with the engine running but it did not seem to be saving the data at the 50ms interval, it was more like 100ms..
I might hook up my oscilloscope to the serial line on my bike and start the engine to see if i can detect any weired stuff going on with the serial signal.
Petri are you aware of any flags that indicate when the engine is running and are used to run certain code only when the engine is running?
Hey Justin when do you plan on releasing the software for the primer 2?
I am having a few issues with a couple of sections of code that i am working to resolve before being able to release anything, Boerd is also developing some software to run on the Primer 2 for engine logging.
I will let you know when i have any interesting updates.
the only problem i am have is getting my password for the primer2 site. i have registered with two different email accounts and still have not received a password
the only problem i am have is getting my password for the primer2 site. i have registered with two different email accounts and still have not received a password
weird, they were down for maintenance last week for days and days so it may be related to that. it has not gone to spam or something has it?
i can sent the code for the primer2 that display the engine-data on the lcd, also i can easy change the code to fast logging.
a other way is we logging the TPS, RPM, AFR, SAP and IAP direct with the primer so i have begin to write some code that logg this values every 6,25ms, but for this way i need some infos for the sensors iap and sap and we must have 4 new wires on the bike.
or someone help me at the M32R-Simulator projekt, i thing that not the fastest way but the best way for the future.