nuttx icon indicating copy to clipboard operation
nuttx copied to clipboard

How to use multiple RTC drivers?

Open takumiando opened this issue 2 years ago • 10 comments

Does not NuttX support multiple RTCs?

I want to use the internal and external RTCs, but the definitions of functions conflict each other at building.

/path/to/nuttx/arch/arm/src/chip/cxd56_rtc.c:433: multiple definition of `up_rtc_settime'; /path/to/nuttx/staging/libdrivers.a(ds3231.o):/path/to//nuttx/drivers/timers/ds3231.c:387: first defined here

Can I specify that which I use with any interfaces?

takumiando avatar Sep 14 '22 08:09 takumiando

@masayuki2009 @jerpelea any idea?

acassis avatar Sep 14 '22 11:09 acassis

From the arch perspective, yes you can just have one RTC hook up_rtc_xxx api. But you can expose multiple RTC through /dev/rtcx by: https://github.com/apache/incubator-nuttx/blob/master/include/nuttx/timers/rtc.h

xiaoxiang781216 avatar Sep 14 '22 11:09 xiaoxiang781216

@takumiando Could you tell us your intention to use multiple RTCs?

masayuki2009 avatar Sep 14 '22 13:09 masayuki2009

@masayuki2009 I(actually our team) develop two editions of the IoT devices(same SoC) running NuttX.
The version A uses internal RTC and the version B should use external one.

But I don't want to release two firmware binaries for each editions(for costs!). So I want to switch RTCs in a same firmware by EEPROM, status of GPIO, etc.

takumiando avatar Sep 14 '22 13:09 takumiando

So you don't have two RTC hardware at the same time, but want to hook the different RTC hardware to up_rtc_xxx at runtime. One approach is:

  1. Implement two RTC drivers by follow https://github.com/apache/incubator-nuttx/blob/master/include/nuttx/timers/rtc.h
  2. Let arch_rtc.c implement up_xxx for you by call up_rtc_set_lowerhalf: https://github.com/apache/incubator-nuttx/blob/master/include/nuttx/timers/arch_rtc.h#L45

In step 2, you check which RTC hardware exist and pass the different rtc_lowerhalf_s instance to up_rtc_set_lowerhalf.

xiaoxiang781216 avatar Sep 14 '22 15:09 xiaoxiang781216

@xiaoxiang781216

Thank you for your kind explanation! I understand your idea.

But many internal RTC lower-half drivers are enabled with each up_rtc_xxx() implementations at the same time.

For example: /arch/arm/src/stm32/Make.defs

ifeq ($(CONFIG_STM32_RTC),y)
CHIP_CSRCS += stm32_rtc.c
ifeq ($(CONFIG_RTC_ALARM),y)
CHIP_CSRCS += stm32_exti_alarm.c
endif
ifeq ($(CONFIG_RTC_PERIODIC),y)
CHIP_CSRCS += stm32_exti_wakeup.c
endif
ifeq ($(CONFIG_RTC_DRIVER),y)
CHIP_CSRCS += stm32_rtc_lowerhalf.c
endif
endif

In this case, I think that stm32_rtc.c(up_rtc_xxx() implementations) and arch_rtc.c conflict because of same function names.

Should I modify each Make.defs to build only lower-half drivers and arch_rtc.c?

takumiando avatar Sep 15 '22 01:09 takumiando

@xiaoxiang781216

Thank you for your kind explanation! I understand your idea.

But many internal RTC lower-half drivers are enabled with each up_rtc_xxx() implementations at the same time.

For example: /arch/arm/src/stm32/Make.defs

ifeq ($(CONFIG_STM32_RTC),y)
CHIP_CSRCS += stm32_rtc.c
ifeq ($(CONFIG_RTC_ALARM),y)
CHIP_CSRCS += stm32_exti_alarm.c
endif
ifeq ($(CONFIG_RTC_PERIODIC),y)
CHIP_CSRCS += stm32_exti_wakeup.c
endif
ifeq ($(CONFIG_RTC_DRIVER),y)
CHIP_CSRCS += stm32_rtc_lowerhalf.c
endif
endif

In this case, I think that stm32_rtc.c(up_rtc_xxx() implementations) and arch_rtc.c conflict because of same function names.

Should I modify each Make.defs to build only lower-half drivers and arch_rtc.c?

Yes, you can:

  1. Enable CONFIG_RTC_DRIVER but disable CONFIG_STM32_RTC to include stm32 lower-half driver only
  2. Enable your external RTC driver
  3. Enable arch_rtc driver by CONFIG_RTC_ARCH
  4. Check which hardware exist in your board file, and pass the exist instance to up_rtc_set_lowerhalf

xiaoxiang781216 avatar Sep 15 '22 02:09 xiaoxiang781216

@xiaoxiang781216

Thank you, I will try them!

By the way,

  • Why do lower-half drivers depend on up_rtc_xxx() implementations in Make.defs? We cannot enable only lower-half in current codes.
  • Why are NOT lower-half drivers for external RTCs(under /drivers/timers/) implemented? What is difference between internals and externals?

I don't understand these policies...

takumiando avatar Sep 15 '22 04:09 takumiando

@xiaoxiang781216

Thank you, I will try them!

By the way,

  • Why do lower-half drivers depend on up_rtc_xxx() implementations in Make.defs?

arch_rtc.c is introduced very later. Before that, all RTC driver need not only implement rtc_lowerhalf_s, but also up_rtc_xxx.

We cannot enable only lower-half in current codes.

  • Why are NOT lower-half drivers for external RTCs(under /drivers/timers/) implemented? What is difference between internals and externals?

I don't understand these policies...

Since internal RTC is part of SoC, which code should put into arch/xxx/yyy/. External RTC connected to SoC through I2C/1wire/SPI, which code should put into drivers/timer/.

xiaoxiang781216 avatar Sep 15 '22 05:09 xiaoxiang781216

arch_rtc.c is introduced very later. Before that, all RTC driver need not only implement rtc_lowerhalf_s, but also up_rtc_xxx.

So, lower-half drivers for external RTCs(under /drivers/timers/) are JUST NOT implemented yet, correct?

takumiando avatar Sep 15 '22 05:09 takumiando