Jump to page: 1 27  
Page
Thread overview
ARM bare-metal programming in D (cont) - volatile
Oct 24, 2013
Mike
Oct 24, 2013
Øivind
Oct 24, 2013
Walter Bright
Oct 24, 2013
Mike
Oct 24, 2013
Iain Buclaw
Oct 24, 2013
Mike
Oct 24, 2013
Walter Bright
Oct 24, 2013
Mike
Oct 24, 2013
eles
Oct 24, 2013
Walter Bright
Oct 24, 2013
eles
Oct 24, 2013
Walter Bright
Oct 25, 2013
Mike
Oct 25, 2013
eles
Oct 25, 2013
Walter Bright
Oct 28, 2013
Russel Winder
Oct 28, 2013
Walter Bright
Oct 28, 2013
eles
Oct 28, 2013
Walter Bright
Oct 28, 2013
eles
Oct 28, 2013
Walter Bright
Oct 24, 2013
Russel Winder
Oct 24, 2013
eles
Oct 24, 2013
Iain Buclaw
Oct 24, 2013
Mike
Oct 24, 2013
Iain Buclaw
Oct 24, 2013
John Colvin
Oct 24, 2013
Iain Buclaw
Oct 24, 2013
John Colvin
Oct 24, 2013
Iain Buclaw
Oct 24, 2013
Johannes Pfau
Oct 24, 2013
Iain Buclaw
Oct 25, 2013
Johannes Pfau
Oct 24, 2013
eles
Oct 24, 2013
Iain Buclaw
Oct 24, 2013
eles
Oct 24, 2013
Timo Sintonen
Oct 24, 2013
Mike
Oct 24, 2013
eles
Oct 25, 2013
Walter Bright
Oct 26, 2013
eles
Oct 27, 2013
Russel Winder
Re: D on ARM [was Re: ARM bare-metal programming in D (cont) - volatile]
Oct 27, 2013
Russel Winder
Oct 27, 2013
Dmitry Olshansky
Re: D on ARM [was Re: ARM bare-metal programming in D (cont) - volatile]
Oct 27, 2013
Russel Winder
Oct 27, 2013
Russel Winder
Oct 24, 2013
Iain Buclaw
Oct 24, 2013
Arjan
Oct 24, 2013
Mike
Oct 24, 2013
Daniel Murphy
Oct 24, 2013
Iain Buclaw
Oct 24, 2013
Timo Sintonen
Oct 25, 2013
Daniel Murphy
Oct 25, 2013
Timo Sintonen
Oct 25, 2013
Johannes Pfau
Oct 25, 2013
Timo Sintonen
Oct 26, 2013
Johannes Pfau
Oct 26, 2013
Iain Buclaw
Oct 26, 2013
Timo Sintonen
Oct 27, 2013
Russel Winder
Oct 27, 2013
Walter Bright
Oct 28, 2013
Russel Winder
Oct 28, 2013
Walter Bright
Oct 27, 2013
Russel Winder
Oct 27, 2013
David Nadlinger
October 24, 2013
Hello again,

I'm interested in ARM bare-metal programming with D, and I'm trying to get my head wrapped around how to approach this.  I'm making progress, but I found something that was surprising to me: deprecation of the volatile keyword.

In the bare-metal/hardware/driver world, this keyword is important to ensure the optimizer doesn't cache reads to memory-mapped IO, as some hardware peripheral may modify the value without involving the processor.

I've read a few discussions on the D forums about the volatile keyword debate, but noone seemed to reconcile the need for volatile in memory-mapped IO.  Was this an oversight?

What's D's answer to this?  If one were to use D to read from memory-mapped IO, how would one ensure the compiler doesn't cache the value?
October 24, 2013
On Thursday, 24 October 2013 at 00:43:11 UTC, Mike wrote:
> Hello again,
>
> I'm interested in ARM bare-metal programming with D, and I'm trying to get my head wrapped around how to approach this.  I'm making progress, but I found something that was surprising to me: deprecation of the volatile keyword.
>
> In the bare-metal/hardware/driver world, this keyword is important to ensure the optimizer doesn't cache reads to memory-mapped IO, as some hardware peripheral may modify the value without involving the processor.
>
> I've read a few discussions on the D forums about the volatile keyword debate, but noone seemed to reconcile the need for volatile in memory-mapped IO.  Was this an oversight?
>
> What's D's answer to this?  If one were to use D to read from memory-mapped IO, how would one ensure the compiler doesn't cache the value?

