C++ and CMSIS USART Drivers: compiler error on assignment

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

C++ and CMSIS USART Drivers: compiler error on assignment

Jump to solution
3,394 Views
danielholala
Senior Contributor II

Hi there,

I'm starting a new C++ project with LPC5526. Further I'm using CMSIS USART drivers for the first time.

My problem:

This simple assignment (in my code at line no. 65) fails:

	ARM_USART_STATUS status1 = FLEXCOMM0_PERIPHERAL.GetStatus();

The compiler emits three error messages:

../source/LPC55S28_Project_CMSIS-Test.cpp: In function 'int main()':
../source/LPC55S28_Project_CMSIS-Test.cpp:65:60: error: no matching function for call to '_ARM_USART_STATUS(ARM_USART_STATUS)'
65 | ARM_USART_STATUS status1 = FLEXCOMM0_PERIPHERAL.GetStatus();

and

...\workspace\LPC55S28_Project_CMSIS-Test\CMSIS_driver/Driver_USART.h:155:25: note: conversion of argument 1 would be ill-formed:
../source/LPC55S28_Project_CMSIS-Test.cpp:65:59: error: binding reference of type 'const _ARM_USART_STATUS&' to 'ARM_USART_STATUS' {aka 'volatile _ARM_USART_STATUS'} discards qualifiers
65 | ARM_USART_STATUS status1 = FLEXCOMM0_PERIPHERAL.GetStatus();
I

and

...\workspace\LPC55S28_Project_CMSIS-Test\CMSIS_driver/Driver_USART.h:155:25: note: conversion of argument 1 would be ill-formed:
../source/LPC55S28_Project_CMSIS-Test.cpp:65:59: error: binding reference of type '_ARM_USART_STATUS&&' to 'ARM_USART_STATUS' {aka 'volatile _ARM_USART_STATUS'} discards qualifiers
65 | ARM_USART_STATUS status1 = FLEXCOMM0_PERIPHERAL.GetStatus();

All error messages relate to this assignment in line 65.

To reproduce:

  • Create new project based on a recent SDK (e.g. LPC55S28):
    • Select C++ project
    • Select Components -> CMSIS-Drivers -> usart_cmsis
  • Use Clocks Tool to enable Flexcomm0 clock (FXCOMCLK0)
  • Use Pins Tool to enable a pin for FC0_TXD and a pin for FC0_RXD
  • Use Peripherals Tool to enable USART0 @ Flexcomm0
    • Tools may need to be enabled first
    • In Components bar, click "+" next to Peripheral Drivers (Universal)
    • Select "FLEXCOMM_USART_CMSIS"
    • In configuration dialog, check "Enable RX" and "Enable TX"
  • In your main project file (where main() is defined) add
    • void USART0_SignalEvent(uint32_t event) { }
  • Finally add the line above.
  • Compile.

 

Any ideas? Thanks!

Tags (3)
0 Kudos
1 Solution
2,076 Views
danielholala
Senior Contributor II

Hi,

this issue seems fixed.

I just had a look at SDK_2.x_LPC5526 2.13.0 (after I installed MCUXpresso IDE 11.7.0).

Now CMSIS Driver_USART.h is included as V2.4, i.e., with volatile dropped from ARM_USART_STATUS and ARM_USART_MODEM_STATUS.

 

View solution in original post

Tags (1)
0 Kudos
13 Replies
3,151 Views
Alice_Yang
NXP TechSupport
NXP TechSupport

This case replied on salesforce.

 

0 Kudos
3,236 Views
Alice_Yang
NXP TechSupport
NXP TechSupport

Hello Daniel.

 

Not recommend remove  "volatile".How about assign data separately:
    status1.rx_busy = FLEXCOMM0_PERIPHERAL.GetStatus().rx_busy;
    status1.tx_busy = FLEXCOMM0_PERIPHERAL.GetStatus().tx_busy;

0 Kudos
3,232 Views
danielholala
Senior Contributor II

Hello Alice,

Thank you for your reply. 

Why do you recommend not to remove "volatile"? Please advise.

What was the reason for adding "volatile" to the struct? The struct is returned by value (copied), so "volatile" seems superfluous.

Why not move the "volatile" declaration to each member instead? I suggested this earlier but you did not respond to it.

I appreciate your support and I'm looking forward to your response.

Best regards,
Daniel

 

 

 

0 Kudos
3,380 Views
Alice_Yang
NXP TechSupport
NXP TechSupport

Hello,

How about directly use C project,

 

0 Kudos
3,379 Views
danielholala
Senior Contributor II

I want to use (a subset of) C++ features in my program.

Tags (1)
0 Kudos
3,354 Views
Alice_Yang
NXP TechSupport
NXP TechSupport

