How to update another byte of a CAN message while changing a byte in real-time? - can-bus

I'm new to CANoe and CAPL scripting. I need to update a byte of CAN message based on a change in another byte through a panel. I added a CAPL script for the automatic change/update but when I send/update the byte through the panel it sends the default values for the other bytes. It gets corrected in the next sample.
includes
{
}
variables
{
message M2P_0x101 msg1;
msTimer timer10ms;
byte counter = 1;
}
on message M2P_0x101
{
if(counterAlive == 15)
{
counterAlive = 0;
}
else
{
counter++;
}
msg1.byte(0) = this.byte(0);
msg1.byte(1) = this.byte(1);
msg1.byte(2) = this.byte(2);
msg1.byte(3) = this.byte(3); // Changing through the Panel
msg1.byte(4) = this.byte(3)+1;
msg1.byte(5) = this.byte(5);
msg1.byte(6) = counter;
msg1.byte(7) = this.byte(7);
}
on timer timer10ms
{
output(msg1);
}
on start
{
setTimerCyclic(timer10ms, 10);
}
4th & 6th byte has default value because 3rd byte was changed from the panel.
I expected the 4th byte to be 1(value of 3rd byte + 1) and the 6th byte to be 4(counter value).
How to solve it? As far as I understand, it seems that the panel inputs/changes are sent to the CAN bus first and then CAPL node reads it and makes changes. This could be the reason for overwriting the other bytes of the message with default values.
Is there a way to include the changes made by CAPL before the panel sends the message to the CAN bus? A combination of Panel & CAPL node?

Related

writing to flash memory dspic33e

I have some questions regarding the flash memory with a dspic33ep512mu810.
I'm aware of how it should be done:
set all the register for address, latches, etc. Then do the sequence to start the write procedure or call the builtins function.
But I find that there is some small difference between what I'm experiencing and what is in the DOC.
when writing the flash in WORD mode. In the DOC it is pretty straightforward. Following is the example code in the DOC
int varWord1L = 0xXXXX;
int varWord1H = 0x00XX;
int varWord2L = 0xXXXX;
int varWord2H = 0x00XX;
int TargetWriteAddressL; // bits<15:0>
int TargetWriteAddressH; // bits<22:16>
NVMCON = 0x4001; // Set WREN and word program mode
TBLPAG = 0xFA; // write latch upper address
NVMADR = TargetWriteAddressL; // set target write address
NVMADRU = TargetWriteAddressH;
__builtin_tblwtl(0,varWord1L); // load write latches
__builtin_tblwth(0,varWord1H);
__builtin_tblwtl(0x2,varWord2L);
__builtin_tblwth(0x2,varWord2H);
__builtin_disi(5); // Disable interrupts for NVM unlock sequence
__builtin_write_NVM(); // initiate write
while(NVMCONbits.WR == 1);
But that code doesn't work depending on the address where I want to write. I found a fix to write one WORD but I can't write 2 WORD where I want. I store everything in the aux memory so the upper address(NVMADRU) is always 0x7F for me. The NVMADR is the address I can change. What I'm seeing is that if the address where I want to write modulo 4 is not 0 then I have to put my value in the 2 last latches, otherwise I have to put the value in the first latches.
If address modulo 4 is not zero, it doesn't work like the doc code(above). The value that will be at the address will be what is in the second set of latches.
I fixed it for writing only one word at a time like this:
if(Address % 4)
{
__builtin_tblwtl(0, 0xFFFF);
__builtin_tblwth(0, 0x00FF);
__builtin_tblwtl(2, ValueL);
__builtin_tblwth(2, ValueH);
}
else
{
__builtin_tblwtl(0, ValueL);
__builtin_tblwth(0, ValueH);
__builtin_tblwtl(2, 0xFFFF);
__builtin_tblwth(2, 0x00FF);
}
I want to know why I'm seeing this behavior?
2)I also want to write a full row.
That also doesn't seem to work for me and I don't know why because I'm doing what is in the DOC.
I tried a simple write row code and at the end I just read back the first 3 or 4 element that I wrote to see if it works:
NVMCON = 0x4002; //set for row programming
TBLPAG = 0x00FA; //set address for the write latches
NVMADRU = 0x007F; //upper address of the aux memory
NVMADR = 0xE7FA;
int latchoffset;
latchoffset = 0;
__builtin_tblwtl(latchoffset, 0);
__builtin_tblwth(latchoffset, 0); //current = 0, available = 1
latchoffset+=2;
__builtin_tblwtl(latchoffset, 1);
__builtin_tblwth(latchoffset, 1); //current = 0, available = 1
latchoffset+=2;
.
. all the way to 127(I know I could have done it in a loop)
.
__builtin_tblwtl(latchoffset, 127);
__builtin_tblwth(latchoffset, 127);
INTCON2bits.GIE = 0; //stop interrupt
__builtin_write_NVM();
while(NVMCONbits.WR == 1);
INTCON2bits.GIE = 1; //start interrupt
int testaddress;
testaddress = 0xE7FA;
status = NVMemReadIntH(testaddress);
status = NVMemReadIntL(testaddress);
testaddress += 2;
status = NVMemReadIntH(testaddress);
status = NVMemReadIntL(testaddress);
testaddress += 2;
status = NVMemReadIntH(testaddress);
status = NVMemReadIntL(testaddress);
testaddress += 2;
status = NVMemReadIntH(testaddress);
status = NVMemReadIntL(testaddress);
What I see is that the value that is stored in the address 0xE7FA is 125, in 0xE7FC is 126 and in 0xE7FE is 127. And the rest are all 0xFFFF.
Why is it taking only the last 3 latches and write them in the first 3 address?
Thanks in advance for your help people.
The dsPIC33 program memory space is treated as 24 bits wide, it is
more appropriate to think of each address of the program memory as a
lower and upper word, with the upper byte of the upper word being
unimplemented
(dsPIC33EPXXX datasheet)
There is a phantom byte every two program words.
Your code
if(Address % 4)
{
__builtin_tblwtl(0, 0xFFFF);
__builtin_tblwth(0, 0x00FF);
__builtin_tblwtl(2, ValueL);
__builtin_tblwth(2, ValueH);
}
else
{
__builtin_tblwtl(0, ValueL);
__builtin_tblwth(0, ValueH);
__builtin_tblwtl(2, 0xFFFF);
__builtin_tblwth(2, 0x00FF);
}
...will be fine for writing a bootloader if generating values from a valid Intel HEX file, but doesn't make it simple for storing data structures because the phantom byte is not taken into account.
If you create a uint32_t variable and look at the compiled HEX file, you'll notice that it in fact uses up the least significant words of two 24-bit program words. I.e. the 32-bit value is placed into a 64-bit range but only 48-bits out of the 64-bits are programmable, the others are phantom bytes (or zeros). Leaving three bytes per address modulo of 4 that are actually programmable.
What I tend to do if writing data is to keep everything 32-bit aligned and do the same as the compiler does.
Writing:
UINT32 value = ....;
:
__builtin_tblwtl(0, value.word.word_L); // least significant word of 32-bit value placed here
__builtin_tblwth(0, 0x00); // phantom byte + unused byte
__builtin_tblwtl(2, value.word.word_H); // most significant word of 32-bit value placed here
__builtin_tblwth(2, 0x00); // phantom byte + unused byte
Reading:
UINT32 *value
:
value->word.word_L = __builtin_tblrdl(offset);
value->word.word_H = __builtin_tblrdl(offset+2);
UINT32 structure:
typedef union _UINT32 {
uint32_t val32;
struct {
uint16_t word_L;
uint16_t word_H;
} word;
uint8_t bytes[4];
} UINT32;

