Volatile now required for access to SRAM/VRAM unlike past versions

Post Reply
Dwedit
Posts: 43
Joined: Sun Jan 06, 2008 4:06 am

Volatile now required for access to SRAM/VRAM unlike past versions

Post by Dwedit » Mon May 23, 2022 7:36 pm

I just wanted to give a heads up to anyone experiencing this. I only caught this because of warnings from the NO$GBA debugger.

In past versions of DevKitArm, you could write code like this:

Code: Select all

void ByteSet(char *p, char value, int size)
{
    while (size)
    {
        *p++ = value;
        size--;
    }
}
In past versions of DevKitArm, this code would compile so that only 8 bit memory access would be performed to that memory, so you could use such code for the SRAM memory area.
This is no longer the case. The compiler will now either replace this with a call to "memset", or will generate code that does 32-bit writes to memory. So this code can no longer be used as-is to access the SRAM memory area.

You now need to use "volatile" on your pointer to prevent the compiler from being allowed to use a larger read or write size.

This even applies to VRAM, in some cases, the compiler will decide to perform 8-bit writes, even if your code did not use any such writes.
A snippet of some code:

Code: Select all

u16 *here=(u16*)0x06000000+(row&0x1F)*32;
int i = 0;
u16 space;
...
for(;i<29;i++)
{
	here[i] = space;
}
In this snippet, the compiler detected a series of writes in a loop, and changed it to memset. The code inside memset saw that the pointer was not aligned to a dword boundary, so it performed 8 bit writes to VRAM.

So now all access to VRAM or SRAM must be done through volatile pointers, otherwise the compiler is free to pick memory access that is incompatible with the actual hardware.

edea
Posts: 1
Joined: Mon Jun 13, 2022 11:59 pm

Re: Volatile now required for access to SRAM/VRAM unlike past versions

Post by edea » Tue Jun 14, 2022 12:57 am

Unfortunately this is wrong.
You don't really understand the semantics of "volatile" and how C looks at the memory access.
All memory locations accessed by C code are uniformly from the point of view of the C compiler,This is often referred to as uniform memory access(UMA).
The "uniform" here means that all these memory locations can be accessed at any time by any load/store instruction.
The "volatile" just tell the compiler that you must generate real load/store instructions.
However,the compiler can still use any type of load/store instruction for performance as long as the result is consistent with the semantics expressed by the C code.
So the problem here is not the behavior of the C compiler but which memory locations you access cannot be treated uniformly,so these memory locations should not be accessed by C code.
You should write the C ABI compliant assembler to access these memory locations and provide the C function interfaces,then use these functions to indirectly access those memory locations instead of directly by C code.

Dwedit
Posts: 43
Joined: Sun Jan 06, 2008 4:06 am

Re: Volatile now required for access to SRAM/VRAM unlike past versions

Post by Dwedit » Sun Dec 04, 2022 8:17 pm

That's a bummer, now it has to be inline functions with inline ASM?

barfoo34
Posts: 3
Joined: Tue Jan 10, 2023 8:27 pm

Re: Volatile now required for access to SRAM/VRAM unlike past versions

Post by barfoo34 » Tue Jan 17, 2023 5:30 pm

edea wrote: Tue Jun 14, 2022 12:57 am The "volatile" just tell the compiler that you must generate real load/store instructions.
However,the compiler can still use any type of load/store instruction for performance as long as the result is consistent with the semantics expressed by the C code.
So the problem here is not the behavior of the C compiler but which memory locations you access cannot be treated uniformly,so these memory locations should not be accessed by C code.
You should write the C ABI compliant assembler to access these memory locations and provide the C function interfaces,then use these functions to indirectly access those memory locations instead of directly by C code.
I don't think that this is correct either :D

Using volatile should be enough: if the writing code happens in a loop, then on every iteration we are guaranteed (according to C99) to hit a "sequence point", and that in turn guarantees that all the previous operations on volatile variables have been executed. This blog post explains the topic in easy to understand terms (although I'm not sure that a volatile struct was the best example to explain it!): "Side effects and sequence points; why volatile matters" (you must search it in the internet, as if I send it as a link my post gets flagged).

Post Reply

Who is online

Users browsing this forum: No registered users and 2 guests