Reply by "M. Manca" March 30, 20122012-03-30
Il 30/03/2012 16:14, Paul Curtis ha scritto:
>
>
> > Il 30/03/2012 15:10, AndrRairan ha scritto:
> > > So 11xx and 11Cxx have masked access and does not have SET, CLEAR and
> > "byte-mapped bits" and 11Uxx are the opposite?
> > >
> > > This part of 11Uxx would be a improvement over 11xx? I think is better
> > > deal with SET, CLEAR and principally "byte-mapped bits"...
> > It is strange, I checked manuals and lpc11*.h files and also I think
> it is
> > quite strange because seems that the older parts have a better GPIO
> > management, so as I said I need more time to investigate. Actually the
> > possibilities are:
> > 1. the manuals are wrong or incomplete (and the .h file reflects the
> > manual status) 2. there are different types of LPC11 microcontrollers
> > realizing GPIO in different ways.
>
> The older 111x parts have 12-bit GPIO ports and "Stellaris-like" masked
> access requires 14 address bits (12 real address bits, two zero bits for
> word addressing).
>
> The newer 11{U,E}xx parts have 24-bit or 32-bit GPIO ports and, hence,
> cannot use the same method of providing a mask in the address to pick the
> bits to affect--that would require an address space of at least 2^32 bits
> which is the entire 32-bit address space...
>
> So no, it is not strange that different methods are used at all.
>
It is strange they aren't compatible having very similar part numbers,
of course to be compatible they should add more 12bit i/o ports but
silicon area size is too important so probably NXP choose the solution
to don't implement the GPIO as 111x parts.
I would check LPC12xx situation, the 1st I used had the LPC111x
management but I don't know if is the same for other LPC12xx members.
> --
> Paul Curtis, Rowley Associates Ltd http://www.rowley.co.uk
> SolderCore running Defender... http://www.vimeo.com/25709426
>
>



An Engineer's Guide to the LPC2100 Series

Reply by Paul Curtis March 30, 20122012-03-30
> Il 30/03/2012 15:10, AndrRairan ha scritto:
> > So 11xx and 11Cxx have masked access and does not have SET, CLEAR and
> "byte-mapped bits" and 11Uxx are the opposite?
> >
> > This part of 11Uxx would be a improvement over 11xx? I think is better
> > deal with SET, CLEAR and principally "byte-mapped bits"
> It is strange, I checked manuals and lpc11*.h files and also I think it is
> quite strange because seems that the older parts have a better GPIO
> management, so as I said I need more time to investigate. Actually the
> possibilities are:
> 1. the manuals are wrong or incomplete (and the .h file reflects the
> manual status) 2. there are different types of LPC11 microcontrollers
> realizing GPIO in different ways.

The older 111x parts have 12-bit GPIO ports and "Stellaris-like" masked
access requires 14 address bits (12 real address bits, two zero bits for
word addressing).

The newer 11{U,E}xx parts have 24-bit or 32-bit GPIO ports and, hence,
cannot use the same method of providing a mask in the address to pick the
bits to affect--that would require an address space of at least 2^32 bits
which is the entire 32-bit address space...

So no, it is not strange that different methods are used at all.

--
Paul Curtis, Rowley Associates Ltd http://www.rowley.co.uk
SolderCore running Defender... http://www.vimeo.com/25709426

