• AVR Freaks

Helpful ReplyHot!PIC24FJ Address Trap issue

Page: 12 > Showing page 1 of 2
Author
jijo.thomas@bytesandnibbles.com
New Member
  • Total Posts : 7
  • Reward points : 0
  • Joined: 2019/06/24 02:21:40
  • Location: 0
  • Status: offline
2019/06/24 21:52:02 (permalink)
0

PIC24FJ Address Trap issue

Dear All,
I am facing an issue with address trap error with following code on PIC24FJ simulator and chip. Could someone help me?
uint8_t* Xor16_H(uint8_t* in1, uint8_t* in2)
{
    uint8_t _result[16];
    uint8_t *result;
    uint8_t i;
    uint8_t Index = (uint8_t)(in2[0] & 0x0F);
    uint8_t p;
    
    for (i = 0; i < 16;)
    {
        p= i;//Index ^ i;
        *(uint16_t*)&_result[p] = (*(uint16_t*)&in1[p]) ^ (*(uint16_t*)&in2[p]); //address trap
         //*(uint8_t*)&result[Index ^ i] = (*(uint8_t*)&in1[Index ^ i]) ^ (*(uint8_t*)&in2[Index ^ i]); //this works fine
        //_result[Index^i] = in1[Index ^ i] ^ in2[Index ^ i]; //this works fine
        i+=2;
    }
    result = (uint8_t*)_result;
    return result;
}

uint8_t* ExtractAuthKey(uint8_t* authkey)
{
    uint8_t _prnd[16];
    uint8_t* prnd;
    memcpy(_prnd,&authkey[16],16);
    authkey = Xor16_H(authkey,_prnd);
    prnd = (uint8_t*)_prnd;
    return prnd;
}

 
I have no clue why it is giving address trap always. Please help me
 
Thanks,
 
 
#1
andersm
Super Member
  • Total Posts : 2605
  • Reward points : 0
  • Joined: 2012/10/07 14:57:44
  • Location: 0
  • Status: offline
Re: PIC24FJ Address Trap issue 2019/06/25 15:40:36 (permalink)
0
1. You're mixing types and pointers and arrays in completely ridiculous ways.
2. Trying to treat bytes as words is a sure way to cause alignment faults.
3. You're also returning pointers to local stack objects.
#2
LdB_ECM
Senior Member
  • Total Posts : 110
  • Reward points : 0
  • Joined: 2019/04/16 22:01:25
  • Location: 0
  • Status: offline
Re: PIC24FJ Address Trap issue 2019/06/25 17:46:28 (permalink)
+1 (1)
You return two local stacks you need to malloc memory if you want to return it.
The memory allocated in a function disappears the moment it exits the function unless it is allocated.
 
However there is no requirement to alloacte any memory all you are trying to do is this
authkey is obviously 32 bytes being 2 16 byte strings
provide an 16 byte buffer and this will do what you want
void ExtractAuthKey (const uint8_t* authkey, uint8_t* result_buffer)
{
   uint16_t* in1 = (uint16_t*)&authkey[0];       // Cast and create ptr1
   uint16_t* in2 = (uint16_t*)&authkey[16];      // Cast and Create ptr2
   uint16_t* result = (uint16_t*)result_buffer;  // Cast and create result pointer
   unsigned i;  
   for (i = 0; i < 4;)                           // Run 4 16 bit xor hash
   {
       result[i] = in1[i] ^ in2[i];              // Return each 16 bit hash to result buffer
   }  
}

So this is the use
uint8_t buffer[16];
ExtractAuthKey(Pointer_To_Your_32Byte_Auth, &buffer[0]);

buffer will contain the result after it executes
 
#3
aschen0866
Super Member
  • Total Posts : 4469
  • Reward points : 0
  • Joined: 2006/01/08 22:18:32
  • Location: San Diego
  • Status: offline
Re: PIC24FJ Address Trap issue 2019/06/25 18:01:41 (permalink)
0
LdB_ECM
void ExtractAuthKey (const uint8_t* authkey, uint8_t* result_buffer)
{
   uint16_t* in1 = (uint16_t*)&authkey[0];       // Cast and create ptr1
   uint16_t* in2 = (uint16_t*)&authkey[16];      // Cast and Create ptr2
   uint16_t* result = (uint16_t*)result_buffer;  // Cast and create result pointer
 ...
}


Unless *authkey and *result_buffer can be guaranteed to have even address, they could be another address trap waiting to happen.
#4
andersm
Super Member
  • Total Posts : 2605
  • Reward points : 0
  • Joined: 2012/10/07 14:57:44
  • Location: 0
  • Status: offline