+1
October 24, 2013
On 10/23/2013 5:43 PM, Mike wrote:
> I'm interested in ARM bare-metal programming with D, and I'm trying to get my
> head wrapped around how to approach this.  I'm making progress, but I found
> something that was surprising to me: deprecation of the volatile keyword.
>
> In the bare-metal/hardware/driver world, this keyword is important to ensure the
> optimizer doesn't cache reads to memory-mapped IO, as some hardware peripheral
> may modify the value without involving the processor.
>
> I've read a few discussions on the D forums about the volatile keyword debate,
> but noone seemed to reconcile the need for volatile in memory-mapped IO.  Was
> this an oversight?
>
> What's D's answer to this?  If one were to use D to read from memory-mapped IO,
> how would one ensure the compiler doesn't cache the value?

volatile was never a reliable method for dealing with memory mapped I/O. The correct and guaranteed way to make this work is to write two "peek" and "poke" functions to read/write a particular memory address:

    int peek(int* p);
    void poke(int* p, int value);

Implement them in the obvious way, and compile them separately so the optimizer will not try to inline/optimize them.
October 24, 2013
On Thursday, 24 October 2013 at 05:37:49 UTC, Walter Bright wrote:
> On 10/23/2013 5:43 PM, Mike wrote:
>> I'm interested in ARM bare-metal programming with D, and I'm trying to get my
>> head wrapped around how to approach this.  I'm making progress, but I found
>> something that was surprising to me: deprecation of the volatile keyword.
>>
>> In the bare-metal/hardware/driver world, this keyword is important to ensure the
>> optimizer doesn't cache reads to memory-mapped IO, as some hardware peripheral
>> may modify the value without involving the processor.
>>
>> I've read a few discussions on the D forums about the volatile keyword debate,
>> but noone seemed to reconcile the need for volatile in memory-mapped IO.  Was
>> this an oversight?
>>
>> What's D's answer to this?  If one were to use D to read from memory-mapped IO,
>> how would one ensure the compiler doesn't cache the value?
>
> volatile was never a reliable method for dealing with memory mapped I/O. The correct and guaranteed way to make this work is to write two "peek" and "poke" functions to read/write a particular memory address:
>
>     int peek(int* p);
>     void poke(int* p, int value);
>
> Implement them in the obvious way, and compile them separately so the optimizer will not try to inline/optimize them.

Thanks for the answer, Walter. I think this would be acceptable in many (most?) cases, but not where high performance is needed  I think these functions add too much overhead if they are not inlined and in a critical path (bit-banging IO, for example).  Afterall, a read/write to a volatile address is a single atomic instruction, if done properly.

Is there a way to tell D to remove the function overhead, for example, like a "naked" attribute, yet still retain the "volatile" behavior?
October 24, 2013
On Thursday, 24 October 2013 at 00:43:11 UTC, Mike wrote:
> Hello again,
>
> I'm interested in ARM bare-metal programming with D, and I'm trying to get my head wrapped around how to approach this.  I'm making progress, but I found something that was surprising to me: deprecation of the volatile keyword.
>
> In the bare-metal/hardware/driver world, this keyword is important to ensure the optimizer doesn't cache reads to memory-mapped IO, as some hardware peripheral may modify the value without involving the processor.
>
> I've read a few discussions on the D forums about the volatile keyword debate, but noone seemed to reconcile the need for volatile in memory-mapped IO.  Was this an oversight?
>
> What's D's answer to this?  If one were to use D to read from memory-mapped IO, how would one ensure the compiler doesn't cache the value?