Reply by "M. Manca" March 30, 20122012-03-30
Il 30/03/2012 15:10, AndrRairan ha scritto:
> So 11xx and 11Cxx have masked access and does not have SET, CLEAR and "byte-mapped bits" and 11Uxx are the opposite?
>
> This part of 11Uxx would be a improvement over 11xx? I think is better deal with SET, CLEAR and principally "byte-mapped bits"
It is strange, I checked manuals and lpc11*.h files and also I think it
is quite strange because seems that the older parts have a better GPIO
management, so as I said I need more time to investigate. Actually the
possibilities are:
1. the manuals are wrong or incomplete (and the .h file reflects the
manual status)
2. there are different types of LPC11 microcontrollers realizing GPIO in
different ways.
> On Mar 30, 2012, at 9:40 AM, M. Manca wrote:
>
>> Phil,
>> I normally read the manuals, so I thought to rapidly search for other
>> LPC11xx user manuals and I find some info may be useful for both us and
>> I hope for others.
>>
>> There are some differences between different LPC11xx User Manuals so
>> this is a piece of LPC11U14 UM10462 user manual (I am using LPC11U14):
>>
>> 9.6.5 Recommended practices
>> The following lists some recommended uses for using the GPIO port registers:
>> . For initial setup after Reset or re-initialization, write the PORT
>> register(s).
>> . To change the state of one pin, write a Byte Pin or Word Pin register.
>> . To change the state of multiple pins at a time, write the SET and/or
>> CLR registers.
>> . To change the state of multiple pins in a tightly controlled
>> environment like a software
>> state machine, consider using the NOT register. This can require less
>> write operations
>> than SET and CLR.
>> . To read the state of one pin, read a Byte Pin or Word Pin register.
>> . To make a decision based on multiple pins, read and mask a PORT register.
>>
>> also it misses a lot of informations present on the UM10398 user manual
>> as this:
>>
>> 12.4.1 Write/read data operation
>> In order for software to be able to set GPIO bits without affecting any
>> other pins in a single
>> write operation, bits [13:2] of a 14-bit wide address bus are used to
>> create a 12-bit wide
>> mask for write and read operations on the 12 GPIO pins for each port.
>> Only GPIOnDATA
>> bits masked by 1 are affected by read and write operations. The masked
>> GPIOnDATA
>> register can be located anywhere between address offsets 0x0000 to
>> 0x3FFC in the
>> GPIOn address space. Reading and writing to the GPIOnDATA register at
>> address
>> 0x3FFC sets all masking bits to 1.
>>
>> And reading with some attention examples for both LPC1114 and LPC11U14 I
>> found that probably we have spoken about 2 different implementations so
>> we are both right in our specific situation, look these 2 GPIO
>> definitions, both are at 0x50000000:
>>
>> /**
>> * @brief Product name title=UM10462 Chapter title=LPC11U1x GPIO
>> Modification date=3/17/2011 Major revision=0 Minor revision=3 (GPIO_PORT)
>> */
>>
>> typedef struct {
>> union {
>> struct {
>> __IO uint8_t B0[32]; /*!< (@ 0x50000000)
>> Byte pin registers port 0; pins PIO0_0 to PIO0_31 */
>> __IO uint8_t B1[32]; /*!< (@ 0x50000020)
>> Byte pin registers port 1 */
>> };
>> __IO uint8_t B[64]; /*!< (@ 0x50000000) Byte
>> pin registers port 0/1 */
>> };
>> __I uint32_t RESERVED0[1008];
>> union {
>> struct {
>> __IO uint32_t W0[32]; /*!< (@ 0x50001000)
>> Word pin registers port 0 */
>> __IO uint32_t W1[32]; /*!< (@ 0x50001080)
>> Word pin registers port 1 */
>> };
>> __IO uint32_t W[64]; /*!< (@ 0x50001000) Word
>> pin registers port 0/1 */
>> };
>> uint32_t RESERVED1[960];
>> __IO uint32_t DIR[2]; /* 0x2000 */
>> uint32_t RESERVED2[30];
>> __IO uint32_t MASK[2]; /* 0x2080 */
>> uint32_t RESERVED3[30];
>> __IO uint32_t PIN[2]; /* 0x2100 */
>> uint32_t RESERVED4[30];
>> __IO uint32_t MPIN[2]; /* 0x2180 */
>> uint32_t RESERVED5[30];
>> __IO uint32_t SET[2]; /* 0x2200 */
>> uint32_t RESERVED6[30];
>> __O uint32_t CLR[2]; /* 0x2280 */
>> uint32_t RESERVED7[30];
>> __O uint32_t NOT[2]; /* 0x2300 */
>> } LPC_GPIO_Type;
>>
>> /*------------- General Purpose Input/Output (GPIO)
>> --------------------------*/
>> /** @addtogroup LPC11xx_GPIO LPC11xx General Purpose Input/Output
>> @{
>> */
>> typedef struct
>> {
>> 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) */
>> };
>> };
>> uint32_t RESERVED1[4096];
>> __IO uint32_t DIR; /*!< Offset: 0x8000 Data
>> direction Register (R/W) */
>> __IO uint32_t IS; /*!< Offset: 0x8004 Interrupt
>> sense Register (R/W) */
>> __IO uint32_t IBE; /*!< Offset: 0x8008 Interrupt
>> both edges Register (R/W) */
>> __IO uint32_t IEV; /*!< Offset: 0x800C Interrupt
>> event Register (R/W) */
>> __IO uint32_t IE; /*!< Offset: 0x8010 Interrupt
>> mask Register (R/W) */
>> __IO uint32_t RIS; /*!< Offset: 0x8014 Raw
>> interrupt status Register (R/ ) */
>> __IO uint32_t MIS; /*!< Offset: 0x8018 Masked
>> interrupt status Register (R/ ) */
>> __IO uint32_t IC; /*!< Offset: 0x801C Interrupt
>> clear Register (R/W) */
>> } LPC_GPIO_TypeDef;
>>
>> a little investigation could be necessary to discover if at 0x50003ffc
>> there are data registers not documented in LPC11U14 manual, could be,
>> but I don't understand why they aren't provided in the include file.
>> So, now I think you can understand why I need to access the mask
>> register. Due to my habit to use also LPC2xxx family I also wrote a
>> wrong info: the mask register is used with PORT and MPORT registers
>> instead SET and CLR register (as required in LPC2xxx family) both SET
>> and CLR may be used directly.
>>
>> Il 30/03/2012 13:30, Phil Young ha scritto:
>>>
>>> Why are you writing to the mask register?.
>>>
>>> You should study the user manual again, it's not necessary.
>>>
>>> See the compiler output below, there is NO write to the mask register.
>>>
>>> 51: ISR_LED_ON; // defined to null when LED's disabled
>>>
>>> 52:
>>>
>>> 53: //~~~~~~~~~~~~ ensure LCD reset is held long enough if LCD
>>> enabled
>>>
>>> 0x00000F02 4BFF LDR r3,[pc,#1020] ; // get address of register
>>> into R3
>>>
>>> 0x00000F04 B08E SUB sp,sp,#0x38 //This is not part of the
>>> operation, but optimization enables instruction re-ordering
>>>
>>> 0x00000F06 2101 MOVS r1,#0x01 // get bit to be set
>>>
>>> 0x00000F08 6059 STR r1,[r3,#0x04] // perform masked IO port update
>>>
>>> Taken from the user manual, this is dedicated HW for the GPIO ports,
>>> it does
>>> NOT use the bit-banding mechanism.
>>>
>>> Write/read data operation
>>>
>>> In order for software to be able to set GPIO bits without affecting any
>>> other pins in a single
>>>
>>> write operation, bits [13:2] of a 14-bit wide address bus are used to
>>> create
>>> a 12-bit wide
>>>
>>> mask for write and read operations on the 12 GPIO pins for each port. Only
>>> GPIOnDATA
>>>
>>> bits masked by 1 are affected by read and write operations. The masked
>>> GPIOnDATA
>>>
>>> register can be located anywhere between address offsets 0x0000 to
>>> 0x3FFC in
>>> the
>>>
>>> GPIOn address space. Reading and writing to the GPIOnDATA register at
>>> address
>>>
>>> 0x3FFC sets all masking bits to 1.
>>>
>>> Regards
>>>
>>> Phil.
>>>
>>> From: l...
>>> [mailto:l... ] On
>>> Behalf Of
>>> M. Manca
>>> Sent: 30 March 2012 12:03
>>> To: l...
>>> Subject: Re: [lpc2000] Cortex-M0 GPIO shadow registers
>>>
>>> Il 30/03/2012 12:31, Phil Young ha scritto:
>>>>
>>>> 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.
>>>>
>>> This is absolutely not true. If you look with attention to GPIO
>>> structure of LPC11U14 for instance you will see that the 2 i/o ports
>>> (PORT0 and PORT1) have both 32bit i/o bytes in the bit-banding region
>>> from 0x50000000 to 0x5000003f and then you will find that P0MASK and
>>> P1MASK at 0x50002080 and 0x50002084 to be used with P0SET/P0CLR and
>>> P1SET/P1CLR. So to use the mask feature you have to write before to the
>>> mask register and after to the set or clear register. This last write
>>> will change the i/o pin status. So it is an atomic operation made
>>> possible by the hardware registers but it is not a full atomic operation
>>> at all. The demonstration is simple; take a task that interrupts your
>>> operation after writing to the mask register and before writing to the
>>> data register and think what happen if that task alters the mask
>>> register. As I said in a previous post this is not a good way to
>>> programming but demonstrates that it is not a full atomic operation,
>>> they are 2 atomic operations 1 to write to the mask register and the 2nd
>>> to write the data using the set or the clr register.
>>>>
>>>> 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
>>>>
>>>>
>>>>
>>>>
>>>
>>>
>>>
>>>
>>>
>>
>
>
>
Reply by March 30, 20122012-03-30
So 11xx and 11Cxx have masked access and does not have SET, CLEAR and "byte-mapped bits" and 11Uxx are the opposite?

This part of 11Uxx would be a improvement over 11xx? I think is better deal with SET, CLEAR and principally "byte-mapped bits"
On Mar 30, 2012, at 9:40 AM, M. Manca wrote:

> Phil,
> I normally read the manuals, so I thought to rapidly search for other
> LPC11xx user manuals and I find some info may be useful for both us and
> I hope for others.
>
> There are some differences between different LPC11xx User Manuals so
> this is a piece of LPC11U14 UM10462 user manual (I am using LPC11U14):
>
> 9.6.5 Recommended practices
> The following lists some recommended uses for using the GPIO port registers:
> . For initial setup after Reset or re-initialization, write the PORT
> register(s).
> . To change the state of one pin, write a Byte Pin or Word Pin register.
> . To change the state of multiple pins at a time, write the SET and/or
> CLR registers.
> . To change the state of multiple pins in a tightly controlled
> environment like a software
> state machine, consider using the NOT register. This can require less
> write operations
> than SET and CLR.
> . To read the state of one pin, read a Byte Pin or Word Pin register.
> . To make a decision based on multiple pins, read and mask a PORT register.
>
> also it misses a lot of informations present on the UM10398 user manual
> as this:
>
> 12.4.1 Write/read data operation
> In order for software to be able to set GPIO bits without affecting any
> other pins in a single
> write operation, bits [13:2] of a 14-bit wide address bus are used to
> create a 12-bit wide
> mask for write and read operations on the 12 GPIO pins for each port.
> Only GPIOnDATA
> bits masked by 1 are affected by read and write operations. The masked
> GPIOnDATA
> register can be located anywhere between address offsets 0x0000 to
> 0x3FFC in the
> GPIOn address space. Reading and writing to the GPIOnDATA register at
> address
> 0x3FFC sets all masking bits to 1.
>
> And reading with some attention examples for both LPC1114 and LPC11U14 I
> found that probably we have spoken about 2 different implementations so
> we are both right in our specific situation, look these 2 GPIO
> definitions, both are at 0x50000000:
>
> /**
> * @brief Product name title=UM10462 Chapter title=LPC11U1x GPIO
> Modification date=3/17/2011 Major revision=0 Minor revision=3 (GPIO_PORT)
> */
>
> typedef struct {
> union {
> struct {
> __IO uint8_t B0[32]; /*!< (@ 0x50000000)
> Byte pin registers port 0; pins PIO0_0 to PIO0_31 */
> __IO uint8_t B1[32]; /*!< (@ 0x50000020)
> Byte pin registers port 1 */
> };
> __IO uint8_t B[64]; /*!< (@ 0x50000000) Byte
> pin registers port 0/1 */
> };
> __I uint32_t RESERVED0[1008];
> union {
> struct {
> __IO uint32_t W0[32]; /*!< (@ 0x50001000)
> Word pin registers port 0 */
> __IO uint32_t W1[32]; /*!< (@ 0x50001080)
> Word pin registers port 1 */
> };
> __IO uint32_t W[64]; /*!< (@ 0x50001000) Word
> pin registers port 0/1 */
> };
> uint32_t RESERVED1[960];
> __IO uint32_t DIR[2]; /* 0x2000 */
> uint32_t RESERVED2[30];
> __IO uint32_t MASK[2]; /* 0x2080 */
> uint32_t RESERVED3[30];
> __IO uint32_t PIN[2]; /* 0x2100 */
> uint32_t RESERVED4[30];
> __IO uint32_t MPIN[2]; /* 0x2180 */
> uint32_t RESERVED5[30];
> __IO uint32_t SET[2]; /* 0x2200 */
> uint32_t RESERVED6[30];
> __O uint32_t CLR[2]; /* 0x2280 */
> uint32_t RESERVED7[30];
> __O uint32_t NOT[2]; /* 0x2300 */
> } LPC_GPIO_Type;
>
> /*------------- General Purpose Input/Output (GPIO)
> --------------------------*/
> /** @addtogroup LPC11xx_GPIO LPC11xx General Purpose Input/Output
> @{
> */
> typedef struct
> {
> 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) */
> };
> };
> uint32_t RESERVED1[4096];
> __IO uint32_t DIR; /*!< Offset: 0x8000 Data
> direction Register (R/W) */
> __IO uint32_t IS; /*!< Offset: 0x8004 Interrupt
> sense Register (R/W) */
> __IO uint32_t IBE; /*!< Offset: 0x8008 Interrupt
> both edges Register (R/W) */
> __IO uint32_t IEV; /*!< Offset: 0x800C Interrupt
> event Register (R/W) */
> __IO uint32_t IE; /*!< Offset: 0x8010 Interrupt
> mask Register (R/W) */
> __IO uint32_t RIS; /*!< Offset: 0x8014 Raw
> interrupt status Register (R/ ) */
> __IO uint32_t MIS; /*!< Offset: 0x8018 Masked
> interrupt status Register (R/ ) */
> __IO uint32_t IC; /*!< Offset: 0x801C Interrupt
> clear Register (R/W) */
> } LPC_GPIO_TypeDef;
>
> a little investigation could be necessary to discover if at 0x50003ffc
> there are data registers not documented in LPC11U14 manual, could be,
> but I don't understand why they aren't provided in the include file.
> So, now I think you can understand why I need to access the mask
> register. Due to my habit to use also LPC2xxx family I also wrote a
> wrong info: the mask register is used with PORT and MPORT registers
> instead SET and CLR register (as required in LPC2xxx family) both SET
> and CLR may be used directly.
>
> Il 30/03/2012 13:30, Phil Young ha scritto:
> >
> >
> > Why are you writing to the mask register?.
> >
> > You should study the user manual again, it's not necessary.
> >
> > See the compiler output below, there is NO write to the mask register.
> >
> > 51: ISR_LED_ON; // defined to null when LED's disabled
> >
> > 52:
> >
> > 53: //~~~~~~~~~~~~ ensure LCD reset is held long enough if LCD
> > enabled
> >
> > 0x00000F02 4BFF LDR r3,[pc,#1020] ; // get address of register
> > into R3
> >
> > 0x00000F04 B08E SUB sp,sp,#0x38 //This is not part of the
> > operation, but optimization enables instruction re-ordering
> >
> > 0x00000F06 2101 MOVS r1,#0x01 // get bit to be set
> >
> > 0x00000F08 6059 STR r1,[r3,#0x04] // perform masked IO port update
> >
> > Taken from the user manual, this is dedicated HW for the GPIO ports,
> > it does
> > NOT use the bit-banding mechanism.
> >
> > Write/read data operation
> >
> > In order for software to be able to set GPIO bits without affecting any
> > other pins in a single
> >
> > write operation, bits [13:2] of a 14-bit wide address bus are used to
> > create
> > a 12-bit wide
> >
> > mask for write and read operations on the 12 GPIO pins for each port. Only
> > GPIOnDATA
> >
> > bits masked by 1 are affected by read and write operations. The masked
> > GPIOnDATA
> >
> > register can be located anywhere between address offsets 0x0000 to
> > 0x3FFC in
> > the
> >
> > GPIOn address space. Reading and writing to the GPIOnDATA register at
> > address
> >
> > 0x3FFC sets all masking bits to 1.
> >
> > Regards
> >
> > Phil.
> >
> > From: l...
> > [mailto:l... ] On
> > Behalf Of
> > M. Manca
> > Sent: 30 March 2012 12:03
> > To: l...
> > Subject: Re: [lpc2000] Cortex-M0 GPIO shadow registers
> >
> > Il 30/03/2012 12:31, Phil Young ha scritto:
> > >
> > >
> > > 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.
> > >
> > This is absolutely not true. If you look with attention to GPIO
> > structure of LPC11U14 for instance you will see that the 2 i/o ports
> > (PORT0 and PORT1) have both 32bit i/o bytes in the bit-banding region
> > from 0x50000000 to 0x5000003f and then you will find that P0MASK and
> > P1MASK at 0x50002080 and 0x50002084 to be used with P0SET/P0CLR and
> > P1SET/P1CLR. So to use the mask feature you have to write before to the
> > mask register and after to the set or clear register. This last write
> > will change the i/o pin status. So it is an atomic operation made
> > possible by the hardware registers but it is not a full atomic operation
> > at all. The demonstration is simple; take a task that interrupts your
> > operation after writing to the mask register and before writing to the
> > data register and think what happen if that task alters the mask
> > register. As I said in a previous post this is not a good way to
> > programming but demonstrates that it is not a full atomic operation,
> > they are 2 atomic operations 1 to write to the mask register and the 2nd
> > to write the data using the set or the clr register.
> > >
> > >
> > > 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
> > >
> > >
> > >
> > >
> >
> >
> >
> >
> >
> >
>
>
>
>



Reply by "M. Manca" March 30, 20122012-03-30
Phil,
I normally read the manuals, so I thought to rapidly search for other
LPC11xx user manuals and I find some info may be useful for both us and
I hope for others.

There are some differences between different LPC11xx User Manuals so
this is a piece of LPC11U14 UM10462 user manual (I am using LPC11U14):

9.6.5 Recommended practices
The following lists some recommended uses for using the GPIO port registers:
. For initial setup after Reset or re-initialization, write the PORT
register(s).
. To change the state of one pin, write a Byte Pin or Word Pin register.
. To change the state of multiple pins at a time, write the SET and/or
CLR registers.
. To change the state of multiple pins in a tightly controlled
environment like a software
state machine, consider using the NOT register. This can require less
write operations
than SET and CLR.
. To read the state of one pin, read a Byte Pin or Word Pin register.
. To make a decision based on multiple pins, read and mask a PORT register.

also it misses a lot of informations present on the UM10398 user manual
as this:

12.4.1 Write/read data operation
In order for software to be able to set GPIO bits without affecting any
other pins in a single
write operation, bits [13:2] of a 14-bit wide address bus are used to
create a 12-bit wide
mask for write and read operations on the 12 GPIO pins for each port.
Only GPIOnDATA
bits masked by 1 are affected by read and write operations. The masked
GPIOnDATA
register can be located anywhere between address offsets 0x0000 to
0x3FFC in the
GPIOn address space. Reading and writing to the GPIOnDATA register at
address
0x3FFC sets all masking bits to 1.

And reading with some attention examples for both LPC1114 and LPC11U14 I
found that probably we have spoken about 2 different implementations so
we are both right in our specific situation, look these 2 GPIO
definitions, both are at 0x50000000:

/**
* @brief Product name title=UM10462 Chapter title=LPC11U1x GPIO
Modification date=3/17/2011 Major revision=0 Minor revision=3 (GPIO_PORT)
*/

typedef struct {
union {
struct {
__IO uint8_t B0[32]; /*!< (@ 0x50000000)
Byte pin registers port 0; pins PIO0_0 to PIO0_31 */
__IO uint8_t B1[32]; /*!< (@ 0x50000020)
Byte pin registers port 1 */
};
__IO uint8_t B[64]; /*!< (@ 0x50000000) Byte
pin registers port 0/1 */
};
__I uint32_t RESERVED0[1008];
union {
struct {
__IO uint32_t W0[32]; /*!< (@ 0x50001000)
Word pin registers port 0 */
__IO uint32_t W1[32]; /*!< (@ 0x50001080)
Word pin registers port 1 */
};
__IO uint32_t W[64]; /*!< (@ 0x50001000) Word
pin registers port 0/1 */
};
uint32_t RESERVED1[960];
__IO uint32_t DIR[2]; /* 0x2000 */
uint32_t RESERVED2[30];
__IO uint32_t MASK[2]; /* 0x2080 */
uint32_t RESERVED3[30];
__IO uint32_t PIN[2]; /* 0x2100 */
uint32_t RESERVED4[30];
__IO uint32_t MPIN[2]; /* 0x2180 */
uint32_t RESERVED5[30];
__IO uint32_t SET[2]; /* 0x2200 */
uint32_t RESERVED6[30];
__O uint32_t CLR[2]; /* 0x2280 */
uint32_t RESERVED7[30];
__O uint32_t NOT[2]; /* 0x2300 */
} LPC_GPIO_Type;

/*------------- General Purpose Input/Output (GPIO)
--------------------------*/
/** @addtogroup LPC11xx_GPIO LPC11xx General Purpose Input/Output
@{
*/
typedef struct
{
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) */
};
};
uint32_t RESERVED1[4096];
__IO uint32_t DIR; /*!< Offset: 0x8000 Data
direction Register (R/W) */
__IO uint32_t IS; /*!< Offset: 0x8004 Interrupt
sense Register (R/W) */
__IO uint32_t IBE; /*!< Offset: 0x8008 Interrupt
both edges Register (R/W) */
__IO uint32_t IEV; /*!< Offset: 0x800C Interrupt
event Register (R/W) */
__IO uint32_t IE; /*!< Offset: 0x8010 Interrupt
mask Register (R/W) */
__IO uint32_t RIS; /*!< Offset: 0x8014 Raw
interrupt status Register (R/ ) */
__IO uint32_t MIS; /*!< Offset: 0x8018 Masked
interrupt status Register (R/ ) */
__IO uint32_t IC; /*!< Offset: 0x801C Interrupt
clear Register (R/W) */
} LPC_GPIO_TypeDef;

