Announcement

Collapse
No announcement yet.

CSL '0401' Program Binary Disassembly Notes

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

    Instead of copying the logic in CAN_Send_DME_ARBIDs(), why not do some things like this:

    Code:
    void CAN_Send_All_ARBIDs(void) {
      CAN_Send_DME_ARBIDs();
      if (enough_time && enough_memory && etc) {
        CAN_Send_Extra_ARBIDs();
      }
    }
    Then CAN_Send_All_ARBIDs() can replace CAN_Send_DME_ARBIDs() in the 10ms task and CAN_Send_Extra_ARBIDs() can handle anything new.

    This makes it so that all the original logic is run with very little change in timing. Also gives you a lot more flexibility cause you can tell CAN_Send_Extra_ARBIDs() to do whatever you want and it won't interfere with the stock routines. Lastly, if the checks are comprehensive, you won't bog down the CPU.

    I like the idea of building out a new data structure for the extra data. No sense in trying to squeeze it in with the rest when you can just have your new function deal with the new data location.
    2002 Topasblau M3 - Coupe - 6MT - Karbonius CSL Airbox - MSS54HP Conversion - Kassel MAP - SSV1 - HJS - PCS Tune - Beisan - MK60 Swap - ZCP Rack - Nogaros - AutoSolutions - 996 Brembos - Slon - CMP - VinceBar - Koni - Eibach - BlueBus - Journal

    2012 Alpinweiss 128i - Coupe - 6AT - Slicktop - Manual Seats - Daily - Journal

    Comment


      Originally posted by Bry5on View Post
      Holy crap this is amazing! I think I had an ideal list of variables at some point back. This is all above my pay grade to easily jump in, how can I help?
      ​If you could dig out your ideal list of variables that would be super handy as a starting point. It will probably also give me the impetus to figure out what to do about values that originate from the slave CPU. I haven't looked but I'm guessing that there's probably room left in the DPR (given the carefree way BMW's engineers used it when adding on the 0401 specific functionality).


      Originally posted by heinzboehmer View Post
      Instead of copying the logic in CAN_Send_DME_ARBIDs(), why not do some things like this:

      Code:
      void CAN_Send_All_ARBIDs(void) {
      CAN_Send_DME_ARBIDs();
      if (enough_time && enough_memory && etc) {
      CAN_Send_Extra_ARBIDs();
      }
      }
      Then CAN_Send_All_ARBIDs() can replace CAN_Send_DME_ARBIDs() in the 10ms task and CAN_Send_Extra_ARBIDs() can handle anything new.

      This makes it so that all the original logic is run with very little change in timing. Also gives you a lot more flexibility cause you can tell CAN_Send_Extra_ARBIDs() to do whatever you want and it won't interfere with the stock routines. Lastly, if the checks are comprehensive, you won't bog down the CPU.

      I like the idea of building out a new data structure for the extra data. No sense in trying to squeeze it in with the rest when you can just have your new function deal with the new data location.
      Yeah that's a good suggestion. I'm not so sure that it will be easy/possible to check how much time/memory is left, given the way the OS manages and calls the tasks. I would need to dig in to this a bit more as part of this work. I know that the safety concept has safeguards built in to stop the DME from being overwhelmed by incoming CAN messages (given these are processed via interrupt) but I can't imagine anything similar exists for the outgoing messages given them are triggered from the timed task. Regardless I'll also look into this further.



      I'd be lying if I said I didn't have some concerns about the legal and moral liability of this. Making a modification of this scale to the program code without complete documentation and without a complete understanding of the entire operating system isn't without risk. Even if others completely absolved me of any responsibility in their eyes I'm not sure if I could stomach the risk of damaging someone else's car, or their life....

      I think next steps are as follows:

      1: Start getting together a list of values that are most in demand to be logged (this helps check whether there are any other gotchas by playing out real examples)
      2; Spend more time digging into OS safeguards around the timed tasks to understand worst-case scenarios
      3: Look into options around getting values from the slave CPU (probably via the DPR)
      2005 ///M3 SMG Coupe Silbergrau Metallic/CSL bucket seats/CSL airbox/CSL console/6 point RACP brace
      Build Thread:
      https://nam3forum.com/forums/forum/m...e46-m3-journal

      Comment


        Originally posted by karter16 View Post
        ​If you could dig out your ideal list of variables that would be super handy as a starting point. It will probably also give me the impetus to figure out what to do about values that originate from the slave CPU. I haven't looked but I'm guessing that there's probably room left in the DPR (given the carefree way BMW's engineers used it when adding on the 0401 specific functionality).
        The list:
        Intake Air Temp
        Radiator Temp
        EGT
        Relative Opening
        Lambda Integrator 1
        Lambda Integrator 2
        heinzboehmer anything I'm missing? Maybe Engine Load?

        I think everything else needed is available over CAN already

        And I think I can speak for Heinz when I say both of us are game to put DMEs at risk here - not much we can really do to damage the engine without it really not working at all I think.
        ‘02 332iT / 6 | ‘70 Jaguar XJ6 electric conversion

        Comment


          Originally posted by Bry5on View Post

          The list:
          Intake Air Temp
          Radiator Temp
          EGT
          Relative Opening
          Lambda Integrator 1
          Lambda Integrator 2
          heinzboehmer anything I'm missing? Maybe Engine Load?

          I think everything else needed is available over CAN already
          Awesome thanks!

          Intake Air Temp = TAN byte on Master @ 0x00FFEDD9
          Radiator Temp - do you want coolant temp (TMOT byte on Master @ 0x00FFEDDA) or radiator outlet temp (TKA byte on Master @ 0x00FFEDDE)?
          EGT = TABG word on slave but available on DPR @ 0x00FF8088
          Relative Opening = AQ_REL word on slave but available on DPR @ 0x00FF80DE or AQ_REL_ALPHA_N word on Master @ 0x00FE97A depending on what you want to use it for.
          Lambda Integrator 1 = LA_F_REGLER1 word on Slave but available on DPR @ 0x00FF80CA
          Lambda Integrator 2 = LA_F_REGLER2 word on Slave but available on DPR @ 0x00FF80CC

          All of these are available either from the Master CPU or are already available on the Dual-Ported RAM which is convenient.

          What is less convenient is that that's 10 bytes, and ideally we keep it to 8 bytes to fit in a single CAN message.



          Originally posted by Bry5on View Post
          And I think I can speak for Heinz when I say both of us are game to put DMEs at risk here - not much we can really do to damage the engine without it really not working at all I think.​
          You have more confidence in my assembly (actually it's not even going to be assembly really, more like poking machine code directly into the ROM) programming skills than I do myself haha. But yes, I was thinking about this further and I think that the safety concept implementation probably does mitigate a fair amount of the risk actually. I think provided I only change the Master section of the ROM then we can be pretty confident that the Slave will identify scenarios where the Master is non-performant and reset it and log a code. It hadn't occurred to me last night that all critical safety functions are maintained in parallel by both processors. I'll still do some more investigation into this but from a safety perspective even if there was some edge case bug in the modified code the Slave should maintain the function of the DME from a safety perspective.
          Last edited by karter16; 06-09-2025, 09:46 PM.
          2005 ///M3 SMG Coupe Silbergrau Metallic/CSL bucket seats/CSL airbox/CSL console/6 point RACP brace
          Build Thread:
          https://nam3forum.com/forums/forum/m...e46-m3-journal

          Comment


            Originally posted by karter16 View Post

            Awesome thanks!

            Intake Air Temp = TAN byte on Master @ 0x00FFEDD9
            Radiator Temp - do you want coolant temp (TMOT byte on Master @ 0x00FFEDDA) or radiator outlet temp (TKA byte on Master @ 0x00FFEDDE)?
            EGT = TABG word on slave but available on DPR @ 0x00FF8088
            Relative Opening = AQ_REL word on slave but available on DPR @ 0x00FF80DE or AQ_REL_ALPHA_N word on Master @ 0x00FE97A depending on what you want to use it for.
            Lambda Integrator 1 = LA_F_REGLER1 word on Slave but available on DPR @ 0x00FF80CA
            Lambda Integrator 2 = LA_F_REGLER2 word on Slave but available on DPR @ 0x00FF80CC

            All of these are available either from the Master CPU or are already available on the Dual-Ported RAM which is convenient.





            You have more confidence in my assembly programming skills than I do myself haha. But yes, I was thinking about this further and I think that the safety concept implementation probably does mitigate a fair amount of the risk actually. I think provided I only change the Master section of the ROM then we can be pretty confident that the Slave will identify scenarios where the Master is non-performant and reset it and log a code. It hadn't occurred to me last night that all critical safety functions are maintained in parallel by both processors. I'll still do some more investigation into this but from a safety perspective even if there was some edge case bug in the modified code the Slave should maintain the function of the DME from a safety perspective.
            I think TMOT is already available on CAN ID 0x329 but radiator outlet temp is not. So, radiator outlet temp

            Relative opening would be for part throttle tuning, or IDing where in the map you are for any given condition. Nice that they're all generally available!

            For completeness, here are some of the other things I log..

            CAN ID 0x316:
            - Engine Speed
            - Torque command​

            CAN ID 0x329:
            - Cruise control buttons
            - Coolant temp
            - Ambient pressure
            - TPS
            - Clutch/Neutral status

            CAN ID 0x545:
            - Cruise active status
            - Oil temp
            - Oil level

            CAN ID 0x153 (from DSC):
            - Speedo
            - Brake status (binary on/off, not pressure)
            - DSC status
            - DSC intervention status
            - DSC commanded throttle cuts

            CAN ID 0x615 (from cluster):
            - Ambient temp
            - Displayed Speed
            - Night lighting status (thanks Heinz)

            CAN ID 0x1F3 (from DSC):
            - Lateral acceleration
            - Longitudinal acceleration
            - Yaw rate

            CAN ID 0x1F5 (from steering angle sensor):
            - Steering angle
            Last edited by Bry5on; 06-09-2025, 10:09 PM.
            ‘02 332iT / 6 | ‘70 Jaguar XJ6 electric conversion

            Comment


              Okay cool - TKA it is.

              The more I look at this the simpler it seems to be getting. Slight change in approach to that proposed above.

              Turns out there actually IS some space to add a pointer in the array to another CAN function. It looks like it's full but actually repeats several times for ARBID 0x513 (which is the last one in the array) so I could slot an additional one in there. The advantage of that is that I could then use the existing CAN_Send_DME_ARBID() function to call the new one as well (less messing around making sure I've set the stack correctly before jumping to the new function, etc.).

              This then means that the actual coding boils down to the following:

              1: Create a copy of CAN_Send_DME_ARBIDs() in empty ROM space - ~ 30 instructions.
              2: Reference the new function in the 10ms task - 1 instruction.
              3: Create a new function that handles the new CAN message in empty ROM space - ~ 80 instructions (based on the function for ARBID 0x316).

              This would of course be for a simple version with fixed variables. Abstracting out the ability to configure what variables to push would be significantly more work.

              Don't want to make it seem simpler than it is. That's still over 100 instructions to craft by hand (no assembler, no ability to use labels, etc.) and then debug by hand. It's a lot of work, but it does seem as though it should be achievable.

              2005 ///M3 SMG Coupe Silbergrau Metallic/CSL bucket seats/CSL airbox/CSL console/6 point RACP brace
              Build Thread:
              https://nam3forum.com/forums/forum/m...e46-m3-journal

              Comment


                Originally posted by karter16 View Post
                You have more confidence in my assembly (actually it's not even going to be assembly really, more like poking machine code directly into the ROM) programming skills than I do myself haha. But yes, I was thinking about this further and I think that the safety concept implementation probably does mitigate a fair amount of the risk actually. I think provided I only change the Master section of the ROM then we can be pretty confident that the Slave will identify scenarios where the Master is non-performant and reset it and log a code. It hadn't occurred to me last night that all critical safety functions are maintained in parallel by both processors. I'll still do some more investigation into this but from a safety perspective even if there was some edge case bug in the modified code the Slave should maintain the function of the DME from a safety perspective.
                I would 100% put my DME at risk to try this sort of thing out. Thing has been through WAY worse. There's a couple jumper wires hanging out in there cause I've destroyed some pads with so much soldering/desoldering.

                But I totally get it, distributing this kind of stuff is scary. Almost as scary as the assembly itself, ha.


                Also, I think Bryson covered everything. I'm essentially logging the exact same things.
                2002 Topasblau M3 - Coupe - 6MT - Karbonius CSL Airbox - MSS54HP Conversion - Kassel MAP - SSV1 - HJS - PCS Tune - Beisan - MK60 Swap - ZCP Rack - Nogaros - AutoSolutions - 996 Brembos - Slon - CMP - VinceBar - Koni - Eibach - BlueBus - Journal

                2012 Alpinweiss 128i - Coupe - 6AT - Slicktop - Manual Seats - Daily - Journal

                Comment


                  Originally posted by karter16 View Post
                  Don't want to make it seem simpler than it is. That's still over 100 instructions to craft by hand (no assembler, no ability to use labels, etc.) and then debug by hand. It's a lot of work, but it does seem as though it should be achievable.
                  Don’t have to do this by hand, if you can get a compiler going for this arch you can just write it in C, compile as a single function without runtimes and copy the assembly from the compiled program.
                  E46 ///M3 • 12/2002 • phönix-gelb • 6MT
                  E39 ///M5 • 12/1998 • avus-blau • 6MT
                  E60 ///M5 • 11/2006 • saphir-schwarz • 6MT

                  Comment


                    Originally posted by bmwfnatic View Post

                    Don’t have to do this by hand, if you can get a compiler going for this arch you can just write it in C, compile as a single function without runtimes and copy the assembly from the compiled program.
                    I'd still need to map the various memory locations for the compiler somehow though right? (e.g. stack location, locations of the global variables, etc., plus tell it what values were already in what registers, etc.). Also if the compiler doesn't have an understanding of the memory map and where the function is going to go in memory space it's not necessarily going to get things like near and far jumps right, etc. I'd have thought?
                    2005 ///M3 SMG Coupe Silbergrau Metallic/CSL bucket seats/CSL airbox/CSL console/6 point RACP brace
                    Build Thread:
                    https://nam3forum.com/forums/forum/m...e46-m3-journal

                    Comment


                      If you guys had to reduce that list by 2 bytes what would you drop? Lambda Integrator 2? (I only say that cause like Heinz I've found bank 1 runs consistently slightly leaner than bank 2 so I only really need to use Lambda 1)
                      2005 ///M3 SMG Coupe Silbergrau Metallic/CSL bucket seats/CSL airbox/CSL console/6 point RACP brace
                      Build Thread:
                      https://nam3forum.com/forums/forum/m...e46-m3-journal

                      Comment


                        Originally posted by karter16 View Post
                        If you guys had to reduce that list by 2 bytes what would you drop? Lambda Integrator 2? (I only say that cause like Heinz I've found bank 1 runs consistently slightly leaner than bank 2 so I only really need to use Lambda 1)
                        Yep!
                        ‘02 332iT / 6 | ‘70 Jaguar XJ6 electric conversion

                        Comment


                          Random aside.

                          One of the torque limitations in the Moment Manager is to restrict maximum torque below a certain vehicle speed under certain conditions in order to quote "reduce noise". I've seen others edit this out by adjusting KL_MD_BEGR_NOISE to not have restricted torque below 60 km/h.

                          Click image for larger version  Name:	Screenshot 2025-06-13 at 4.42.42 PM.png Views:	0 Size:	15.3 KB ID:	308395

                          Worth noting that if you want to turn this off completely you can simply set K_NOISE_CFG to 0.

                          Click image for larger version  Name:	Screenshot 2025-06-13 at 4.43.40 PM.png Views:	0 Size:	11.1 KB ID:	308396


                          Click image for larger version  Name:	Screenshot 2025-06-13 at 4.44.12 PM.png Views:	0 Size:	176.4 KB ID:	308397

                          Other notes:
                          - If you set bit 0 of K_NOISE_CFG to 1 you can make the car use the VANOS noise tables.
                          Last edited by karter16; 06-12-2025, 09:02 PM.
                          2005 ///M3 SMG Coupe Silbergrau Metallic/CSL bucket seats/CSL airbox/CSL console/6 point RACP brace
                          Build Thread:
                          https://nam3forum.com/forums/forum/m...e46-m3-journal

                          Comment


                            You mean I’ve only had 80% torque in first gear this whole time?! Ha

                            punched this in to ChatGPT for fun. It immediately figured out this is a noise management routine for a car

                            START noise_st_calc
                            |
                            |-- Is speed in mid range AND correct gear selected AND motor is active?
                            | |
                            | |-- YES --> Add time since last check to "valid condition timer"
                            | |
                            | |-- NO -->
                            | |
                            | |-- Is speed out of bounds OR wrong gear AND noise mode is not active?
                            | |
                            | |-- YES --> Reset "valid condition timer" to 0
                            |
                            |-- Is:
                            | - throttle/power demand high enough
                            | - speed in valid range
                            | - correct gear selected
                            | - "valid condition timer" exceeds required threshold?
                            | |
                            | |-- YES --> Set noise mode to ACTIVE (set high bit)
                            |
                            |-- Is:
                            | - noise mode currently ACTIVE
                            | AND
                            | - throttle is too low OR wrong gear selected OR speed out of acceptable range?
                            | |
                            | |-- YES --> Deactivate noise mode (clear high bit) AND reset timer
                            |
                            |-- Save current system time as "last checked time"
                            |
                            |-- Is noise mode INACTIVE OR noise feature is DISABLED in configuration?
                            | |
                            | |-- YES --> Clear low bits (0 and 1) of noise state
                            |
                            | |-- NO --> Noise is ACTIVE AND config is enabled:
                            | |
                            | |-- Is "mode bit 0" enabled in config?
                            | | |
                            | | |-- YES --> Set bit 0 in noise state
                            | |
                            | |-- Is "mode bit 1" enabled in config?
                            | |
                            | |-- YES --> Set bit 1 in noise state AND RETURN
                            |
                            RETURN​
                            Last edited by Bry5on; 06-12-2025, 09:43 PM.
                            ‘02 332iT / 6 | ‘70 Jaguar XJ6 electric conversion

                            Comment


                              Originally posted by Bry5on View Post
                              You mean I’ve only had 80% torque in first gear this whole time?! Ha
                              My E60 M5 6spd did the same thing, ign based torque management, I disabled it and it turned my description of the car from “quite civil” to a “burnout machine”…
                              E46 ///M3 • 12/2002 • phönix-gelb • 6MT
                              E39 ///M5 • 12/1998 • avus-blau • 6MT
                              E60 ///M5 • 11/2006 • saphir-schwarz • 6MT

                              Comment


                                Well I’m definitely going to be disabling this now that modern tires are grippier. That’s an extra 50ft-lbs in first gear! Here we go.

                                Also, this would be a cool thing to have enabled/disabled based on sport mode. Wonder why they didn’t do that.
                                ‘02 332iT / 6 | ‘70 Jaguar XJ6 electric conversion

                                Comment

                                Working...
                                X