Crc16 on power failure

M

maxthebaz

Our machines have this requirement: if power failure occurs, many
important variables are to be resumed from where they were interrupted
after the machine is restarted (power on in this case). In other words,
the basic idea is to keep a snapshot of the state machine before it is
interrupted.
The board is provided with:
- a 32-bit H8S/2633 Hitachi microprocessor;
- a battery-backed memory (BBM), where these variables are stored; BBM
area involved is about 16 Kbytes (the whole BBM has a 128KB capability)
- 2 big capacitors; if a blackout occurs, they guarantee a 400 msec
(Tsave) extra power supply time.
When power supply is going to fall down, a function is invoked by power
failure NMI. This function, within Tsave time, has to perform the
following main operations:
- it calculates CRC16 checksum for the BBM variable area (for our 16KB,
this requires a long time: 90 msec!).
- it saves the CRC16 checksum in BBM (of course, in a different BBM
address from the previous variable area).
Then, when machine is re-started, a new checksum of the interested BBM
area is performed: the result is compared with the previous stored one.
If they differ, a BBM corruption is assumed (error detection).

Now I am seeking a better solution: the target is to reduce the 2 big
capacitors, i.e. to reduce Tsave time. The reason is to save space (and
money) by reducing them. I'm looking for a way to anticipate CRC16
calculation in a safe and fast way, before power failure.
One solution could be a CRC16 computation invoked at every time a BBM
variable is changed, but this operation needs 90 msec (as I wrote
before), while main loop now is about 10 msec. That's why this solution
is not applicable at all.

Note: because of our application, I can't consider solutions like
saving every second, i.e. loosing "only" last second changes.

Thank you very much.
 
B

Ben Pfaff

Our machines have this requirement: if power failure occurs, many
important variables are to be resumed from where they were interrupted
after the machine is restarted (power on in this case). In other words,
the basic idea is to keep a snapshot of the state machine before it is
interrupted.

You didn't state a question about the C programming language
anywhere, so I'm going to suggest that further followups should
go only to comp.arch.embedded.
 
D

Didi

- it calculates CRC16 checksum for the BBM variable area (for our 16KB,
this requires a long time: 90 msec!).

I don't know the CPU you are using, but apr. 10 uS per 16 bits sounds
like
there may be room for improvement just of the code (using that now
widely
popular algorithm which includes table lookup etc., you can find it in
the one of the PPP related RFC-s, I _think_ it was described in
sufficient detail either in rfc1661 or in rfc1662. (OK, just checked,
it
really is inside RFC1662, not bad for over 2 years not having to deal
with it :).
How fast is the CPU you are using (I mean clock frequency)?

Another possibility might be to split the 16K in several pieces and
calculate the CRC only for the piece which has been modified, if the
nature of the data and the application would allow that.

Dimiter
 
C

Colin Hankins

You need to use a better implementation of the CRC16. Even performing the
calculation one bit at a time you could probably do better than 90ms.
 
D

David T. Ashley

Our machines have this requirement: if power failure occurs, many
important variables are to be resumed from where they were interrupted
after the machine is restarted (power on in this case). In other words,
the basic idea is to keep a snapshot of the state machine before it is
interrupted.
The board is provided with:

Snip.

Please redirect this question to:

comp.arch.embedded
 
H

hagman

Our machines have this requirement: if power failure occurs, many
important variables are to be resumed from where they were interrupted
after the machine is restarted (power on in this case). In other words,
the basic idea is to keep a snapshot of the state machine before it is
interrupted.
The board is provided with:
- a 32-bit H8S/2633 Hitachi microprocessor;
- a battery-backed memory (BBM), where these variables are stored; BBM
area involved is about 16 Kbytes (the whole BBM has a 128KB capability)
- 2 big capacitors; if a blackout occurs, they guarantee a 400 msec
(Tsave) extra power supply time.

I assume that some higher-level transaction/rollback system is
implemented as well
in your data structure?
When power supply is going to fall down, a function is invoked by power
failure NMI. This function, within Tsave time, has to perform the
following main operations:
- it calculates CRC16 checksum for the BBM variable area (for our 16KB,
this requires a long time: 90 msec!).

There are specialized CRC chips. Might this help?
I assume that BBM is somewhat slow in access.
How much of the 90ms is pure reading time?
- it saves the CRC16 checksum in BBM (of course, in a different BBM
address from the previous variable area).
Then, when machine is re-started, a new checksum of the interested BBM
area is performed: the result is compared with the previous stored one.
If they differ, a BBM corruption is assumed (error detection).

Now I am seeking a better solution: the target is to reduce the 2 big
capacitors, i.e. to reduce Tsave time. The reason is to save space (and
money) by reducing them. I'm looking for a way to anticipate CRC16
calculation in a safe and fast way, before power failure.
One solution could be a CRC16 computation invoked at every time a BBM
variable is changed, but this operation needs 90 msec (as I wrote
before), while main loop now is about 10 msec. That's why this solution
is not applicable at all.

CRC should be possible incremental.
If you change Byte[k] from OLD to NEW, the CRC should change by
TABLE8[k,OLD] ^ TABLE8[k,NEW]
This requires 256*n words of precalculated tables for n bytes of
memory,
so here it's 8MB, which might be too much.

Here's a slower but less memory demanding idea of mine (n words, i.e.
32KB):