a little investigation could be necessary to discover if at 0x50003ffc
there are data registers not documented in LPC11U14 manual, could be,
but I don't understand why they aren't provided in the include file.
So, now I think you can understand why I need to access the mask
register. Due to my habit to use also LPC2xxx family I also wrote a
wrong info: the mask register is used with PORT and MPORT registers
instead SET and CLR register (as required in LPC2xxx family) both SET
and CLR may be used directly.
Il 30/03/2012 13:30, Phil Young ha scritto:
>
>
> Why are you writing to the mask register?.
>
> You should study the user manual again, it's not necessary.
>
> See the compiler output below, there is NO write to the mask register.
>
> 51: ISR_LED_ON; // defined to null when LED's disabled
>
> 52:
>
> 53: //~~~~~~~~~~~~ ensure LCD reset is held long enough if LCD
> enabled
>
> 0x00000F02 4BFF LDR r3,[pc,#1020] ; // get address of register
> into R3
>
> 0x00000F04 B08E SUB sp,sp,#0x38 //This is not part of the
> operation, but optimization enables instruction re-ordering
>
> 0x00000F06 2101 MOVS r1,#0x01 // get bit to be set
>
> 0x00000F08 6059 STR r1,[r3,#0x04] // perform masked IO port update
>
> Taken from the user manual, this is dedicated HW for the GPIO ports,
> it does
> NOT use the bit-banding mechanism.
>
> Write/read data operation
>
> In order for software to be able to set GPIO bits without affecting any
> other pins in a single
>
> write operation, bits [13:2] of a 14-bit wide address bus are used to
> create
> a 12-bit wide
>
> mask for write and read operations on the 12 GPIO pins for each port. Only
> GPIOnDATA
>
> bits masked by 1 are affected by read and write operations. The masked
> GPIOnDATA
>
> register can be located anywhere between address offsets 0x0000 to
> 0x3FFC in
> the
>
> GPIOn address space. Reading and writing to the GPIOnDATA register at
> address
>
> 0x3FFC sets all masking bits to 1.
>
> Regards
>
> Phil.
>
> From: l...
> [mailto:l... ] On
> Behalf Of
> M. Manca
> Sent: 30 March 2012 12:03
> To: l...
> Subject: Re: [lpc2000] Cortex-M0 GPIO shadow registers
>
> Il 30/03/2012 12:31, Phil Young ha scritto:
> >
> >
> > 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.
> >
> This is absolutely not true. If you look with attention to GPIO
> structure of LPC11U14 for instance you will see that the 2 i/o ports
> (PORT0 and PORT1) have both 32bit i/o bytes in the bit-banding region
> from 0x50000000 to 0x5000003f and then you will find that P0MASK and
> P1MASK at 0x50002080 and 0x50002084 to be used with P0SET/P0CLR and
> P1SET/P1CLR. So to use the mask feature you have to write before to the
> mask register and after to the set or clear register. This last write
> will change the i/o pin status. So it is an atomic operation made
> possible by the hardware registers but it is not a full atomic operation
> at all. The demonstration is simple; take a task that interrupts your
> operation after writing to the mask register and before writing to the
> data register and think what happen if that task alters the mask
> register. As I said in a previous post this is not a good way to
> programming but demonstrates that it is not a full atomic operation,
> they are 2 atomic operations 1 to write to the mask register and the 2nd
> to write the data using the set or the clr register.
> >
> >
> > 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
> >
> >
> >
> >
>
>



Reply by Phil Young March 30, 20122012-03-30
Sorry Wouter,

No offence intended.

Regards

Phil.

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

> Hi Wouter,
> It's quite common to have multiple tasks needing to set / clear bits on
the
> same IO register, particularly when using standard parts since you have to
> work within the constraints of pin multiplexing.

Take care who you are addressing: you are responding to a response to my
post, not to my post itself!

--

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



Reply by Wouter van Ooijen March 30, 20122012-03-30
> Hi Wouter,
> It's quite common to have multiple tasks needing to set / clear bits on the
> same IO register, particularly when using standard parts since you have to
> work within the constraints of pin multiplexing.

Take care who you are addressing: you are responding to a response to my
post, not to my post itself!

--

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

Reply by March 30, 20122012-03-30
OK, now I got it! It make sense and I agree that it's a very elegant solution.

Either if I use the same make operation inside and outside an interrupt it will be safe.

On Mar 30, 2012, at 8:30 AM, Phil Young wrote:

> Why are you writing to the mask register?.
>
> You should study the user manual again, it's not necessary.
>
> See the compiler output below, there is NO write to the mask register.
>
> 51: ISR_LED_ON; // defined to null when LED's disabled
>
> 52:
>
> 53: //~~~~~~~~~~~~ ensure LCD reset is held long enough if LCD
> enabled
>
> 0x00000F02 4BFF LDR r3,[pc,#1020] ; // get address of register
> into R3
>
> 0x00000F04 B08E SUB sp,sp,#0x38 //This is not part of the
> operation, but optimization enables instruction re-ordering
>
> 0x00000F06 2101 MOVS r1,#0x01 // get bit to be set
>
> 0x00000F08 6059 STR r1,[r3,#0x04] // perform masked IO port update
>
> Taken from the user manual, this is dedicated HW for the GPIO ports, it does
> NOT use the bit-banding mechanism.
>
> Write/read data operation
>
> In order for software to be able to set GPIO bits without affecting any
> other pins in a single
>
> write operation, bits [13:2] of a 14-bit wide address bus are used to create
> a 12-bit wide
>
> mask for write and read operations on the 12 GPIO pins for each port. Only
> GPIOnDATA
>
> bits masked by 1 are affected by read and write operations. The masked
> GPIOnDATA
>
> register can be located anywhere between address offsets 0x0000 to 0x3FFC in
> the
>
> GPIOn address space. Reading and writing to the GPIOnDATA register at
> address
>
> 0x3FFC sets all masking bits to 1.
>
> Regards
>
> Phil.
>
> From: l... [mailto:l...] On Behalf Of
> M. Manca
> Sent: 30 March 2012 12:03
> To: l...
> Subject: Re: [lpc2000] Cortex-M0 GPIO shadow registers
>
> Il 30/03/2012 12:31, Phil Young ha scritto:
> >
> >
> > 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.
> >
> This is absolutely not true. If you look with attention to GPIO
> structure of LPC11U14 for instance you will see that the 2 i/o ports
> (PORT0 and PORT1) have both 32bit i/o bytes in the bit-banding region
> from 0x50000000 to 0x5000003f and then you will find that P0MASK and
> P1MASK at 0x50002080 and 0x50002084 to be used with P0SET/P0CLR and
> P1SET/P1CLR. So to use the mask feature you have to write before to the
> mask register and after to the set or clear register. This last write
> will change the i/o pin status. So it is an atomic operation made
> possible by the hardware registers but it is not a full atomic operation
> at all. The demonstration is simple; take a task that interrupts your
> operation after writing to the mask register and before writing to the
> data register and think what happen if that task alters the mask
> register. As I said in a previous post this is not a good way to
> programming but demonstrates that it is not a full atomic operation,
> they are 2 atomic operations 1 to write to the mask register and the 2nd
> to write the data using the set or the clr register.
> >
> >
> > 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
> >
> >
> >
> >
>
>



Reply by Phil Young March 30, 20122012-03-30
A couple of important points.

I use CMSIS where it makes sense, but CMSIS does not IMPOSE anything, its
just there to make life a little easier.



The CMSIS files provided by a vendor for their HW must follow certain
guidelines, but they are free to provide whatever functions they like.



The NXP provided CMSIS header include register definitions providing full
support of the masked write operations, I use these register definitions.



See the following from the NXP provided CMSIS compliant headers for the
LPC1114.



/*------------- General Purpose Input/Output (GPIO)
--------------------------*/

/** @addtogroup LPC11xx_GPIO LPC11xx General Purpose Input/Output

@{

*/

typedef struct

{

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) */

};

};

uint32_t RESERVED1[4096];

__IO uint32_t DIR; /*!< Offset: 0x8000 Data direction
Register (R/W) */

__IO uint32_t IS; /*!< Offset: 0x8004 Interrupt sense
Register (R/W) */

__IO uint32_t IBE; /*!< Offset: 0x8008 Interrupt both
edges Register (R/W) */

__IO uint32_t IEV; /*!< Offset: 0x800C Interrupt event
Register (R/W) */

__IO uint32_t IE; /*!< Offset: 0x8010 Interrupt mask
Register (R/W) */

__IO uint32_t RIS; /*!< Offset: 0x8014 Raw interrupt
status Register (R/ ) */

__IO uint32_t MIS; /*!< Offset: 0x8018 Masked interrupt
status Register (R/ ) */

__IO uint32_t IC; /*!< Offset: 0x801C Interrupt clear
Register (R/W) */

} LPC_GPIO_TypeDef;

/*@}*/ /* end of group LPC11xx_GPIO */



Regards



Phil.



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





Il 30/03/2012 11:50, Phil Young ha scritto:
>
>
> 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.
>
I wasn't very clear. I told about bit-banding that permit atomic
operations; when I say 32bit registers I mean in this context 32bit i/o
registers so using them with mask registers, another form of atomic
operations to access i/o registers.

So to be more clear: when you need to set or clear more then 1 bit on a
register it is better to use 32bit registers using properly mask
registers, when you need to set or clear 1 bit only you can use bit-banding.

Technically speaking, CMSIS as imposed by ARM to silicon vendors doesn't
make possible to optimize too much i/o access.

If you search i/o definition files for ARM7 or ARM9 microcontrollers as
LPC2148 you could see that i/o registers are defined in a different way
using #defines with the address embedded on them. The main difference is
when the compiler computes the destination address. If you wish lowest
access time you should write a define with the destination address
embedded on it so there is no need to calculate it at run time.

Actually CMSIS compliant i/o definition for Cortex-M microcontrollers
require use of union of structs and arrays, so the destination address
have to be calculated at run time.
> 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.
> >>>
> >>>
> >>>
> >>>
Reply by Phil Young March 30, 20122012-03-30
Why are you writing to the mask register?.

You should study the user manual again, it's not necessary.

See the compiler output below, there is NO write to the mask register.

51: ISR_LED_ON; // defined to null when LED's disabled

52:

53: //~~~~~~~~~~~~ ensure LCD reset is held long enough if LCD
enabled

0x00000F02 4BFF LDR r3,[pc,#1020] ; // get address of register
into R3

0x00000F04 B08E SUB sp,sp,#0x38 //This is not part of the
operation, but optimization enables instruction re-ordering

0x00000F06 2101 MOVS r1,#0x01 // get bit to be set

0x00000F08 6059 STR r1,[r3,#0x04] // perform masked IO port update

Taken from the user manual, this is dedicated HW for the GPIO ports, it does
NOT use the bit-banding mechanism.

Write/read data operation

In order for software to be able to set GPIO bits without affecting any
other pins in a single

write operation, bits [13:2] of a 14-bit wide address bus are used to create
a 12-bit wide

mask for write and read operations on the 12 GPIO pins for each port. Only
GPIOnDATA

bits masked by 1 are affected by read and write operations. The masked
GPIOnDATA

register can be located anywhere between address offsets 0x0000 to 0x3FFC in
the

GPIOn address space. Reading and writing to the GPIOnDATA register at
address

0x3FFC sets all masking bits to 1.

Regards

Phil.

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

Il 30/03/2012 12:31, Phil Young ha scritto:
> 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.
>
This is absolutely not true. If you look with attention to GPIO
structure of LPC11U14 for instance you will see that the 2 i/o ports
(PORT0 and PORT1) have both 32bit i/o bytes in the bit-banding region
from 0x50000000 to 0x5000003f and then you will find that P0MASK and
P1MASK at 0x50002080 and 0x50002084 to be used with P0SET/P0CLR and
P1SET/P1CLR. So to use the mask feature you have to write before to the
mask register and after to the set or clear register. This last write
will change the i/o pin status. So it is an atomic operation made
possible by the hardware registers but it is not a full atomic operation
at all. The demonstration is simple; take a task that interrupts your
operation after writing to the mask register and before writing to the
data register and think what happen if that task alters the mask
register. As I said in a previous post this is not a good way to
programming but demonstrates that it is not a full atomic operation,
they are 2 atomic operations 1 to write to the mask register and the 2nd
to write the data using the set or the clr register.
> 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
>
>