I recently had cause to write a fairly substantial SPLat program for a customer who had ordered a custom SPLat design. (We usually try and persuade our customers to write their own programs, but this was a special case with a custom controller and a tight deadline, so I let my arm be twisted.)
The program (and controller) is for high speed shutter door operation, and requires a number of operating parameters to be set up by installation technicians using the built in LCD display. There are two key features required for this kind of menu driven setup. The setup data must be stored in a non-volatile memory, and (ideally) it should be possible to cancel out of the setup without having actually changed the value (in case the user changes their mind).
The newly introduced shadow memory achieves this very simply. Shadow memory is a non-volatile memory that "shadows" all 128 bytes (at time of writing) of user RAM. It can be written and read in any block size from 1 byte up to the full 128 bytes. To store a particular block of RAM in non-volatile memory you just use its RAM address and block length in a ShadowWrite instruction. To restore it you use the same parameters in a ShadowRead instruction.
In the setup menus I wrote for the door control I simply let the user go through the moves, changing the setup value and altering it in RAM. If the user completes the process with the "OK" button to accept the changes, I do a ShadowWrite. If the user ends up with the Cancel button, I instead do a ShadowRead to restore the original value from shadow memory. When the program first starts up, its initialization code ShadowReads all the setup parameters.
This strategy will work only if setup mode is quite distinct from operating mode. If setup changes must be done while the program is also operating, there is a risk that a weird setup value could be used in operation. That was the case with a milk storage and chilling system I did a year or so ago. System configuration, say cycle times, can be changed while the system is operating. In that case I had to use temporary memory locations to hold the parameter being changed, and only write it to the "real" variable when the user accepted the changes. What this shows, of course, is that you have to understand the application and how the controller is going to be used, then make sure you devise or select a strategy that will meet the needs. There is no universal solution!