Discussion:
[PIC] Setting part of a port on a PIC32?
Neil
2018-02-21 14:41:17 UTC
Permalink
I'm looking for a fast way to set one byte of PORTD on a PIC32MX ...
RB8:15, without affecting the other nibble/bits. I'm using UNoptimized
XC32.

Yes, I can save the state of the other bits as they change around the
code and reassemble a full port word when I need to change the upper
nibble, but that seems like it would waste a lot of cycles.
Since the instruction set allows for OR'ing and AND'ing port bits
(writing to specific addresses for the port it seems), I'm wondering if
ANDing with a mask and then ORing in C translate directly to the
respective instructions?

Or is there a better/more clever way to do this?

Cheers,
-Neil.
--
http://www.piclist.com/techref/piclist PIC/SX FAQ & list archive
View/change your membership options at
http://mailman.mit.edu/mailman/listinfo/piclist
Isaac M. Bavaresco
2018-02-21 14:50:49 UTC
Permalink
Neil,

It is perfectly possible to do byte-wise accesses on the IO ports:

*(unsigned char*)0xBF886061    = Value;    /* LATB[8:15] = Value */

Cheers,

Isaac
Post by Neil
I'm looking for a fast way to set one byte of PORTD on a PIC32MX ...
RB8:15, without affecting the other nibble/bits. I'm using UNoptimized
XC32.
Yes, I can save the state of the other bits as they change around the
code and reassemble a full port word when I need to change the upper
nibble, but that seems like it would waste a lot of cycles.
Since the instruction set allows for OR'ing and AND'ing port bits
(writing to specific addresses for the port it seems), I'm wondering if
ANDing with a mask and then ORing in C translate directly to the
respective instructions?
Or is there a better/more clever way to do this?
Cheers,
-Neil.
---
Este email foi escaneado pelo Avast antivírus.
https://www.avast.com/antivirus
--
http://www.piclist.com/techref/piclist PIC/SX FAQ & list archive
View/change your membership options at
http
Neil
2018-02-21 15:39:53 UTC
Permalink
Was not aware of this... nice.
Curious, where is the documented?

Cheers,
-Neil.
Neil,
*(unsigned char*)0xBF886061 = Value; /* LATB[8:15] = Value */
Cheers,
Isaac
Post by Neil
I'm looking for a fast way to set one byte of PORTD on a PIC32MX ...
RB8:15, without affecting the other nibble/bits. I'm using UNoptimized
XC32.
Yes, I can save the state of the other bits as they change around the
code and reassemble a full port word when I need to change the upper
nibble, but that seems like it would waste a lot of cycles.
Since the instruction set allows for OR'ing and AND'ing port bits
(writing to specific addresses for the port it seems), I'm wondering if
ANDing with a mask and then ORing in C translate directly to the
respective instructions?
Or is there a better/more clever way to do this?
Cheers,
-Neil.
---
Este email foi escaneado pelo Avast antivírus.
https://www.avast.com/antivirus
--
http://www.piclist.com/techref/piclist PIC/SX FAQ & list archive
View/change your membership options at
http://mailm
r***@bredband.net
2018-02-22 12:05:26 UTC
Permalink
 
If you are not accessing a whole byte, the correct way to set/clear/invert bits in an sfr register for a PIC32 without affecting other bits in the same register is to use the SET, CLR or INV offset addresses for the register and a mask. Even though the REGISTER.BIT=value construct can be used it takes more instructions and is not atomic for a PIC32 (as it is for 8 and 16 bit PICS).
If you use REGISTER.BIT=value you can get caught by the Read Modify Write problem (because it is not atomic). This is true for registers where bits can be changed from both hardware and software (e.g. interrupt flags for several interrupts that shares the same register) and where several interrupts and/or main code accesses bits in the same register.

Look in the header file for your processor to see the correct mask definitions for individual bits. You can OR several mask definitions to manipulate several bits in one instruction.

/Ruben

Den Wed, 21 Feb 2018 10:39:53 -0500, Neil skrev:

Was not aware of this... nice.
Curious, where is the documented?

Cheers,
-Neil.



On 2/21/2018 9:50 AM, Isaac M. Bavaresco wrote:
> Neil,
>
> It is perfectly possible to do byte-wise accesses on the IO ports:
>
> *(unsigned char*)0xBF886061 = Value; /* LATB[8:15] = Value */
>
> Cheers,
>
> Isaac
>
>
>
> Em 21/02/2018 11:41, Neil escreveu:
>> I'm looking for a fast way to set one byte of PORTD on a PIC32MX ...
>> RB8:15, without affecting the other nibble/bits. I'm using UNoptimized
>> XC32.
>>
>> Yes, I can save the state of the other bits as they change around the
>> code and reassemble a full port word when I need to change the upper
>> nibble, but that seems like it would waste a lot of cycles.
>> Since the instruction set allows for OR'ing and AND'ing port bits
>> (writing to specific addresses for the port it seems), I'm wondering if
>> ANDing with a mask and then ORing in C translate directly to the
>> respective instructions?
>>
>> Or is there a better/more clever way to do this?
>>
>> Cheers,
>> -Neil.
>>
>
> ---
> Este email foi escaneado pelo Avast antivírus.
> https://www.avast.com/antivirus
>

