EmbeddedRelated.com
Forums

Cortex-M0 GPIO shadow registers

Started by Unknown March 29, 2012
Hello guys,

I just can't figure out how the shadow registers works on Cortex-M0, i'm using LPC11C14.

I'm doing this way now, using CMSIS:
LPC_GPIO0->DATA |= (0x1 << bit);
or
LPC_GPIO0->DATA &= ~(0x1 << bit);

writing directly on GPIOnDATA register As I could understand writing directly to this register set all mask bits to 1 allowing directly access.
This way of doing is wrong or unsafe?
Why use masked access?
following...
this in on CMSIS file:

union {
__IO uint32_t MASKED_ACCESS[4096]; /*!< Offset: 0x0000 to 0x3FFC Port data Register for pins PIOn_0 to PIOn_11 (R/W) */
struct {
uint32_t RESERVED0[4095];
__IO uint32_t DATA; /*!< Offset: 0x3FFC Port data Register (R/W) */
};
I read the pages 185 to 187, but I really can't understand it.

How do I use the masks?
Wich one should I use?
Should I make some think like this:

LPC_GPIO0->MASKED_ACCESS[ 0 ] = 0x01 << 2;
LPC_GPIO0->DATA = 0xFF;

This would set just the first bit?
Thanks,
AndrRairan.

An Engineer's Guide to the LPC2100 Series

Hi Andr

the mask register defines the bits that your operation is allowed to
modify. This way, you don't need read-modify-write cycles in software
but simply set the mask and write your value.

I would suggest you use the following sequence on ***ALL*** accesses
(more on "***ALL***" below):
- backup the mask register
- set the mask to the value you want
- write your value to the port (note that masked bits are not relevant,
so you may simplify your code)
- restore the mask

By doing this on all accesses, you're likely not to worry about
interrupts, except if your sequence needs to need a precise timing or if
the interrupt may change the sequence. Likewise, you have a SET and
CLEAR registers that can simplify single bits operations. It's actually
a nice feature.

Hope it helps
Cheers
Olivier
AndrRairan wrote:
> Hello guys,
>
> I just can't figure out how the shadow registers works on Cortex-M0, i'm using LPC11C14.
>
> I'm doing this way now, using CMSIS:
> LPC_GPIO0->DATA |= (0x1<< bit);
> or
> LPC_GPIO0->DATA&= ~(0x1<< bit);
>
> writing directly on GPIOnDATA register As I could understand writing directly to this register set all mask bits to 1 allowing directly access.
> This way of doing is wrong or unsafe?
> Why use masked access?
> following...
> this in on CMSIS file:
>
> union {
> __IO uint32_t MASKED_ACCESS[4096]; /*!< Offset: 0x0000 to 0x3FFC Port data Register for pins PIOn_0 to PIOn_11 (R/W) */
> struct {
> uint32_t RESERVED0[4095];
> __IO uint32_t DATA; /*!< Offset: 0x3FFC Port data Register (R/W) */
> };
> I read the pages 185 to 187, but I really can't understand it.
>
> How do I use the masks?
> Wich one should I use?
> Should I make some think like this:
>
> LPC_GPIO0->MASKED_ACCESS[ 0 ] = 0x01<< 2;
> LPC_GPIO0->DATA = 0xFF;
>
> This would set just the first bit?
> Thanks,
> AndrRairan.
>
>
Hi Andr

The whole point of masked access is to avoid conflicts with interrupts, and
it's really easy to use in most cases.

I use the following macros for setting and clearing bits.

#define SET_GPIO(Port,Bits)(Port->MASKED_ACCESS[(Bits)] = (Bits))
#define CLR_GPIO(Port,Bits)(Port->MASKED_ACCESS[(Bits)] = (0))

Then I define macro's for the ports to make the code more portable, e.g.
#define ISR_LED_ON SET_GPIO(LPC_GPIO3,0x1) // P3.0
#define ISR_LED_OFF CLR_GPIO(LPC_GPIO3,0x1)

Of course if you change multiple bits you can simply clear the inverse using
another SW mask then set the bits required ( a slightly more complex macro
).
e.g.

#define
PUT_GPIO(Port,Value,Mask)(CLR_GPIO(Port,(Mask));SET_GPIO(Port,(Value)))

Or slightly better but probably a CPU cycle longer

#define PUT_GPIO(Port,Value,Mask)(CLR_GPIO(Port,(Mask) &
~(Value));SET_GPIO(Port,(Value)))

