Rx UART interrupt when toggling LED pin

Go To Last Post
5 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0


Having a strange issue.  I'm using an AVR128DA32.

UART2: Tx on PF0 and Rx on PF1.

LED: PF5

 

Whenever I turn off the LED (in HAL_Blinky_Toggle() below) I get a Rx complete interrupt (USART2_RXC_vect).  Turning on the LED does not cause an interrupt.  Only thought was that it has to do with writing to the shared port F but I'm not sure why that might be.

 

 

 

I tried using VPORT but this did not fix it.  I've also tried various forms of bit manipulation with VPORT and was suprised that most did not actually compile to CBI/SBI.  For example, only this first one compiled as expected:

 

These did not:

 

 

 

So two questions:

1. Why am I getting this Rx interrupt?

2. Why is VPORT not compiling as I'd expect it to?

 

Appreciate your help in advance!

Best regards,

Dan

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1


You have selected PF4 and PF5 as ports for USART2.

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Re (2):

 

I think if you attempt to write a function that toggles a bit using SBI/CBI your expectations will swiftly align with the compiler output.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

2. Why is VPORT not compiling as I'd expect it to?

 

was suprised that most did not actually compile to CBI/SBI

If you make them static (static inline or static inline __attribute((always_inline)) ), you have a very good chance to get sbi/cbi, but still no guarantee the compiler will oblige if it cannot see at compile time your choice of port/pin for any reason.

 

In your particular case, your usage is the problem-

out |= bm -> can be reduced to sbi (which is what you are getting)

out &= bm -> cannot be reduced to cbi because you are clearing 7 bits (notice you forgot the ~), so you get read/andi/write

out ^= bm -> cannot be reduced to sbi or cbi as you are xoring all 8 bits (or rather, there is no single bit xor instruction and the compiler is not going to make the leap to using the vport IN to get you a toggle even if bm is a single bit)

 

Your mcu has OUTSET/OUTCLR/OUTTGL in addition to the DIR versions which you are already using, so use these registers to always get atomic setting/clearing of pins. Your compiler can do whatever it wants and you will get atomic as its no longer dependent on what instructions are used, but what registers are used. The downside is a couple clock cycles which ends up being unimportant. The upside is you do not have to check up on the compiler to see if your vport usage results in cbi/sbi, plus you have more options in passing ports/pins around to functions without the worry you will be losing atomic. Upside > downside. They added these registers for a good reason, and its a good idea to use them.

 

 

 

//with static, will most likely be inlined (not a called function)

//but then not usable by other source files unless this is put in a header

//you can also init on use in many cases (set to output in this case)

//so you do not need to specifically init the pin

static

void Hal_Blinky_Toggle(){

    BLINKY_PORT.DIRSET = BLINKY_PINbm;

    BLINKY_PORT.OUTTGL = BLINKY_PINbm;

 

Last Edited: Tue. Jul 26, 2022 - 02:03 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks for the great feedback.  

 

@kabasan, exactly right.  I'm supporting a few micros and that was incorrectly copied from another.  Thanks.

 

Regarding CBI/SBI, very informative.  @curtvm, I experimented as you said with |/&/^/~ and compilation was exactly as you suggested.  Makes sense now.  Thanks again!  I also found the VPORT section of this page to be very helpful.