CAN message signals, CAPL

I am trying to save the signal data in the each my of a CAN message in separate variables.
For eg. I have a CAN message 'msg1' of dlc =4, with signals {8, 5, 7, 21} in CANalyzer's CAPL,
I would like to save them in variables like:
int var1 = msg1.byte(0);
but I keep getting zero (0) as the final value of the variable after the operation.
Any help is much appreciated.
Thanks
If you are not doing this already, implement an on message event using the keyword this:
on message msg1 {
var1 = this.byte(0);
...
}
The event will always be triggered when CANalyzer receives the message specified in the on message event. This way you can also make sure that the value stored by var1 is up to date.
You can also use a more general approach using arrays.
on message msg1 {
int i;
int var[msg1.dlc];
for (i = 0; i < msg1.dlc; i++) {
var[i] = this.byte(i);
}
}

CAPL Script for Diagnostic Services

I am writing the CAPL script to Automise the Diagnostic services. I have read some DIDs which are bigger than 8 bytes in size. Till 8 bytes I can capture correctly the data in my CAPL script but when the data size exceeds the 8 bytes, then I get some garbage values 00 for remaining bytes.
The complete read data I can see in CANoe Trace but I am not able to capture it in my CAPL script. If someone has any ideas or solution, please share with me.
In Belo script, the issue is that I can capture value till this.byte(7) correctly. But for this.byte(8) and this.byte(9) I read 00 although the actual value in CANoe Trace is 0x54 and 0x66. So it means I cannot read more than 8 bytes in CAPL from CAN.
My script looks like:
variables
{
//Please insert your code below this comment
byte test_num;
message DTOOL_to_UPA msg_tester;
mstimer readTimerDID_2001;
mstimer defaultSession;
byte readBuf2001[8];
}
// read request
on key 'd'
{
test_num = 0;
msg_tester.dlc = 8;
msg_tester.dir = tx;
msg_tester.can = 1;
settimer(defaultSession, 2000);
}
on timer defaultSession // Request DID: 10 01
{
msg_tester.byte(0) = 0x02;
msg_tester.byte(1) = 0x10;
msg_tester.byte(2) = 0x01;
output(msg_tester);
settimer(readTimerDID_2001, 100);
canceltimer(defaultSession);
}
on timer readTimerDID_2001 // Read Request DID: 22 20 01
{
msg_tester.byte(0) = 0x03;
msg_tester.byte(1) = 0x22;
msg_tester.byte(2) = 0x20;
msg_tester.byte(3) = 0x01;
output(msg_tester);
canceltimer(readTimerDID_2001);
}
on message UPA_to_DTOOL
{
if (this.DIR == RX)
{
// Response Data for DID 2001
if (
(this.byte(0)== 0x04)&&(this.byte(1)== 0x62)&&(this.byte(2)==0x20)&&
(this.byte(3)== 0x01)&&(this.byte(4)== 0x23) &&(this.byte(5)== 0x00)&&
(this.byte(6)== 0x44)&&(this.byte(7)== 0x22) &&(this.byte(8)==0x54)&&
(this.byte(9)== 0x66)
)
{
readDID2001();
}
}
}
on message UPA_to_DTOOL
is reacting on the CAN message UPA_to_DTOOL, and this you can only access the 8 bytes of the CAN message.
If you want to react on diagnostic messages you should use
on diagResponse <serviceName>
inside of this handler you can then access the complete data of the diagnostic message
I had a similar problem accessing j1939 PGN with data length code (DLC) > 8 byte. These messages were transmitted as a j1939 Frame (DLC > 8 byte) instead of a CAN frame (DLC = 8 byte) in the trace window. I had to make use of the getThisMessage(pg pg_variable, int length) function in an on pg event like this.
on pg UPA_to_DTOOL {
pg UPA_to_DTOOL UPA_to_DTOOL_pg;
getThisMessage(UPA_to_DTOOL, UPA_to_DTOOL.dlc);
write("byte 9 = %X", UPA_to_DTOOL.byte(9));
}
Because messages with DLC > 8 are transmitted in a special way, the getThisMessage had to be used in my case, which let me access all the message bytes. I am not sure this solution for j1939 PGNs helps you because I do not know whether you have a license for j1939 in your canoe installation.