This will of course lead to a couple of CPU cycles when the bits are neither
the old or new value, but for most cases that doesn't matter.

If you need to change multiple bits and they must transition
"simultaneously" then you have to do as Olivier suggested but then also you
need to disable interrupts before the sequence and re-enable them
immediately afterwards.

Also using the masked approach if you change bits in multiple threads you
need to restore the mask in anything but the lowest priority thread, though
this can be done after re-enabling interrupts so that you don't affect
interrupt latency too much.

Regards

Phil.
-----Original Message-----
From: l... [mailto:l...] On Behalf Of
Olivier Gautherot
Sent: 30 March 2012 02:15
To: l...
Subject: Re: [lpc2000] Cortex-M0 GPIO shadow registers

Hi Andr

the mask register defines the bits that your operation is allowed to modify.
This way, you don't need read-modify-write cycles in software but simply set
the mask and write your value.

I would suggest you use the following sequence on ***ALL*** accesses (more
on "***ALL***" below):
- backup the mask register
- set the mask to the value you want
- write your value to the port (note that masked bits are not relevant, so
you may simplify your code)
- restore the mask

By doing this on all accesses, you're likely not to worry about interrupts,
except if your sequence needs to need a precise timing or if the interrupt
may change the sequence. Likewise, you have a SET and CLEAR registers that
can simplify single bits operations. It's actually a nice feature.