--
http://www.piclist.com/techref/piclist PIC/SX FAQ & list archive
View/change your membership options at
http://mailman.mit.edu/mailman/listinfo/piclist
 
--
http://www.piclist.com/techref/piclist PIC/SX FAQ & list archive
View/change your membership options at
ht
Isaac M. Bavaresco
2018-02-22 12:30:20 UTC
Permalink
Post by r***@bredband.net
If you are not accessing a whole byte, the correct way to set/clear/invert bits in an sfr register for a PIC32 without affecting other bits in the same register is to use the SET, CLR or INV offset addresses for the register and a mask.
It works well if you are only setting or clearing bits, but if you need
to do both (clearing some bits and setting others) then it takes more
instructions also.
Post by r***@bredband.net
Even though the REGISTER.BIT=value construct can be used it takes more instructions and is not atomic for a PIC32 (as it is for 8 and 16 bit PICS).
If you use REGISTER.BIT=value you can get caught by the Read Modify Write problem (because it is not atomic).
Atomicity is not the same thing as RMW. RMW happens when you are reading
the pins and setting the latches in the same instruction. Older PIC16Fs
only have the PORT register, so when you do PORTx |= Value, the
processor reads the *pins*, does the OR and then writes the result back
to the output latch register. If some pin is heavily capacitance-loaded
then RMW is more probable.

The newer PIC16F, PIC18F, PIC24/dsPIC and PIC32 all have the LATx
registers, that solves the RMW problem. It is still possible do RMW on
the PORTx registers and suffer from RMW issues, but then it is a
programmer's option.
Post by r***@bredband.net
This is true for registers where bits can be changed from both hardware and software (e.g. interrupt flags for several interrupts that shares the same register) and where several interrupts and/or main code accesses bits in the same register.
Look in the header file for your processor to see the correct mask definitions for individual bits. You can OR several mask definitions to manipulate several bits in one instruction.
The problems caused by atomicity/interrupts can be solved by disabling
the offending interrupts during the operation. It usually is not a
problem because the operation can take just a few instructions and the
interrupt jitter introduced can be just a few micro- or nano-seconds.


Cheers,
Isaac


---
Este email foi escaneado pelo Avast antivírus.
https://www.avast.com/antivirus
--
http://www.piclist.com/techref/piclist PIC/SX FAQ & list archive
View/change your membership options at
http://mailman.mit
r***@bredband.net
2018-02-22 14:10:38 UTC
Permalink
Post by Isaac M. Bavaresco
It works well if you are only setting or clearing bits, but if you need
to do both (clearing some bits and setting others) then it takes more
instructions also.
Then you only need 2 instructions.
Post by Isaac M. Bavaresco
Atomicity is not the same thing as RMW. RMW happens when you are reading
the pins and setting the latches in the same instruction.
Yes it is not the same thing as for reading, modifying and writing back port
registers for 8 or 16 bit PICs

but REGISTER.BIT=value for a PIC32 is actually a
non atomic Read, Modify and Write set of operations. If you do this on a register
that holds e.g. interrupt flags for several interrupts, you can accidentally clear an
interrupt flag that has been set by the hardware just after you have read the
register but before it is written back. This is actually an error that is pretty hard
to debug since it can only

happen in a very narrow time space. You can also
accidentally set an interrupt flag i

f you have a higher priority interrupt
interrupting a lower priority interrupt just when it clears its interrupt flag which
can cause the higher priority interrupt to be executed again when it shouldn't.
Post by Isaac M. Bavaresco
The problems caused by atomicity/interrupts can be solved by disabling
the offending interrupts during the operation. It usually is not a
problem because the operation can take just a few instructions and the
interrupt jitter introduced can be just a few micro- or nano-seconds.
A critical section will only help when it is software only that is involved (software


clearing interrupt flags) but it will not help when hardware is also involved (software
clearing interrupt flag inside a critical section will not stop the hardware to set
another interrupt flag in the same register). Only atomicity will help for that.