Re: PIC24FJ Address Trap issue 2019/06/25 18:11:01 (permalink)
0
That is cleaner, but doesn't solve the alignment issue. The caller must guarantee that all the arrays are aligned to a word boundary, or the code will trap. If the arrays contain 16-bit words, it is much easier to just use the correct data types from the start, rather than pretend they're something else.
#5
LdB_ECM
Senior Member
  • Total Posts : 110
  • Reward points : 0
  • Joined: 2019/04/16 22:01:25
  • Location: 0
  • Status: offline
Re: PIC24FJ Address Trap issue 2019/06/25 19:09:14 (permalink)
0
I only started on the PIC 16 bit processors for 1 little job after years on 32 micros so bear with me here because I haven't had an issue up todate and what you said stuns me. I assumed like most ARM riscs that all natural allocations will be on 2 byte boundaries to match the 16bit processor because usually riscs hate manhandling byte alignments.
 
On an ARM you would have to go out of your way to get a byte aligned array it is dam difficult and I have coded that way on the PIC24F without issue, so was shocked at your response.
 
So lets cover the three situations and confirm I am expecting
1.) Malloc ... I am assuming that anything it gives you back will be 2 byte boundary. I can't imagine they would be silly enough to not 2 byte align the heap.
2.) Local variable
void func (void)
    uint8_t a;    // this should be 2 byte aligned
    uint8_t b;   // this should be two byte aligned the stack will pad the extra byte
3.) Global variable
 uint8_t a;    // this should be 2 byte aligned
 uint8_t b;   // this should be two byte aligned the data will have a hole with the extra byte
 
So this comes back to the crux of my question how do you create a non aligned array of uint8_t, uint16_t or anything?
I am excluding some dodgy pointer operation setting an odd address, you can do that on any CPU.
I am after any allocation that wont be on a 16bit aligned address on a PIC24F because those are the ones that will gotcha me on my coding.
post edited by LdB_ECM - 2019/06/25 19:11:44
#6
jijo.thomas@bytesandnibbles.com
New Member
  • Total Posts : 7
  • Reward points : 0
  • Joined: 2019/06/24 02:21:40
  • Location: 0
  • Status: offline
Re: PIC24FJ Address Trap issue 2019/06/25 21:26:16 (permalink)
0
Thank you. Can you give me the example with malloc so that i can return uint8_t*
#7
ric
Super Member
  • Total Posts : 22768
  • Reward points : 0
  • Joined: 2003/11/07 12:41:26
  • Location: Australia, Melbourne
  • Status: online
Re: PIC24FJ Address Trap issue 2019/06/25 21:31:49 (permalink)
0
jijo.thomas@bytesandnibbles.com
Thank you. Can you give me the example with malloc so that i can return uint8_t*

I see you are determined to do this the worst way possible.
 

I also post at: PicForum
Links to useful PIC information: http://picforum.ric323.co...opic.php?f=59&t=15
NEW USERS: Posting images, links and code - workaround for restrictions.
To get a useful answer, always state which PIC you are using!
#8
LdB_ECM
Senior Member
  • Total Posts : 110
  • Reward points : 0
  • Joined: 2019/04/16 22:01:25
  • Location: 0
  • Status: offline
Re: PIC24FJ Address Trap issue 2019/06/25 22:06:43 (permalink)
+1 (1)
As ric said that is not a great idea you are asking to bleed memory because there is no obvious owner to be given the task of cleanup. Just get the caller to provide the buffer and if need be the size of buffer.
 
This is conceptually the same as the second circa 70's example
void ExtractAuthKey (const uint8_t* authkey, uint8_t* result_buffer)

This is old school circa 1970's string functions and DANGEROUS
uint8_t* ExtractAuthKey (const uint8_t* authkey)

 
However if you really want to do it .. here it is
Invariably you will forget to Free those 8 bytes of memory :-) 
uint8_t* ExtractAuthKey (const uint8_t* authkey)
{
   uint16_t* in1 = (uint16_t*)&authkey[0];       // Cast and create ptr1
   uint16_t* in2 = (uint16_t*)&authkey[16];      // Cast and Create ptr2
   uint16_t* result = (uint16_t*)malloc(8);     // malloc 8 bytes from heap
   unsigned i;  
   for (i = 0; i < 4;)                           // Run 4 16 bit xor hash
   {
       result[i] = in1[i] ^ in2[i];              // Return each 16 bit hash to result buffer
   }  
 
 
 
   return ((uint8_t*)result);      // cast result pointer for return
}

post edited by LdB_ECM - 2019/06/25 22:35:09
#9
NKurzman
A Guy on the Net
  • Total Posts : 17519
  • Reward points : 0
  • Joined: 2008/01/16 19:33:48
  • Location: 0
  • Status: online
Re: PIC24FJ Address Trap issue 2019/06/25 22:07:29 (permalink)
+1 (1)
Bad guess:
uint8_t a; // this should be 2 byte aligned
uint8_t b; // this should be two byte aligned