// the battery-backed-memory.
// 1) byte array for the main variables
byte BBMbyte[BBM_ByteCount];
// 2) the saved checksum
uint16 BBM_CRC;

// precalculated table of influence of lowest bit at index
const uint16 TABLE1[BBM_ByteCount] = { .... };

// for protection against NMI during SetBBMByte
int global_index;
uint16 global_CRC;
byte global_NEW;
bool global_dirty;

void SetBBMByte(int index, byte NEW)
{
byte OLD = BBMbyte[index];
if (OLD==NEW) return;

unsigned int crc = global_CRC;

int pat = TABLE1[index];
int changes = NEW ^ OLD;
for (int i=0; i<8; ++i)
if (changes & (1<<i))
crc ^= pat<<i;

for (int i=7; i>=0; --i)
if (crc & (1<<(16+i)))
crc ^= CRC16POLY << (i+1);

// poor man's critical section, prevent optimizer from changing
anything here
global_index = index;
global_NEW = NEW;
global_dirty = true;
global_CRC = crc;
BBMbyte[index] = NEW;
BBM_CRC = crc;
global_dirty = false;
}

void NMIfunc()
{
if (global_dirty) {
// NMI during critical section of SetBBMByte
if (global_CRC != BBM_CRC) {
// NMI after "global_CRC = crc", before "BBM_CRC = crc"
BBMbyte[global_index] = global_NEW;
BBM_CRC = global_crc;
global_dirty = false;
} //else SetBBMbyte was totally ignored or completed
}

// additional transaction protection code might be put here

halt_cpu(); // must not return to running process!!
}



You can adapt this to handle words instead of bytes.
However, with the variable names as above, you must have
sizeof(crc) >= sizeof(NEW) +16/sizeof(char)
where the 16 is the 16 from CRC16.

SetBBMByte is much slower than a simple memory access,
but you may halt the cpu almost immediately upon NMI.
Note: because of our application, I can't consider solutions like
saving every second, i.e. loosing "only" last second changes.

A) What is the cost of loosing last second changes?
B) What is the cost of the capacitors?
It sounds like A is much bigger than B, hence keep the capacitors. ;)
 
A

Arlet

Our machines have this requirement: if power failure occurs, many
important variables are to be resumed from where they were interrupted
after the machine is restarted (power on in this case). In other words,
the basic idea is to keep a snapshot of the state machine before it is
interrupted.
The board is provided with:
- a 32-bit H8S/2633 Hitachi microprocessor;
- a battery-backed memory (BBM), where these variables are stored; BBM
area involved is about 16 Kbytes (the whole BBM has a 128KB capability)
- 2 big capacitors; if a blackout occurs, they guarantee a 400 msec
(Tsave) extra power supply time.
When power supply is going to fall down, a function is invoked by power
failure NMI. This function, within Tsave time, has to perform the
following main operations:
- it calculates CRC16 checksum for the BBM variable area (for our 16KB,
this requires a long time: 90 msec!).
- it saves the CRC16 checksum in BBM (of course, in a different BBM
address from the previous variable area).
Then, when machine is re-started, a new checksum of the interested BBM
area is performed: the result is compared with the previous stored one.
If they differ, a BBM corruption is assumed (error detection).

Now I am seeking a better solution: the target is to reduce the 2 big
capacitors, i.e. to reduce Tsave time. The reason is to save space (and
money) by reducing them. I'm looking for a way to anticipate CRC16
calculation in a safe and fast way, before power failure.
One solution could be a CRC16 computation invoked at every time a BBM
variable is changed, but this operation needs 90 msec (as I wrote
before), while main loop now is about 10 msec. That's why this solution
is not applicable at all.

You could divide your total variable area in a number of shorter
blocks, say 512 bytes, or 1KB each, and perform a CRC16 only on the
block where a variable has been updated. Of course, this won't work if
you frequently change many variables throughout the entire memory.

It does have an added advantage of better protection against errors,
and in the case a CRC error is detected in a block you may still be
able to use the other blocks.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,767
Messages
2,569,572
Members
45,045
Latest member
DRCM

Latest Threads

Top