This article might also give some insight in the problems with volatile:
http://blog.regehr.org/archives/28
October 24, 2013
On 24 October 2013 06:37, Walter Bright <newshound2@digitalmars.com> wrote:
> On 10/23/2013 5:43 PM, Mike wrote:
>>
>> I'm interested in ARM bare-metal programming with D, and I'm trying to get
>> my
>> head wrapped around how to approach this.  I'm making progress, but I
>> found
>> something that was surprising to me: deprecation of the volatile keyword.
>>
>> In the bare-metal/hardware/driver world, this keyword is important to
>> ensure the
>> optimizer doesn't cache reads to memory-mapped IO, as some hardware
>> peripheral
>> may modify the value without involving the processor.
>>
>> I've read a few discussions on the D forums about the volatile keyword
>> debate,
>> but noone seemed to reconcile the need for volatile in memory-mapped IO.
>> Was
>> this an oversight?
>>
>> What's D's answer to this?  If one were to use D to read from
>> memory-mapped IO,
>> how would one ensure the compiler doesn't cache the value?
>
>
> volatile was never a reliable method for dealing with memory mapped I/O.

Are you talking dmd or in general (it's hard to tell).  In gdc, volatile is the same as in gcc/g++ in behaviour.  Although in one aspect, when the default storage model was switched to thread-local, that made volatile on it's own pointless.

As a side note, 'shared' is considered a volatile type in gdc, which differs from the deprecated keyword which set volatile at a decl/expression level.  There is a difference in semantics, but it escapes this author at 6.30am in the morning.  :o)

In any case, using shared would be my recommended route for you to go down.


> The correct and guaranteed way to make this work is to write two "peek" and "poke" functions to read/write a particular memory address:
>
>     int peek(int* p);
>     void poke(int* p, int value);
>
> Implement them in the obvious way, and compile them separately so the optimizer will not try to inline/optimize them.

+1.  Using an optimiser along with code that talks to hardware can result in bizarre behaviour.

-- 
Iain Buclaw

*(p < e ? p++ : p) = (c & 0x0f) + '0';
October 24, 2013
On Thursday, 24 October 2013 at 06:25:20 UTC, Arjan wrote:
> On Thursday, 24 October 2013 at 00:43:11 UTC, Mike wrote:
>> Hello again,
>>
>> I'm interested in ARM bare-metal programming with D, and I'm trying to get my head wrapped around how to approach this.  I'm making progress, but I found something that was surprising to me: deprecation of the volatile keyword.
>>
>> In the bare-metal/hardware/driver world, this keyword is important to ensure the optimizer doesn't cache reads to memory-mapped IO, as some hardware peripheral may modify the value without involving the processor.
>>
>> I've read a few discussions on the D forums about the volatile keyword debate, but noone seemed to reconcile the need for volatile in memory-mapped IO.  Was this an oversight?
>>
>> What's D's answer to this?  If one were to use D to read from memory-mapped IO, how would one ensure the compiler doesn't cache the value?
>
> This article might also give some insight in the problems with volatile:
> http://blog.regehr.org/archives/28

Arjan, Thanks for the information.  I basically agree with premise of that blog, but the author also said "If you are writing code for an in-order embedded processor and have little or no infrastructure besides the C compiler, you may need to lean more heavily on volatile".  Well, that's me.

