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

取消
显示结果 
显示  仅  | 搜索替代 
您的意思是: 
已解决

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

跳至解决方案
3,836 次查看
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!

标记 (3)
0 项奖励
回复
1 解答
2,518 次查看
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.

 

在原帖中查看解决方案

标记 (1)
0 项奖励
回复
13 回复数
3,593 次查看
Alice_Yang
NXP TechSupport
NXP TechSupport

This case replied on salesforce.

 

0 项奖励
回复
3,678 次查看
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 项奖励
回复
3,674 次查看
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 项奖励
回复
3,822 次查看
Alice_Yang
NXP TechSupport
NXP TechSupport

Hello,

How about directly use C project,

 

0 项奖励
回复
3,821 次查看
danielholala
Senior Contributor II

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

标记 (1)
0 项奖励
回复
3,796 次查看
Alice_Yang
NXP TechSupport
NXP TechSupport

Hello danielholala,

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

 

BR

Alice

0 项奖励
回复
3,791 次查看
danielholala
Senior Contributor II

Alice,

please see attached.

Best regards,
Daniel

0 项奖励
回复
3,767 次查看
Alice_Yang
NXP TechSupport
NXP TechSupport
0 项奖励
回复
3,751 次查看
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 项奖励
回复
3,833 次查看
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 项奖励
回复
3,619 次查看
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 项奖励
回复
2,519 次查看
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.

 

标记 (1)
0 项奖励
回复
3,777 次查看
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 项奖励
回复