Hope it helps
Cheers
Olivier
AndrRairan wrote:
> Hello guys,
>
> I just can't figure out how the shadow registers works on Cortex-M0, i'm
using LPC11C14.
>
> I'm doing this way now, using CMSIS:
> LPC_GPIO0->DATA |= (0x1<< bit);
> or
> LPC_GPIO0->DATA&= ~(0x1<< bit);
>
> writing directly on GPIOnDATA register As I could understand writing
directly to this register set all mask bits to 1 allowing directly access.
> This way of doing is wrong or unsafe?
> Why use masked access?
> following...
> this in on CMSIS file:
>
> union {
> __IO uint32_t MASKED_ACCESS[4096]; /*!< Offset: 0x0000 to 0x3FFC
Port data Register for pins PIOn_0 to PIOn_11 (R/W) */
> struct {
> uint32_t RESERVED0[4095];
> __IO uint32_t DATA; /*!< Offset: 0x3FFC Port data
Register (R/W) */
> };
> I read the pages 185 to 187, but I really can't understand it.
>
> How do I use the masks?
> Wich one should I use?
> Should I make some think like this:
>
> LPC_GPIO0->MASKED_ACCESS[ 0 ] = 0x01<< 2; LPC_GPIO0->DATA = 0xFF;
>
> This would set just the first bit?
> Thanks,
> AndrRairan.
>
>
Ok Phil, thank you for explanation

But why you put Bits in the MASKED_ACCESS index?
> Port->MASKED_ACCESS[(Bits)]
>
Why there have 4095 32-bit register for MASKED_ACCESS?
Does matter which one to use?

What is the difference of simply writing on DATA register?
This two operations isn't both single cycle?

And about the SET and CLEAR register, I couldn't find them on User Manual.
Can anyone give me the directions?

Best regards and thanks again.
On Mar 29, 2012, at 11:54 PM, Phil Young wrote:

> Hi Andr
>
> The whole point of masked access is to avoid conflicts with interrupts, and
> it's really easy to use in most cases.
>
> I use the following macros for setting and clearing bits.
>
> #define SET_GPIO(Port,Bits)(Port->MASKED_ACCESS[(Bits)] = (Bits))
> #define CLR_GPIO(Port,Bits)(Port->MASKED_ACCESS[(Bits)] = (0))
>
> Then I define macro's for the ports to make the code more portable, e.g.
> #define ISR_LED_ON SET_GPIO(LPC_GPIO3,0x1) // P3.0
> #define ISR_LED_OFF CLR_GPIO(LPC_GPIO3,0x1)
>
> Of course if you change multiple bits you can simply clear the inverse using
> another SW mask then set the bits required ( a slightly more complex macro
> ).
> e.g.
>
> #define
> PUT_GPIO(Port,Value,Mask)(CLR_GPIO(Port,(Mask));SET_GPIO(Port,(Value)))
>
> Or slightly better but probably a CPU cycle longer
>
> #define PUT_GPIO(Port,Value,Mask)(CLR_GPIO(Port,(Mask) &
> ~(Value));SET_GPIO(Port,(Value)))
>
> This will of course lead to a couple of CPU cycles when the bits are neither
> the old or new value, but for most cases that doesn't matter.
>
> If you need to change multiple bits and they must transition
> "simultaneously" then you have to do as Olivier suggested but then also you
> need to disable interrupts before the sequence and re-enable them
> immediately afterwards.
>
> Also using the masked approach if you change bits in multiple threads you
> need to restore the mask in anything but the lowest priority thread, though
> this can be done after re-enabling interrupts so that you don't affect
> interrupt latency too much.
>
> Regards
>
> Phil.
>
> -----Original Message-----
> From: l... [mailto:l...] On Behalf Of
> Olivier Gautherot
> Sent: 30 March 2012 02:15
> To: l...
> Subject: Re: [lpc2000] Cortex-M0 GPIO shadow registers
>
> Hi Andr
>
> the mask register defines the bits that your operation is allowed to modify.
> This way, you don't need read-modify-write cycles in software but simply set
> the mask and write your value.
>
> I would suggest you use the following sequence on ***ALL*** accesses (more
> on "***ALL***" below):
> - backup the mask register
> - set the mask to the value you want
> - write your value to the port (note that masked bits are not relevant, so
> you may simplify your code)
> - restore the mask
>
> By doing this on all accesses, you're likely not to worry about interrupts,
> except if your sequence needs to need a precise timing or if the interrupt
> may change the sequence. Likewise, you have a SET and CLEAR registers that
> can simplify single bits operations. It's actually a nice feature.
>
> Hope it helps
> Cheers
> Olivier
>
> AndrRairan wrote:
> > Hello guys,
> >
> > I just can't figure out how the shadow registers works on Cortex-M0, i'm
> using LPC11C14.
> >
> > I'm doing this way now, using CMSIS:
> > LPC_GPIO0->DATA |= (0x1<< bit);
> > or
> > LPC_GPIO0->DATA&= ~(0x1<< bit);
> >
> > writing directly on GPIOnDATA register As I could understand writing
> directly to this register set all mask bits to 1 allowing directly access.
> > This way of doing is wrong or unsafe?
> > Why use masked access?
> >
> >
> > following...
> > this in on CMSIS file:
> >
> > union {
> > __IO uint32_t MASKED_ACCESS[4096]; /*!< Offset: 0x0000 to 0x3FFC
> Port data Register for pins PIOn_0 to PIOn_11 (R/W) */
> > struct {
> > uint32_t RESERVED0[4095];
> > __IO uint32_t DATA; /*!< Offset: 0x3FFC Port data
> Register (R/W) */
> > };
> >
> >
> > I read the pages 185 to 187, but I really can't understand it.
> >
> > How do I use the masks?
> > Wich one should I use?
> > Should I make some think like this:
> >
> > LPC_GPIO0->MASKED_ACCESS[ 0 ] = 0x01<< 2; LPC_GPIO0->DATA = 0xFF;
> >
> > This would set just the first bit?
> >
> >
> > Thanks,
> > AndrRairan.
> >
> >
> >
> >
Ok, now I got it.

There are 4096 registers because they are the masks! pretty obvious...
I was thinking that you have to write in a mask for after using it, but they are the mask already.
Thats right?

But my second questions stays.
What's the difference between:

LPC_GPIO3->MASKED_ACCESS[ 0x01 ] = 0x01;
and
LPC_GPIO3->DATA |= 0x01;

They both aren't single cycle?
AndrRairan.
On Mar 29, 2012, at 11:54 PM, Phil Young wrote:

> Hi Andr
>
> The whole point of masked access is to avoid conflicts with interrupts, and
> it's really easy to use in most cases.
>
> I use the following macros for setting and clearing bits.
>
> #define SET_GPIO(Port,Bits)(Port->MASKED_ACCESS[(Bits)] = (Bits))
> #define CLR_GPIO(Port,Bits)(Port->MASKED_ACCESS[(Bits)] = (0))
>
> Then I define macro's for the ports to make the code more portable, e.g.
> #define ISR_LED_ON SET_GPIO(LPC_GPIO3,0x1) // P3.0
> #define ISR_LED_OFF CLR_GPIO(LPC_GPIO3,0x1)
>
> Of course if you change multiple bits you can simply clear the inverse using
> another SW mask then set the bits required ( a slightly more complex macro
> ).
> e.g.
>
> #define
> PUT_GPIO(Port,Value,Mask)(CLR_GPIO(Port,(Mask));SET_GPIO(Port,(Value)))
>
> Or slightly better but probably a CPU cycle longer
>
> #define PUT_GPIO(Port,Value,Mask)(CLR_GPIO(Port,(Mask) &
> ~(Value));SET_GPIO(Port,(Value)))
>
> This will of course lead to a couple of CPU cycles when the bits are neither
> the old or new value, but for most cases that doesn't matter.
>
> If you need to change multiple bits and they must transition
> "simultaneously" then you have to do as Olivier suggested but then also you
> need to disable interrupts before the sequence and re-enable them
> immediately afterwards.
>
> Also using the masked approach if you change bits in multiple threads you
> need to restore the mask in anything but the lowest priority thread, though
> this can be done after re-enabling interrupts so that you don't affect
> interrupt latency too much.
>
> Regards
>
> Phil.
>
> -----Original Message-----
> From: l... [mailto:l...] On Behalf Of
> Olivier Gautherot
> Sent: 30 March 2012 02:15
> To: l...
> Subject: Re: [lpc2000] Cortex-M0 GPIO shadow registers
>
> Hi Andr
>
> the mask register defines the bits that your operation is allowed to modify.
> This way, you don't need read-modify-write cycles in software but simply set
> the mask and write your value.
>
> I would suggest you use the following sequence on ***ALL*** accesses (more
> on "***ALL***" below):
> - backup the mask register
> - set the mask to the value you want
> - write your value to the port (note that masked bits are not relevant, so
> you may simplify your code)
> - restore the mask
>
> By doing this on all accesses, you're likely not to worry about interrupts,
> except if your sequence needs to need a precise timing or if the interrupt
> may change the sequence. Likewise, you have a SET and CLEAR registers that
> can simplify single bits operations. It's actually a nice feature.
>
> Hope it helps
> Cheers
> Olivier
>
> AndrRairan wrote:
> > Hello guys,
> >
> > I just can't figure out how the shadow registers works on Cortex-M0, i'm
> using LPC11C14.
> >
> > I'm doing this way now, using CMSIS:
> > LPC_GPIO0->DATA |= (0x1<< bit);
> > or
> > LPC_GPIO0->DATA&= ~(0x1<< bit);
> >
> > writing directly on GPIOnDATA register As I could understand writing
> directly to this register set all mask bits to 1 allowing directly access.
> > This way of doing is wrong or unsafe?
> > Why use masked access?
> >
> >
> > following...
> > this in on CMSIS file:
> >
> > union {
> > __IO uint32_t MASKED_ACCESS[4096]; /*!< Offset: 0x0000 to 0x3FFC
> Port data Register for pins PIOn_0 to PIOn_11 (R/W) */
> > struct {
> > uint32_t RESERVED0[4095];
> > __IO uint32_t DATA; /*!< Offset: 0x3FFC Port data
> Register (R/W) */
> > };
> >
> >
> > I read the pages 185 to 187, but I really can't understand it.
> >
> > How do I use the masks?
> > Wich one should I use?
> > Should I make some think like this:
> >
> > LPC_GPIO0->MASKED_ACCESS[ 0 ] = 0x01<< 2; LPC_GPIO0->DATA = 0xFF;
> >
> > This would set just the first bit?
> >
> >
> > Thanks,
> > AndrRairan.
> >
> >
> >
> >
Hi Andr

|= is not an atomic operation, the compiler will generate a sequence of load
, OR, store operations.
There is a danger than at interrupt can occur after the load and before the
store, and can update the register with a new value.
This would then get overwritten by the store losing the value changes that
the ISR made.

Regards

Phil.

-----Original Message-----
From: l... [mailto:l...] On Behalf Of
AndrRairan
Sent: 30 March 2012 04:57
To: l...
Subject: Re: [lpc2000] Cortex-M0 GPIO shadow registers

Ok, now I got it.

There are 4096 registers because they are the masks! pretty obvious...
I was thinking that you have to write in a mask for after using it, but they
are the mask already.
Thats right?

But my second questions stays.
What's the difference between:

LPC_GPIO3->MASKED_ACCESS[ 0x01 ] = 0x01; and LPC_GPIO3->DATA |= 0x01;

They both aren't single cycle?
AndrRairan.
On Mar 29, 2012, at 11:54 PM, Phil Young wrote:

> Hi Andr
>
> The whole point of masked access is to avoid conflicts with
> interrupts, and it's really easy to use in most cases.
>
> I use the following macros for setting and clearing bits.
>
> #define SET_GPIO(Port,Bits)(Port->MASKED_ACCESS[(Bits)] = (Bits))
> #define CLR_GPIO(Port,Bits)(Port->MASKED_ACCESS[(Bits)] = (0))
>
> Then I define macro's for the ports to make the code more portable, e.g.
> #define ISR_LED_ON SET_GPIO(LPC_GPIO3,0x1) // P3.0 #define ISR_LED_OFF
> CLR_GPIO(LPC_GPIO3,0x1)
>
> Of course if you change multiple bits you can simply clear the inverse
> using another SW mask then set the bits required ( a slightly more
> complex macro ).
> e.g.
>
> #define
> PUT_GPIO(Port,Value,Mask)(CLR_GPIO(Port,(Mask));SET_GPIO(Port,(Value))
> )
>
> Or slightly better but probably a CPU cycle longer
>
> #define PUT_GPIO(Port,Value,Mask)(CLR_GPIO(Port,(Mask) &
> ~(Value));SET_GPIO(Port,(Value)))
>
> This will of course lead to a couple of CPU cycles when the bits are
> neither the old or new value, but for most cases that doesn't matter.
>
> If you need to change multiple bits and they must transition
> "simultaneously" then you have to do as Olivier suggested but then
> also you need to disable interrupts before the sequence and re-enable
> them immediately afterwards.
>
> Also using the masked approach if you change bits in multiple threads
> you need to restore the mask in anything but the lowest priority
> thread, though this can be done after re-enabling interrupts so that
> you don't affect interrupt latency too much.
>
> Regards
>
> Phil.
>
> -----Original Message-----
> From: l... [mailto:l...] On
> Behalf Of Olivier Gautherot
> Sent: 30 March 2012 02:15
> To: l...
> Subject: Re: [lpc2000] Cortex-M0 GPIO shadow registers
>
> Hi Andr
>
> the mask register defines the bits that your operation is allowed to
modify.
> This way, you don't need read-modify-write cycles in software but
> simply set the mask and write your value.
>
> I would suggest you use the following sequence on ***ALL*** accesses
> (more on "***ALL***" below):
> - backup the mask register
> - set the mask to the value you want
> - write your value to the port (note that masked bits are not
> relevant, so you may simplify your code)
> - restore the mask
>
> By doing this on all accesses, you're likely not to worry about
> interrupts, except if your sequence needs to need a precise timing or
> if the interrupt may change the sequence. Likewise, you have a SET and
> CLEAR registers that can simplify single bits operations. It's actually a
nice feature.
>
> Hope it helps
> Cheers
> Olivier
>
> AndrRairan wrote:
> > Hello guys,
> >
> > I just can't figure out how the shadow registers works on Cortex-M0,
> > i'm
> using LPC11C14.
> >
> > I'm doing this way now, using CMSIS:
> > LPC_GPIO0->DATA |= (0x1<< bit);
> > or
> > LPC_GPIO0->DATA&= ~(0x1<< bit);
> >
> > writing directly on GPIOnDATA register As I could understand
> > writing
> directly to this register set all mask bits to 1 allowing directly access.
> > This way of doing is wrong or unsafe?
> > Why use masked access?
> >
> >
> > following...
> > this in on CMSIS file:
> >
> > union {
> > __IO uint32_t MASKED_ACCESS[4096]; /*!< Offset: 0x0000 to 0x3FFC
> Port data Register for pins PIOn_0 to PIOn_11 (R/W) */
> > struct {
> > uint32_t RESERVED0[4095];
> > __IO uint32_t DATA; /*!< Offset: 0x3FFC Port data
> Register (R/W) */
> > };
> >
> >
> > I read the pages 185 to 187, but I really can't understand it.
> >
> > How do I use the masks?
> > Wich one should I use?
> > Should I make some think like this:
> >
> > LPC_GPIO0->MASKED_ACCESS[ 0 ] = 0x01<< 2; LPC_GPIO0->DATA = 0xFF;
> >
> > This would set just the first bit?
> >
> >
> > Thanks,
> > AndrRairan.
> >
> >
> >
> >
Il 30/03/2012 05:56, AndrRairan ha scritto:
> Ok, now I got it.
>
> There are 4096 registers because they are the masks! pretty obvious...
> I was thinking that you have to write in a mask for after using it, but they are the mask already.
> Thats right?
>
> But my second questions stays.
> What's the difference between:
>
> LPC_GPIO3->MASKED_ACCESS[ 0x01 ] = 0x01;
> and
> LPC_GPIO3->DATA |= 0x01;
>
> They both aren't single cycle?
Both AREN'T single cycle, they are a sequence of movs, lsls, (orrs only
for the second with |=) and str.
str that is the last instruction performs the write to the register.