Hello danielholala,

Please attach your whole project ,I will help to check on my side.

 

BR

Alice

0 Kudos
3,349 Views
danielholala
Senior Contributor II

Alice,

please see attached.

Best regards,
Daniel

0 Kudos
3,309 Views
danielholala
Senior Contributor II

Hi Alice,

I'm pretty sure that it's not a "C++ grammar issue". I checked your references and I think they don't apply here.

The issue arises because the C++ compiler employs a stricter type checking. Further, the implicitly created constructor does not support copying volatile values.

See:

https://stackoverflow.com/questions/17217300/why-am-i-not-provided-with-a-default-copy-constructor-f...

https://stackoverflow.com/questions/49367852/volatile-struct-struct-not-possible-why

 

Solution: remove "volatile" qualifier from typedef. See also my other posting, please.

Best regards,
Daniel

0 Kudos
3,391 Views
danielholala
Senior Contributor II

For your information, ARM_USART_STATUS is defined in "CMSIS_driver/Driver_USART.h" as follows

typedef volatile struct _ARM_USART_STATUS {
  uint32_t tx_busy          : 1;        ///< Transmitter busy flag
  uint32_t rx_busy          : 1;        ///< Receiver busy flag
  uint32_t tx_underflow     : 1;        ///< Transmit data underflow detected (cleared on start of next send operation)
  uint32_t rx_overflow      : 1;        ///< Receive data overflow detected (cleared on start of next receive operation)
  uint32_t rx_break         : 1;        ///< Break detected on receive (cleared on start of next receive operation)
  uint32_t rx_framing_error : 1;        ///< Framing error detected on receive (cleared on start of next receive operation)
  uint32_t rx_parity_error  : 1;        ///< Parity error detected on receive (cleared on start of next receive operation)
  uint32_t reserved         : 25;
} ARM_USART_STATUS;

 

 

 

I can query specific members directly, e.g., 

	uint32_t busy = FLEXCOMM0_PERIPHERAL.GetStatus().tx_busy;

 This compiles without errors.

0 Kudos
3,177 Views
danielholala
Senior Contributor II

Hello everybody,

I checked the original source files on Github that served as templates for NXP's CMSIS drivers.

The type ARM_USART_STATUS is defined in this file:

https://github.com/ARM-software/CMSIS_5/blob/master/CMSIS/Driver/Include/Driver_USART.h

and the definition omits the volatile qualifier.

The changelog reads:

/* History:
 *  Version 2.4
 *    Removed volatile from ARM_USART_STATUS and ARM_USART_MODEM_STATUS
 *  Version 2.3
 *    ARM_USART_STATUS and ARM_USART_MODEM_STATUS made volatile
 /*

 

I'd appreciate if you'd forward this information to the SDK team.

Thanks.

Best regards,
Dan

 

0 Kudos
2,077 Views
danielholala
Senior Contributor II

Hi,

this issue seems fixed.

I just had a look at SDK_2.x_LPC5526 2.13.0 (after I installed MCUXpresso IDE 11.7.0).

Now CMSIS Driver_USART.h is included as V2.4, i.e., with volatile dropped from ARM_USART_STATUS and ARM_USART_MODEM_STATUS.

 

Tags (1)
0 Kudos
3,335 Views
danielholala
Senior Contributor II

Hi everybody,

If  the "volatile" qualifier from ARM_USART_STATUS is removed, the program compiles.

I wonder why "volatile" had been added to this struct in the first place. Usually it's required when a variable may be changed from outside of the current execution flow (i.e., memory mapped registers, interrupt service routines, multithreading).  I don't see why it's needed here.

Further, if need be, volatile could be added to specific members that require the use of the "volatile" qualifier, i.e.: 

typedef struct _ARM_USART_STATUS {
  volatile uint32_t tx_busy          : 1;        ///< Transmitter busy flag
  volatile uint32_t rx_busy          : 1;        ///< Receiver busy flag
  volatile uint32_t tx_underflow     : 1;        ///< Transmit data underflow detected (cleared on start of next send operation)
  volatile uint32_t rx_overflow      : 1;        ///< Receive data overflow detected (cleared on start of next receive operation)
  volatile uint32_t rx_break         : 1;        ///< Break detected on receive (cleared on start of next receive operation)
  volatile uint32_t rx_framing_error : 1;        ///< Framing error detected on receive (cleared on start of next receive operation)
  volatile uint32_t rx_parity_error  : 1;        ///< Parity error detected on receive (cleared on start of next receive operation)
  uint32_t reserved         : 25;
} ARM_USART_STATUS;

 This compiles, too.

 

0 Kudos