stevech
Joined: 23 Feb 2006
|
|
Posted: 09 October 2006, 4:37 AM Post subject: Hack to preserve date/time across a reset of the ZBasic VM |
|
|
This code preserves the date and time within the ZBasic VM operating system across a reset or re-download of a a new program. Often, the chip gets reset by DTR toggling merely due to opening a serial port on the PC to see the console output.
The time it took to reset (a second or two, or the time to dowload (a few seconds), is lost, but this is better than nothing! A clock chip would be nice too, but nada. The code won't deal with a power-off/on of course, and you can make a choice on not retrieving date/time from RAM based on the system register for "cause of reset".
This code is a bit of a hack. It saves the date/time to RAM once a second (you can change that rate), in an area of RAM unlikely to be erased during the reset. This could change due to VM changes, but for now, it works. This RAM area is at a higher address than the maximum expected address for the main() tasks's stack, and lower than the heap is expected to go. With the larger RAM on the AVR 644 chip as is the ZX24a et al, this is less of a risk.
In another posting here today, I showed a program to set the date/time in the VM by parsing out incoming serial data created by a MS Windows command line echo date time command.
Don may have a suggestion on a tweak. This is my first attempt at based variables so beware.
It would be kinda nice to have a compiler option to set the base address of static variables to something above 0, so this secret stash area could be assuredly preserved.
Here's the code to put in the heading and in main()
| Code: |
const RAMstashOffset as unsignedInteger = 300 ' offset from stack pointer of main() to unused RAM we hope
private saveDateTimeToRAMstack(40) as byte
...
main()
...
userSPmain = register.userSP ' save in a global
callTask saveDateTimeToRAM, saveDateTimeToRAMstack
sub saveDateTimeToRAM() ' a task
Dim RAMaddr as UnsignedInteger
Dim mm as byte Based (RAMaddr+0)
Dim d as byte Based (mm.dataAddress+sizeof(byte))
Dim y as integer Based (d.dataAddress+sizeof(byte))
Dim h as byte Based (y.dataAddress+sizeof(integer))
Dim m as byte Based (h.dataAddress+sizeof(byte))
Dim secs as single Based (m.dataAddress+sizeof(byte))
RAMaddr = userSPmain + RAMstashOffset
'debug.print "RAMaddr:";cstr(RAMaddr);" secs addr ";cstr(secs.dataAddress)
call PutTimeStamp(y, mm, d, h, m, secs) ' set the date/time from what was saved
console.writeline( "date/time recalled from RAM")
do
call getTimeStamp(y, mm, d, h, m, secs) ' put time into RAM storage
sleep(1.0)
loop
end sub |
|
|
dkinzer Site Admin
Joined: 03 Sep 2005
Location: Portland, OR
|
|
Posted: 09 October 2006, 4:54 AM Post subject: |
|
|
Using a structure might simplify the code:
| Code: | sub saveDateTimeToRAM() ' a task
Structure TimeDate
Dim mm as Byte
Dim d as Byte
Dim y as Integer
Dim h as Byte
Dim m as Byte
Dim secs as Single
End Structure
Dim RAMaddr as UnsignedInteger
Dim td as TimeDate Based (RAMaddr+0)
RAMaddr = userSPmain + RAMstashOffset
'debug.print "RAMaddr:";cstr(RAMaddr);" secs addr ";cstr(secs.dataAddress)
call PutTimeStamp(td.y, td.mm, td.d, td.h, td.m, td.secs) ' set the date/time from what was saved
console.writeline( "date/time recalled from RAM")
do
call getTimeStamp(td.y, td.mm, td.d, td.h, td.m, td.secs) ' put time into RAM storage
sleep(1.0)
loop
end sub |
|
|