Can't save to Flash Memory?

I am using the following library <flash.h> to Erase/Write/Read from memory but unfortunately the data I am trying to save doesn't seem to be written to flash memory. I am using PIC18F87j11 with MPLAB XC8 compiler. Also when I read the program memory from PIC after attempting to write to it, there is no data on address 0x1C0CA. What am I doing wrong?
char read[1];
/* set FOSC clock to 8MHZ */
OSCCON = 0b01110000;
/* turn off 4x PLL */
OSCTUNE = 0x00;
TRISDbits.TRISD6 = 0; // set as ouput
TRISDbits.TRISD7 = 0; // set as ouput
LATDbits.LATD6 = 0; // LED 1 OFF
LATDbits.LATD7 = 1; // LED 2 ON
EraseFlash(0x1C0CA, 0x1C0CA);
WriteBytesFlash(0x1C0CA, 1, 0x01);
ReadFlash(0x1C0CA, 1, read[0]);
if (read[0] == 0x01)
LATDbits.LATD6 = 1; // LED 1 ON
while (1) {
}
I don't know what WriteFlashBytes does but the page size for your device is 64 bytes and after writing you need to write an ulock sequence to EECON2 and EECON1 registers to start programming the flash memory

insert numerical sequence in large text file

I need to create a file in this format :
item0000001
item0000002
item0000003
item0000004
item0000005
I was doing this with UltraEdit which has column mode including insert number ( start + increment including leading zeros ).
Unfortunately, UltraEdit bombs out above 1 million rows.
Does anyone know of a text editor with large file capacity that has a similar operation?
BaltoStar has not written which version of UltraEdit was used and how exactly he has tried to create the file.
However, here is an UltraEdit script which can be used to create a file with lines containing an incrementing number with leading zeros according to last number.
To use that script with UltraEdit v14.20 or UEStudio v9.00 or any later version, copy the code block of the script and paste it into a new ASCII file with DOS line terminations in UltraEdit/UEStudio. Save the file for example as CreateLinesWithIncrementingNumber.js into your preferred directory of UE/UES scripts.
Now run the script by clicking on menu item Run Active Script in menu Scripting.
The script prompts the user for first and last value of the incrementing number, and for strings left and right of the incrementing number which can be both also empty strings.
Then lean back and see how the script writes the lines with the incrementing number into a new file in blocks. I created a file with more than 150 MB with an incrementing number from 0 to 5.000.000 within a few seconds using this UltraEdit script.
if (typeof(UltraEdit.clipboardContent) == "string")
{
// Write in blocks of not more than 4 MB into the file. Do not increase
// this value too much as during the script execution much more free
// RAM in a continous block is necessary than the value used here for
// joining the lines in user clipboard 9. A too large value results
// in a memory exception during script execution and the user of the
// script also does not see for several seconds what is going on.
var nBlockSize = 4194304;
// Create a new file and make sure it uses DOS/Windows line terminations
// independent on the user configuration for line endings of new files.
UltraEdit.newFile();
UltraEdit.activeDocument.unixMacToDos();
var sLineTerm = "\r\n"; // Type of line termination is DOS/Windows.
// Ask user of script for the first value to write into the file.
do
{
var nFirstNumber = UltraEdit.getValue("Please enter first value of incrementing number:",1);
if (nFirstNumber < 0)
{
UltraEdit.messageBox("Sorry, but first value cannot be negative.");
}
}
while (nFirstNumber < 0);
// Ask user of script for the last value to write into the file.
do
{
var nLastNumber = UltraEdit.getValue("Please enter last value of incrementing number:",1);
if (nFirstNumber >= nLastNumber)
{
UltraEdit.messageBox("Sorry, but last value must be greater than "+nFirstNumber.toString(10)+".");
}
}
while (nFirstNumber >= nLastNumber);
var sBeforeNumber = UltraEdit.getString("Please enter string left of the incrementing number:",1);
var sAfterNumber = UltraEdit.getString("Please enter string right of the incrementing number:",1);
// http://stackoverflow.com/questions/16378849/ultraedit-how-do-i-pad-out-a-string-with-leading-blanks
// Convert the highest number to a decimal string and get a copy
// of this string with every character replaced by character '0'.
// With last number being 39428 the created string is "00000".
var sLeadingZeros = nLastNumber.toString(10).replace(/./g,"0");
// Instead of writing the string with the incrementing number line
// by line to file which would be very slow and which would create
// lots of undo records, the lines are collected first in an array of
// strings whereby the number of strings in the array is determined
// by value of variable nBlockSize. The lines in the array are
// concatenated into user clipboard 9 and written as block to the
// file using paste command. That is much faster and produces just
// a few undo records even on very large files.
UltraEdit.selectClipboard(9);
UltraEdit.clearClipboard();
// Calculate number of lines per block which depends on the
// lengths of the 4 strings which build a line in the file.
var nLineLength = sBeforeNumber.length + sLeadingZeros.length +
sAfterNumber.length + sLineTerm.length;
var nRemainder = nBlockSize % nLineLength;
var nLinesPerBlock = (nBlockSize - nRemainder) / nLineLength;
var asLines = [];
var nCurrentNumber = nFirstNumber;
while (nLastNumber >= nCurrentNumber)
{
// Convert integer number to decimal string.
var sNumber = nCurrentNumber.toString(10);
// Has the decimal string of the current number less
// characters than the decimal string of the last number?
if (sNumber.length < sLeadingZeros.length)
{
// Build decimal string new with X zeros from the alignment string
// and concatenate this leading zero string with the number string.
sNumber = sLeadingZeros.substr(0,sLeadingZeros.length-sNumber.length) + sNumber;
}
asLines.push(sBeforeNumber + sNumber + sAfterNumber);
if (asLines.length >= nLinesPerBlock)
{
asLines.push(""); // Results in a line termination at block end.
UltraEdit.clipboardContent = asLines.join(sLineTerm);
UltraEdit.activeDocument.paste();
UltraEdit.clearClipboard();
asLines = [];
}
nCurrentNumber++;
}
// Output also the last block.
if (asLines.length)
{
asLines.push("");
UltraEdit.clipboardContent = asLines.join(sLineTerm);
UltraEdit.activeDocument.paste();
UltraEdit.clearClipboard();
}
// Reselect the system clipboard and move caret to top of new file.
UltraEdit.selectClipboard(0);
UltraEdit.activeDocument.top();
}
else if(UltraEdit.messageBox)
{
UltraEdit.messageBox("Sorry, but you need a newer version of UltraEdit/UEStudio for this script.");
}
else
{
UltraEdit.newFile();
UltraEdit.activeDocument.write("Sorry, but you need a newer version of UltraEdit/UEStudio for this script.");
}

Resources