/Ruben
Post by Isaac M. Bavaresco
If you are not accessing a whole byte, the correct way to set/clear/invert bits in an sfrregister for a PIC32 without affecting other bits in the same register is to use the SET, CLR or INV offset addresses for the register and a mask.
It works well if you are only setting or clearing bits, but if you need
to do both (clearing some bits and setting others) then it takes more
instructions also.
Post by Isaac M. Bavaresco
Even though the REGISTER.BIT=value construct can be used it takes more instructions and is not atomic for a PIC32 (as it is for 8 and 16 bit PICS).
If you use REGISTER.BIT=value you can get caught by the Read Modify Write problem (because it is not atomic).
Atomicity is not the same thing as RMW. RMW happens when you are reading
the pins and setting the latches in the same instruction. Older PIC16Fs
only have the PORT register, so when you do PORTx |= Value, the
processor reads the *pins*, does the OR and then writes the result back
to the output latch register. If some pin is heavily capacitance-loaded
then RMW is more probable.

The newer PIC16F, PIC18F, PIC24/dsPIC and PIC32 all have the LATx
registers, that solves the RMW problem. It is still possible do RMW on
the PORTx registers and suffer from RMW issues, but then it is a
programmer's option.
Post by Isaac M. Bavaresco
This is true for registers where bits can be changed from both hardware and software (e.g. interrupt flags for several interrupts that sharesthe same register) and where several interrupts and/or main code accesses bits in the same register.
Look in the header file for your processor to see the correct mask definitions for individual bits. You can OR several mask definitions to manipulate several bits in one instruction.
The problems caused by atomicity/interrupts can be solved by disabling
the offending interrupts during the operation. It usually is not a
problem because the operation can take just a few instructions and the
interrupt jitter introduced can be just a few micro- or nano-seconds.


Cheers,
Isaac


---
Este email foi escaneado pelo Avast antivírus.
https://www.avast.com/antivirus


--
http://www.piclist.com/techref/piclist PIC/SX FAQ & list archive
View/change your membership options at
http://mailman.mit.edu/mailman/listinfo/piclist
--
http://www.piclist.com/techref/piclist PIC/SX FAQ & list archive
View/change your membership opt
Isaac M. Bavaresco
2018-02-22 14:35:49 UTC
Permalink
Post by Isaac M. Bavaresco
It works well if you are only setting or clearing bits, but if you need
Post by Isaac M. Bavaresco
to do both (clearing some bits and setting others) then it takes more
instructions also.
Then you only need 2 instructions.
Perhaps more, supposing you have a mask for the bits you want to change
and the new value of the bits already in their correct positions:

xSET    = Value & Mask;
xCLR    = ~Value & Mask;
Post by Isaac M. Bavaresco
Post by Isaac M. Bavaresco
Atomicity is not the same thing as RMW. RMW happens when you are reading
the pins and setting the latches in the same instruction.
Yes it is not the same thing as for reading, modifying and writing back port
registers for 8 or 16 bit PICs
but REGISTER.BIT=value for a PIC32 is actually a
non atomic Read, Modify and Write set of operations. If you do this on a register
that holds e.g. interrupt flags for several interrupts, you can accidentally clear an
interrupt flag that has been set by the hardware just after you have read the
register but before it is written back. This is actually an error that is pretty hard
to debug since it can only
happen in a very narrow time space. You can also
accidentally set an interrupt flag i
f you have a higher priority interrupt
interrupting a lower priority interrupt just when it clears its interrupt flag which
can cause the higher priority interrupt to be executed again when it shouldn't.
This is one point where the datasheets always cover very well and the
manufacturers create their hardware very carefully.

Some architectures clear interrupt flags by writing ones to the bits
that need to be cleared, then you can simply do:

MyIntFlag    = INTREG & MYINTMASK;
INTREG    = MyIntFlag;
if( MyIntFlag ) ...

Others simply keep each flag alone or together with other
device-specific register.

Some, like the PIC16Fs allow RMW instructions operate in their interrupt
flag registers.
Post by Isaac M. Bavaresco
Post by Isaac M. Bavaresco
The problems caused by atomicity/interrupts can be solved by disabling
the offending interrupts during the operation. It usually is not a
problem because the operation can take just a few instructions and the
interrupt jitter introduced can be just a few micro- or nano-seconds.
A critical section will only help when it is software only that is involved (software
clearing interrupt flags) but it will not help when hardware is also involved (software
clearing interrupt flag inside a critical section will not stop the hardware to set
another interrupt flag in the same register). Only atomicity will help for that.
To solve issues related to the hardware, the manufacturers offer canned
solutions that they explain and enforce their use.

Cheers,
Isaac



---
Este email foi escaneado pelo Avast antivírus.
https://www.avast.com/antivirus
--
http://www.piclist.com/techref/piclist PIC/SX FAQ & list archive
View/change your membership options at
http://mailman.mit.edu/mailman/l
Loading...