memcpy hardware fault when reading from unaligned Flash address

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

memcpy hardware fault when reading from unaligned Flash address

3,028 Views
mihaisavu
Contributor I

I get a hardware fault if I try to copy data from flash using memcpy, if the source address is 2 bytes aligned but not 4 bytes aligned

I am using EVKMIMXRT1064 development board together with SDK flexspi_nor_pooling_transfer example. (SDK 2.9.2)

The original line bellow works

memcpy(s_nor_read_buffer, (void *)(EXAMPLE_FLEXSPI_AMBA_BASE + EXAMPLE_SECTOR * SECTOR_SIZE),sizeof(s_nor_read_buffer));    // Works

if I change it to:
memcpy(s_nor_read_buffer, (void *)(EXAMPLE_FLEXSPI_AMBA_BASE + EXAMPLE_SECTOR * SECTOR_SIZE+1),sizeof(s_nor_read_buffer)-1);   // Works
memcpy(s_nor_read_buffer, (void *)(EXAMPLE_FLEXSPI_AMBA_BASE + EXAMPLE_SECTOR * SECTOR_SIZE+2),sizeof(s_nor_read_buffer)-2);   // does not work -> hardware fault

Is there a way to make memcpy functional, regarding address alignment?

Labels (1)
0 Kudos
Reply
4 Replies

3,014 Views
gusarambula
NXP TechSupport
NXP TechSupport

Hello Mihaisavu,

It’s usually desired to maintain memory alignment to avoid problems. However, it could be a problem with optimization so I would recommend disabling optimization and seeing if the problem persists.

ARM does allow unaligned accesses, but these are also monitored by the MPU so you would need to review the settings of the MPU for this memory area.

Regards,
Gustavo

0 Kudos
Reply

3,007 Views
mihaisavu
Contributor I

Hello Gustavo,

The optimization is None (-O0).

If I replace the memcpy with a for block copy it works.

char *src=(char *)(EXAMPLE_FLEXSPI_AMBA_BASE + EXAMPLE_SECTOR * SECTOR_SIZE+2);
for(int i=0;i<(sizeof(s_nor_read_buffer)-2);i++){
s_nor_read_buffer[i] =src[i];
}

But I would like to use memcpy since it is used a lot in a software I am porting to iMXRT

Can you point me what MPU settings to check? I am using SDK 2.9.2 "driver_example" "flexspi_nor_pooling_transfer" with MCUXpresso and EVKMIMXRT1064 evaluation board. I made no other to original example settings

Regards,

Mihai

0 Kudos
Reply

2,999 Views
TomE
Specialist II

You should probably read the source of the memcpy() function that you're using to see what it is doing internally. It is very common for these functions to first make small transfers (1 byte at a time) until they get 2 or 4 (or more) byte alignment, and then proceed to use the most efficient transfer mode the CPU can support. For this CPU it might be performing LDM or even LDREXD instructions which will fault if they don't have 4 and 8 byte alignment, irrespective of SCTLR.A. The memcpy() code will make sure it doesn't get that wrong. So the 1-byte offset works because memcpy() is alignined, but the 2-byte offset generates different cycles which are failing on that peripheral.

I've read through the FlexSPI chapter and there's nothing obvious in there to say what's going wrong. That memory space might be cached, and that might be causing problems.

After you get the error, can you examine the FlexSPI error registers? These are detailed in "26.8.2 Overview of Error Flags". They might show what sort of memory cycle the FlexSPI didn't like.

I've read through the "B3.5 Protected Memory System Architecture, PMSAv7" chapter in the "ARM v7-M Architecture Reference Manual" and can't find any reference to alignment.

Technically, memcpy() is a user-space function, and should only be used from user code that doesn't go anywhere near any hardware addresses. It can be used in drivers that are accessing "regular memory". If you have a memory space with special alignment requirements, then a custom memory copy routine (or a wrapper for memcpy() that enforces alignment) can be used for that driver or memory space. I've worked on systems with a custom memcpy-like function that knew all of the different memory spaces, and called different copy functions depending on the source and destination addresses.

I'm not familiar with the evaluation board or SDK code.

Tom

 

0 Kudos
Reply

2,987 Views
mihaisavu
Contributor I

Hello Tom,

Thanks for your answer!

The memcpy assembly code is bellow. It does four bytes transfers if both addresses (source and destination) are even. It looks I will have to debug deeper into FlexSPI settings... 

Regards,

Mihai

__aeabi_memcpy:
70005b66: orr.w r3, r0, r1
70005b6a: lsls r3, r3, #31
70005b6c: mov r3, r0
70005b6e: bmi.n 0x70005b8a <__aeabi_memcpy8+26>
__aeabi_memcpy8:
70005b70: mov r3, r0
70005b72: subs r2, #4
70005b74: ittt cs
70005b76: ldrcs.w r12, [r1], #4
70005b7a: strcs.w r12, [r3], #4
70005b7e: subscs.w r2, r2, #4
70005b82: bcs.n 0x70005b74 <__aeabi_memcpy8+4>
70005b84: adds r2, #4
70005b86: it eq
70005b88: bxeq lr
70005b8a: subs r2, #1
70005b8c: itt cs
70005b8e: ldrbcs.w r12, [r1], #1
70005b92: strbcs.w r12, [r3], #1
70005b96: bhi.n 0x70005b8a <__aeabi_memcpy8+26>
70005b98: bx lr

0 Kudos
Reply