Compilers will align based on the instruction set of the CPU. The PIC24 can handle bytes or words, so there is no reason to waste RAM.
You are assuming the rules you noticed for the ARM are universal. They are not. It is simply the ARM compilers programmers making the best use of resources as they see fit.
For a PIC24 if you need byte variables aligned, then tell the compiler to do it. If not you get a 50/50 chance of an exception.
And it can come and go as new code moves variables around.
#10
LdB_ECM
Senior Member
  • Total Posts : 110
  • Reward points : 0
  • Joined: 2019/04/16 22:01:25
  • Location: 0
  • Status: offline
Re: PIC24FJ Address Trap issue 2019/06/25 22:32:28 (permalink)
0
The rule tends to be true of all large RISC's I get on micros this small you may need byte instructions to squeeze every last space.
 
I assume the stack is aligned otherwise the push/pop or whatever PIC calls them have to roll?
Also malloc what is it's status aligned or not?
 
I know the details probably in the XC16 documentation somewhere but I find the search and index on it a nightmare and one of you guys will know the answer off the top of your head.
 
jijo if you are going to go that way this may be useful for you which I will release to public we use it alot on ARM risc
https://github.com/LdB-ECM/PIC24F/tree/master/memory
It's a simple memory allocator system that your can set for any alignment and it's allocations will always be that alignment.
It has a basic testbench if you want to check it.
 
You initialize the memory system with a start and address which is it's heap to allocate.
In C the easy way to do that is just create a uint8_t memory array and feed it the first and last address and it will dish that space out that is what the sample on the readme does.
 
On ARMs we often have 4 or 5 of these things running with 2, 4, 8, 16 and 64 byte alignment spaces
 
Anyhow it is what it is a really simple heap manager that you can set an alignment on.
 
post edited by LdB_ECM - 2019/06/25 23:27:05
#11
jijo.thomas@bytesandnibbles.com
New Member
  • Total Posts : 7
  • Reward points : 0
  • Joined: 2019/06/24 02:21:40
  • Location: 0
  • Status: offline
Re: PIC24FJ Address Trap issue 2019/06/26 00:05:04 (permalink)
0
Thanks. 
 
Can you tell me whats wrong here?
//This works fine
void Xor16_H(uint8_t* in1, uint8_t* in2)
{
    uint16_t* in11 = (uint16_t*)&in1[0]; 
    uint16_t* in12 = (uint16_t*)&in2[0]; 
    uint16_t i;
    uint16_t Index = 0;
    
    for (i = 0; i < 8;i++) 
    {
        in11[Index ^ i] = in11[Index ^ i] ^ in12[Index ^ i];

    }

}

//This throws address error
void Xor16_H(uint8_t* in1, uint8_t* in2)
{
    uint16_t i;
    uint16_t Index = 0;
    
    for (i = 0; i < 8;i++) 
    {
        *(uint16_t*)&in1[Index ^ i] = *(uint16_t*)&in1[Index ^ i] ^ *(uint16_t*)&in2[Index ^ i];

    }

}

#12
LdB_ECM
Senior Member
  • Total Posts : 110
  • Reward points : 0
  • Joined: 2019/04/16 22:01:25
  • Location: 0
  • Status: offline
Re: PIC24FJ Address Trap issue 2019/06/26 00:27:24 (permalink) ☄ Helpfulby jijo.thomas@bytesandnibbles.com 2019/06/26 02:48:59
0
You need to understand C precedence ... same as maths
So does 2 + 3 * 4  equal 20 or 24 and why?
 
This thing also has a precedence please take a second to look at it
https://en.cppreference.com/w/c/language/operator_precedence
 
So when you write junk like this its dam difficult to in you head work out the precedence is
*(uint16_t*)&in1[Index ^ i]
 Now armed with the C precedence chart start putting brackets like you do in maths  and see what you have done
 
Now can I also point out that those pointers will optimize to just a register it costs you nothing to write it out the safe way :-)
 
So what I am questioning is why you are trying to write it like that it is horrible and almost unreadable and completely unsafe.
#13
jijo.thomas@bytesandnibbles.com
New Member
  • Total Posts : 7
  • Reward points : 0
  • Joined: 2019/06/24 02:21:40
  • Location: 0
  • Status: offline
Re: PIC24FJ Address Trap issue 2019/06/26 02:49:22 (permalink)
0
Thank you very much 
#14
andersm
Super Member
  • Total Posts : 2605
  • Reward points : 0
  • Joined: 2012/10/07 14:57:44
  • Location: 0
  • Status: offline
Re: PIC24FJ Address Trap issue 2019/06/26 03:03:40 (permalink)
0
LdB_ECMAlso malloc what is it's status aligned or not?

Malloc always returns a pointer compatible with the strictest alignment requirements of the platform.
 