In general ARM architectures have no particular feeling with i/o
management. In Cortex-M series there is the possibility for the silicon
vendors to implement a bit-banding region that permits to access real
single bits as they were bytes so we can say that bit-banding is a
memory region devoted to bit access "shadowing" them as bytes so
Cortex-M processor don't need bit access special instructions.

This may be an advantage if you have to access just 1 bit but if you
need to access more bits it is better to access the 32bit registers
because to set bits performance of C compiler is the same, for toggling,
oring and anding there is always one more instruction.
> AndrRairan.
> On Mar 29, 2012, at 11:54 PM, Phil Young wrote:
>
>> Hi Andr
>>
>> The whole point of masked access is to avoid conflicts with interrupts, and
>> it's really easy to use in most cases.
>>
>> I use the following macros for setting and clearing bits.
>>
>> #define SET_GPIO(Port,Bits)(Port->MASKED_ACCESS[(Bits)] = (Bits))
>> #define CLR_GPIO(Port,Bits)(Port->MASKED_ACCESS[(Bits)] = (0))
>>
>> Then I define macro's for the ports to make the code more portable, e.g.
>> #define ISR_LED_ON SET_GPIO(LPC_GPIO3,0x1) // P3.0
>> #define ISR_LED_OFF CLR_GPIO(LPC_GPIO3,0x1)
>>
>> Of course if you change multiple bits you can simply clear the inverse using
>> another SW mask then set the bits required ( a slightly more complex macro
>> ).
>> e.g.
>>
>> #define
>> PUT_GPIO(Port,Value,Mask)(CLR_GPIO(Port,(Mask));SET_GPIO(Port,(Value)))
>>
>> Or slightly better but probably a CPU cycle longer
>>
>> #define PUT_GPIO(Port,Value,Mask)(CLR_GPIO(Port,(Mask) &
>> ~(Value));SET_GPIO(Port,(Value)))
>>
>> This will of course lead to a couple of CPU cycles when the bits are neither
>> the old or new value, but for most cases that doesn't matter.
>>
>> If you need to change multiple bits and they must transition
>> "simultaneously" then you have to do as Olivier suggested but then also you
>> need to disable interrupts before the sequence and re-enable them
>> immediately afterwards.
>>
>> Also using the masked approach if you change bits in multiple threads you
>> need to restore the mask in anything but the lowest priority thread, though
>> this can be done after re-enabling interrupts so that you don't affect
>> interrupt latency too much.
>>
>> Regards
>>
>> Phil.
>>
>> -----Original Message-----
>> From: l... [mailto:l...] On Behalf Of
>> Olivier Gautherot
>> Sent: 30 March 2012 02:15
>> To: l...
>> Subject: Re: [lpc2000] Cortex-M0 GPIO shadow registers
>>
>> Hi Andr
>>
>> the mask register defines the bits that your operation is allowed to modify.
>> This way, you don't need read-modify-write cycles in software but simply set
>> the mask and write your value.
>>
>> I would suggest you use the following sequence on ***ALL*** accesses (more
>> on "***ALL***" below):
>> - backup the mask register
>> - set the mask to the value you want
>> - write your value to the port (note that masked bits are not relevant, so
>> you may simplify your code)
>> - restore the mask
>>
>> By doing this on all accesses, you're likely not to worry about interrupts,
>> except if your sequence needs to need a precise timing or if the interrupt
>> may change the sequence. Likewise, you have a SET and CLEAR registers that
>> can simplify single bits operations. It's actually a nice feature.
>>
>> Hope it helps
>> Cheers
>> Olivier
>>
>> AndrRairan wrote:
>>> Hello guys,
>>>
>>> I just can't figure out how the shadow registers works on Cortex-M0, i'm
>> using LPC11C14.
>>> I'm doing this way now, using CMSIS:
>>> LPC_GPIO0->DATA |= (0x1<< bit);
>>> or
>>> LPC_GPIO0->DATA&= ~(0x1<< bit);
>>>
>>> writing directly on GPIOnDATA register As I could understand writing
>> directly to this register set all mask bits to 1 allowing directly access.
>>> This way of doing is wrong or unsafe?
>>> Why use masked access?
>>>
>>>
>>> following...
>>> this in on CMSIS file:
>>>
>>> union {
>>> __IO uint32_t MASKED_ACCESS[4096]; /*!< Offset: 0x0000 to 0x3FFC
>> Port data Register for pins PIOn_0 to PIOn_11 (R/W) */
>>> struct {
>>> uint32_t RESERVED0[4095];
>>> __IO uint32_t DATA; /*!< Offset: 0x3FFC Port data
>> Register (R/W) */
>>> };
>>>
>>>
>>> I read the pages 185 to 187, but I really can't understand it.
>>>
>>> How do I use the masks?
>>> Wich one should I use?
>>> Should I make some think like this:
>>>
>>> LPC_GPIO0->MASKED_ACCESS[ 0 ] = 0x01<< 2; LPC_GPIO0->DATA = 0xFF;
>>>
>>> This would set just the first bit?
>>>
>>>
>>> Thanks,
>>> AndrRairan.
>>>
>>>
>>>
>>>
You completely missed the point here.
In the masked operation preparing the value to be written using the masked
register access can take millions of cycles without causing a problem.
There is no hazard since the updating of the GPIO using the masked write
interface involves a single access to the GPIO register.

So for the purposes of hazard analysis this is an atomic operation.

Using a read modify write approach is not.

Regards

Phil.

-----Original Message-----
From: l... [mailto:l...] On Behalf Of
M. Manca
Sent: 30 March 2012 10:21
To: l...
Subject: Re: [lpc2000] Cortex-M0 GPIO shadow registers

Il 30/03/2012 05:56, AndrRairan ha scritto:
> Ok, now I got it.
>
> There are 4096 registers because they are the masks! pretty obvious...
> I was thinking that you have to write in a mask for after using it, but
they are the mask already.
> Thats right?
>
> But my second questions stays.
> What's the difference between:
>
> LPC_GPIO3->MASKED_ACCESS[ 0x01 ] = 0x01; and LPC_GPIO3->DATA |= 0x01;
>
> They both aren't single cycle?
Both AREN'T single cycle, they are a sequence of movs, lsls, (orrs only for
the second with |=) and str.
str that is the last instruction performs the write to the register.

