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

キャンセル
次の結果を表示 
表示  限定  | 次の代わりに検索 
もしかして: 

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

ソリューションへジャンプ
4,115件の閲覧回数
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,797件の閲覧回数
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,872件の閲覧回数
Alice_Yang
NXP TechSupport
NXP TechSupport

This case replied on salesforce.

 

0 件の賞賛
返信
3,957件の閲覧回数
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,953件の閲覧回数
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 件の賞賛
返信
4,101件の閲覧回数
Alice_Yang
NXP TechSupport
NXP TechSupport

Hello,

How about directly use C project,

 

0 件の賞賛
返信
4,100件の閲覧回数
danielholala
Senior Contributor II

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

タグ(1)
0 件の賞賛
返信
4,075件の閲覧回数
Alice_Yang
NXP TechSupport
NXP TechSupport

Hello danielholala,

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

 

BR

Alice

0 件の賞賛
返信
4,070件の閲覧回数
danielholala
Senior Contributor II

Alice,

please see attached.

Best regards,
Daniel

0 件の賞賛
返信
4,046件の閲覧回数
Alice_Yang
NXP TechSupport
NXP TechSupport
0 件の賞賛
返信
4,030件の閲覧回数
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 件の賞賛
返信
4,112件の閲覧回数
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,898件の閲覧回数
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,798件の閲覧回数
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 件の賞賛
返信
4,056件の閲覧回数
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 件の賞賛
返信