Byte variables will be allocated with 1-byte alignment on ARM, GCC allocates byte arrays with 4-byte alignment by default.
#15
LdB_ECM
Senior Member
  • Total Posts : 110
  • Reward points : 0
  • Joined: 2019/04/16 22:01:25
  • Location: 0
  • Status: offline
Re: PIC24FJ Address Trap issue 2019/06/26 06:13:58 (permalink)
0
I know the ARM I have coded on them for 10+ years .... it's the PIC I am new with :-)
I showed you the default way we deal with it on the ARM we setup our own subsystems which malloc at whatever alignment we want. I even know roughly who you are because TNeo (by Dmitry Frank) was initially forked from your code when I first started on the baby Cortex M3.
 
The PIC handles bytes is 16bit with 24 bit pointers and has interesting bank windowing so I am expecting the answer might be slightly more interesting.
 
Anyhow I will do the fishing exercise and look it up tonight, the PIC documentation search I find frustrating. 
 
post edited by LdB_ECM - 2019/06/26 06:39:38
#16
aschen0866
Super Member
  • Total Posts : 4469
  • Reward points : 0
  • Joined: 2006/01/08 22:18:32
  • Location: San Diego
  • Status: offline
Re: PIC24FJ Address Trap issue 2019/06/26 10:03:16 (permalink)
0
LdB_ECM
...
So lets cover the three situations and confirm I am expecting
...
 

What if the buffer is part of packed data structure? For example,

typedef struct __attribute__((packed))
{
    uint8_t command;
    uint16_t length;
    uint8_t payload[16];
    uint16_t crc;
} COM_PACKET;

In this case length, payload and crc will all be at odd addresses.
 
On a processor that assumes natural alignment, any time you up-cast a pointer, you are risking a potential address trap.
#17
LdB_ECM
Senior Member
  • Total Posts : 110
  • Reward points : 0
  • Joined: 2019/04/16 22:01:25
  • Location: 0
  • Status: offline
Re: PIC24FJ Address Trap issue 2019/06/26 11:42:55 (permalink)
0
That comes under the stupid things with pointers ... it isn't natural
 
You pack a structure you should know the risk and you need to take care.
#18
aschen0866
Super Member
  • Total Posts : 4469
  • Reward points : 0
  • Joined: 2006/01/08 22:18:32
  • Location: San Diego
  • Status: offline
Re: PIC24FJ Address Trap issue 2019/06/26 12:38:13 (permalink)
0
LdB_ECM
That comes under the stupid things with pointers ... it isn't natural
 

Why not? A 16-bit or 32-bit processor communicates with an 8-bit processor using a defined protocol.
LdB_ECM
You pack a structure you should know the risk and you need to take care.

Yes, to "take care" of it, the best thing to do is not to assume a point argument will always be naturally aligned and avoid pointer up casting altogether.
#19
LdB_ECM
Senior Member
  • Total Posts : 110
  • Reward points : 0
  • Joined: 2019/04/16 22:01:25
  • Location: 0
  • Status: offline
Re: PIC24FJ Address Trap issue 2019/06/26 19:54:59 (permalink)
0
Can we please drop this "natural" was defined by me to mean something. Packed field struct's are always something we take care of, hell your peripheral bus may be only 32bits while your on a 64bit CortexA53 or A72 all Pi's for example are that way in 32 or 64 bit.
 
So I would never write structures like people do on here because I can't port the code, but no home hobby person is ever going to write structures like we do.
 
If you really want to see what we do take a typical USB register and the code is intended for 32bit/64bit ARM you have to spell out the alignment of each and every field individually and of the structure itself
struct __attribute__((__packed__, aligned(4))) HostChannel {
    volatile __attribute__((aligned(4))) struct HostChannelCharacteristic Characteristic;    // +0x0
    volatile __attribute__((aligned(4))) struct HostChannelSplitControl SplitCtrl;            // +0x4
    volatile __attribute__((aligned(4))) struct ChannelInterrupts Interrupt;                // +0x8
    volatile __attribute__((aligned(4))) struct ChannelInterrupts InterruptMask;            // +0xc
    volatile __attribute__((aligned(4))) struct HostTransferSize TransferSize;                // +0x10
    volatile __attribute__((aligned(4))) uint32_t  DmaAddr;                                    // +0x14
    volatile __attribute__((aligned(4))) uint32_t _reserved18;                                // +0x18
    volatile __attribute__((aligned(4))) uint32_t _reserved1c;                                // +0x1c
};

 
Show that to your home hobby coder and they will have a heartache and they would never write like that because they don't recycle code like we do. Only those who get around will even work out why we have the volatile there. You only have to compare that to the sample structs provided in comments here to see how different the worlds are.
post edited by LdB_ECM - 2019/06/26 20:24:33
#20
Page: 12 > Showing page 1 of 2
Jump to:
© 2019 APG vNext Commercial Version 4.5