In general ARM architectures have no particular feeling with i/o management.
In Cortex-M series there is the possibility for the silicon vendors to
implement a bit-banding region that permits to access real single bits as
they were bytes so we can say that bit-banding is a memory region devoted to
bit access "shadowing" them as bytes so Cortex-M processor don't need bit
access special instructions.

This may be an advantage if you have to access just 1 bit but if you need to
access more bits it is better to access the 32bit registers because to set
bits performance of C compiler is the same, for toggling, oring and anding
there is always one more instruction.
> AndrRairan.
> On Mar 29, 2012, at 11:54 PM, Phil Young wrote:
>
>> Hi Andr
>>
>> The whole point of masked access is to avoid conflicts with
>> interrupts, and it's really easy to use in most cases.
>>
>> I use the following macros for setting and clearing bits.
>>
>> #define SET_GPIO(Port,Bits)(Port->MASKED_ACCESS[(Bits)] = (Bits))
>> #define CLR_GPIO(Port,Bits)(Port->MASKED_ACCESS[(Bits)] = (0))
>>
>> Then I define macro's for the ports to make the code more portable, e.g.
>> #define ISR_LED_ON SET_GPIO(LPC_GPIO3,0x1) // P3.0 #define
>> ISR_LED_OFF CLR_GPIO(LPC_GPIO3,0x1)
>>
>> Of course if you change multiple bits you can simply clear the
>> inverse using another SW mask then set the bits required ( a slightly
>> more complex macro ).
>> e.g.
>>
>> #define
>> PUT_GPIO(Port,Value,Mask)(CLR_GPIO(Port,(Mask));SET_GPIO(Port,(Value)
>> ))
>>
>> Or slightly better but probably a CPU cycle longer
>>
>> #define PUT_GPIO(Port,Value,Mask)(CLR_GPIO(Port,(Mask) &
>> ~(Value));SET_GPIO(Port,(Value)))
>>
>> This will of course lead to a couple of CPU cycles when the bits are
>> neither the old or new value, but for most cases that doesn't matter.
>>
>> If you need to change multiple bits and they must transition
>> "simultaneously" then you have to do as Olivier suggested but then
>> also you need to disable interrupts before the sequence and re-enable
>> them immediately afterwards.
>>
>> Also using the masked approach if you change bits in multiple threads
>> you need to restore the mask in anything but the lowest priority
>> thread, though this can be done after re-enabling interrupts so that
>> you don't affect interrupt latency too much.
>>
>> Regards
>>
>> Phil.
>>
>> -----Original Message-----
>> From: l... [mailto:l...] On
>> Behalf Of Olivier Gautherot
>> Sent: 30 March 2012 02:15
>> To: l...
>> Subject: Re: [lpc2000] Cortex-M0 GPIO shadow registers
>>
>> Hi Andr
>>
>> the mask register defines the bits that your operation is allowed to
modify.
>> This way, you don't need read-modify-write cycles in software but
>> simply set the mask and write your value.
>>
>> I would suggest you use the following sequence on ***ALL*** accesses
>> (more on "***ALL***" below):
>> - backup the mask register
>> - set the mask to the value you want
>> - write your value to the port (note that masked bits are not
>> relevant, so you may simplify your code)
>> - restore the mask
>>
>> By doing this on all accesses, you're likely not to worry about
>> interrupts, except if your sequence needs to need a precise timing or
>> if the interrupt may change the sequence. Likewise, you have a SET
>> and CLEAR registers that can simplify single bits operations. It's
actually a nice feature.
>>
>> Hope it helps
>> Cheers
>> Olivier
>>
>> AndrRairan wrote:
>>> Hello guys,
>>>
>>> I just can't figure out how the shadow registers works on Cortex-M0,
>>> i'm
>> using LPC11C14.
>>> I'm doing this way now, using CMSIS:
>>> LPC_GPIO0->DATA |= (0x1<< bit);
>>> or
>>> LPC_GPIO0->DATA&= ~(0x1<< bit);
>>>
>>> writing directly on GPIOnDATA register As I could understand
>>> writing
>> directly to this register set all mask bits to 1 allowing directly
access.
>>> This way of doing is wrong or unsafe?
>>> Why use masked access?
>>>
>>>
>>> following...
>>> this in on CMSIS file:
>>>
>>> union {
>>> __IO uint32_t MASKED_ACCESS[4096]; /*!< Offset: 0x0000 to 0x3FFC
>> Port data Register for pins PIOn_0 to PIOn_11 (R/W) */
>>> struct {
>>> uint32_t RESERVED0[4095];
>>> __IO uint32_t DATA; /*!< Offset: 0x3FFC Port data
>> Register (R/W) */
>>> };
>>>
>>>
>>> I read the pages 185 to 187, but I really can't understand it.
>>>
>>> How do I use the masks?
>>> Wich one should I use?
>>> Should I make some think like this:
>>>
>>> LPC_GPIO0->MASKED_ACCESS[ 0 ] = 0x01<< 2; LPC_GPIO0->DATA = 0xFF;
>>>
>>> This would set just the first bit?
>>>
>>>
>>> Thanks,
>>> AndrRairan.
>>>
>>>
>>>
>>>
> In the masked operation preparing the value to be written using the masked
> register access can take millions of cycles without causing a problem.
> There is no hazard since the updating of the GPIO using the masked write
> interface involves a single access to the GPIO register.
>
> So for the purposes of hazard analysis this is an atomic operation.

Only when there the mask register is used by just one thread!

--

Wouter van Ooijen

-- -------
Van Ooijen Technische Informatica: www.voti.nl
consultancy, development, PICmicro products
docent Hogeschool van Utrecht: www.voti.nl/hvu
C++ on uC blog: http://www.voti.nl/erblog

Again, you missed the point.

With the LPC1114 the masked register write is an atomic operation.

The lower address bits are used as the mask, so a single write operation
performs a masked update of the register.

There is no physical mask register involved, it's a virtual mask.

It IS ALWAYS atomic.

Regards

Phil.

From: l... [mailto:l...] On Behalf Of
Wouter van Ooijen
Sent: 30 March 2012 11:18
To: l...
Subject: Re: [lpc2000] Cortex-M0 GPIO shadow registers

> In the masked operation preparing the value to be written using the masked
> register access can take millions of cycles without causing a problem.
> There is no hazard since the updating of the GPIO using the masked write
> interface involves a single access to the GPIO register.
>
> So for the purposes of hazard analysis this is an atomic operation.

Only when there the mask register is used by just one thread!

--

Wouter van Ooijen

-- -------
Van Ooijen Technische Informatica: www.voti.nl
consultancy, development, PICmicro products
docent Hogeschool van Utrecht: www.voti.nl/hvu
C++ on uC blog: http://www.voti.nl/erblog