My goal is to target bare-metal embedded systems with D, so I'm looking for a volatile-like solution in D.  I don't care if the language has the "volatile" keyword or not, I just want to be able to read and write to my IO as fast as possible, and I'm wondering if D has a way to do this in a way that is comparable to what can be achieved in C.
October 24, 2013
On 24 October 2013 07:19, Mike <none@none.com> wrote:
> On Thursday, 24 October 2013 at 05:37:49 UTC, Walter Bright wrote:
>>
>> On 10/23/2013 5:43 PM, Mike wrote:
>>>
>>> I'm interested in ARM bare-metal programming with D, and I'm trying to
>>> get my
>>> head wrapped around how to approach this.  I'm making progress, but I
>>> found
>>> something that was surprising to me: deprecation of the volatile keyword.
>>>
>>> In the bare-metal/hardware/driver world, this keyword is important to
>>> ensure the
>>> optimizer doesn't cache reads to memory-mapped IO, as some hardware
>>> peripheral
>>> may modify the value without involving the processor.
>>>
>>> I've read a few discussions on the D forums about the volatile keyword
>>> debate,
>>> but noone seemed to reconcile the need for volatile in memory-mapped IO.
>>> Was
>>> this an oversight?
>>>
>>> What's D's answer to this?  If one were to use D to read from
>>> memory-mapped IO,
>>> how would one ensure the compiler doesn't cache the value?
>>
>>
>> volatile was never a reliable method for dealing with memory mapped I/O. The correct and guaranteed way to make this work is to write two "peek" and "poke" functions to read/write a particular memory address:
>>
>>     int peek(int* p);
>>     void poke(int* p, int value);
>>
>> Implement them in the obvious way, and compile them separately so the optimizer will not try to inline/optimize them.
>
>
> Thanks for the answer, Walter. I think this would be acceptable in many (most?) cases, but not where high performance is needed  I think these functions add too much overhead if they are not inlined and in a critical path (bit-banging IO, for example).  Afterall, a read/write to a volatile address is a single atomic instruction, if done properly.
>

Operations on volatile are *not* atomic. Nor do they establish a proper happens-before relationship for threading.  This is why we have core.atomic as a portable synchronisation mechanism in D.


Regards
-- 
Iain Buclaw

*(p < e ? p++ : p) = (c & 0x0f) + '0';
October 24, 2013
On Thursday, 24 October 2013 at 05:37:49 UTC, Walter Bright wrote:
> On 10/23/2013 5:43 PM, Mike wrote:
>> I'm interested in ARM bare-metal programming with D, and I'm trying to get my
>> head wrapped around how to approach this.  I'm making progress, but I found
>> something that was surprising to me: deprecation of the volatile keyword.
>>
>> In the bare-metal/hardware/driver world, this keyword is important to ensure the
>> optimizer doesn't cache reads to memory-mapped IO, as some hardware peripheral
>> may modify the value without involving the processor.
>>
>> I've read a few discussions on the D forums about the volatile keyword debate,
>> but noone seemed to reconcile the need for volatile in memory-mapped IO.  Was
>> this an oversight?
>>
>> What's D's answer to this?  If one were to use D to read from memory-mapped IO,
>> how would one ensure the compiler doesn't cache the value?
>
> volatile was never a reliable method for dealing with memory mapped I/O. The correct and guaranteed way to make this work is to write two "peek" and "poke" functions to read/write a particular memory address:
>
>     int peek(int* p);
>     void poke(int* p, int value);
>
> Implement them in the obvious way, and compile them separately so the optimizer will not try to inline/optimize them.

Yes, this is a simplest way to do it and works with gdc when compiled in separate file with no optimizations and inlining.

But todays peripherals may have tens of registers and they are usually represented as a struct. Using the peripheral often require several register access. Doing it this way will not make code very readable.

As a workaround I have all register access functions in a separate file and compile those files in a separate directory with no optimizations. The amount of code generated is 3-4 times more and this is a problem because in controllers memory and speed are always too small.

October 24, 2013
On 10/23/2013 11:19 PM, Mike wrote:
> Thanks for the answer, Walter. I think this would be acceptable in many (most?)
> cases, but not where high performance is needed I think these functions add too
> much overhead if they are not inlined and in a critical path (bit-banging IO,
> for example). Afterall, a read/write to a volatile address is a single atomic
> instruction, if done properly.
>
> Is there a way to tell D to remove the function overhead, for example, like a
> "naked" attribute, yet still retain the "volatile" behavior?

You have to give up on volatile. Nobody agrees on what it means. What does "don't optimize" mean? And that's not at all the same thing as "atomic".

I wouldn't worry about peek/poke being too slow unless you actually benchmark it and prove it is. Then, your alternatives are:

1. Write it in ordinary D, compile it, check the code generated, and if it is what you want, you're golden (at least for that compiler & switches).

2. Write it in inline asm. That's what it's for.

3. Write it in an external C function and link it in.
« First   ‹ Prev
1 2 3 4 5 6 7