I've written code for PIC16F1947 in C. I am using the following:
A part of the code deals with data coming from PC. The specific packet I'm sending from PC is 325 bytes. This packet looks as follows:
data: 0, 64, 1, 0, 255, 255, 255, ... (all 255) ..., 255, 1
index: 0 1 2 3 4 5 6 323 324
The contents of the packet are shown as 8 bit decimal value (8 bit unsigned integer). The micro stores it in an array of unsigned char
:
unsigned char _command_mgr_buff[330];
unsigned char
is the 8 bit unsigned integer for PIC16F.
The last byte of the packet, ie index 324, is the checksum of the packet. It is the summation of index 1 through 323, including 1 and 323. The PC code (in C#) that calculates this checksum is as follows:
allCertPages[324] = 0;
for (int i = 1; i <= 323; i++)
{
allCertPages[324] += allCertPages[i];
}
allCertPages
is a byte[]
.
The micro must verify that the checksum is indeed the value passed from PC. Here is the verification code that I've written for PIC16F, including some debug information:
param0 = _command_mgr_buff[324]; // param0 is unsigned int, 16 bit
param1 = _command_mgr_buff[324]; // param1 is unsigned int, 16 bit
// Checksum verification
for (var = 1; var <= 323; var++) // var is unsigned int, 16 bit
{
_command_mgr_buff[324] -= _command_mgr_buff[var];
param1 -= _command_mgr_buff[var];
}
if (!_command_mgr_buff[324])
{
send_status(CS_BAD_PARAM);
}
The idea is to subtract all values within the range [1, 323] from the checksum. If the final value is 0, then checksum is correct. Otherwise, if _command_mgr_buff[324]
is found non-zero after subtraction, then the checksum is incorrect.
After executing the code in debug mode (and also in release mode), I'm getting non-zero value in _command_mgr_buff[324]
(so send_status(CS_BAD_PARAM);
gets executed and the PC thinks something is wrong), but zero in the lower byte of param1
!
How is that possible?!
In case you're interested, here is the assembly generated for the non-zero checking:
8780 ;mgr_command.c: 1230: if (!_command_mgr_buff[324])
8781 0E89 30EA movlw low(8870+0144h)
8782 0E8A 00D3 movwf (??_command_mgr_run+0)^080h+0
8783 0E8B 3023 movlw high(8870+0144h)
8784 0E8C 00D4 movwf (??_command_mgr_run+0)^080h+0+1
8785 0E8D 0853 movf 0+(??_command_mgr_run+0)^080h+0,w
8786 0E8E 0086 movwf fsr1l
8787 0E8F 0854 movf 1+(??_command_mgr_run+0)^080h+0,w
8788 0E90 0087 movwf fsr1h
8789
8790 0E91 0881 movf indf1,f
8791 0E92 1D03 skipz
8792 0E93 2E95 goto u10101
8793 0E94 2E96 goto u10100
8794 0E95 u10101:
8795 0E95 2E9B goto l55070
8796 0E96 u10100:
8797 line 1232
8798
8799 0E96 l55068:
8800 ;mgr_command.c: 1231: {
8801 ;mgr_command.c: 1232: send_status(0x11);
8802 0E96 3011 movlw (011h)
8803 0E97 31B6 2693 3188 fcall _send_status
8804 line 1233
8805 ;mgr_command.c: 1233: }
8806 0E9A 2FE3 goto l45048
8807 line 1234
Here is a screenshot taken during debugging. Please check the Watch window in the right and the tooltip for 324-th element.
param0
should be 1param1 & 0xFF
should be 0_command_mgr_buff[324]
should be 0 (tooltip shows 0x0F??!!)If your code is as you say, the main problem here is your test itself:
if (!_command_mgr_buff[324])
{
send_status(CS_BAD_PARAM);
}
You're sending the signal if the result is what you want (namely zero)...
This is one of the reasons why I don't like boolean testing of non-boolean values. Boolean variables often have names that cue you into reading the condition they capture correctly, like if (isLoaded)
or if (!anyErrors)
...and that doesn't hold for numerics. So it's easier to make sure you've got the semantics you want to just write it out:
if (_command_mgr_buff[324] != 0)
{
send_status(CS_BAD_PARAM);
}
As for why your debugger is giving you the 0x0F...can't help you there...my point just being that you're in the zero branch. You might try a clean build and see if it still says that. (The program's debug symbols could be out of date or something?)