This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

nrf52840_bitfields.h library has strange macros

Hello, here is the question about nrf52840_bitfields.h. Is there any problem with macros definition? For example we have such definition:

/* Bit 20 : Enable differential mode */
#define SAADC_CH_CONFIG_MODE_Pos (20UL) /*!< Position of MODE field. */
#define SAADC_CH_CONFIG_MODE_Msk (0x1UL << SAADC_CH_CONFIG_MODE_Pos) /*!< Bit mask of MODE field. */
#define SAADC_CH_CONFIG_MODE_SE (0UL) /*!< Single-ended, PSELN will be ignored, negative input to SAADC shorted to GND */
#define SAADC_CH_CONFIG_MODE_Diff (1UL) /*!< Differential */

I expected to see definition of SAADC_CH_CONFIG_MODE_Diff, as 0x1UL << SAADC_CH_CONFIG_MODE_Pos, but this if definition of SAADC_CH_CONFIG_MODE_Msk.

So I can't just write NRF_SAADC->CH[n]. CONFIG |= SAADC_CH_CONFIG_MODE_Diff.

And I have to write  NRF_SAADC->CH[n]. CONFIG |= SAADC_CH_CONFIG_MODE_Diff << SAADC_CH_CONFIG_MODE_Pos instead.

So here is the question: does it really comfortable to work with such macros? For me it creates some difficulties with code reading and writing, maybe it is possible to fix this in the next generation libraries?

Parents Reply Children
  • Hi

    To be honest I agree that some of the simpler peripherals are just as easy to use directly, compared to going through nrfx, such as the TIMER, GPIOTE and PPI peripherals. 

    But for peripherals that are more complicated to use, such as the SAADC peripheral and all the serial interfaces (UART, SPI, TWI etc) I would strongly recommend using the nrfx drivers instead. These drivers have been tested and developed over a long period of time to make sure that they are reliable and bug free, and incorporate the required workarounds for errata issues relevant to that peripheral. 

    It is also limited how much support we can provide for debugging custom driver implementations if you have any issues, so again I would only do this for peripherals that are quick and easy to configure and use. 

    Back to the question of using the bitfields, the normal way to handle it for multi field registers is like this, separating each field on its own line for clarity. 

    For 1 bit fields there is also a small cheat you can use, and just use the _Msk define directly, rather than using the value and the pos defines. Some examples of this:

    // Enable channel 2
    NRF_PPI->CHENSET = PPI_CHENSET_CH2_Msk;

    // Set the COMPARE0 to CLEAR and COMPARE0 to STOP shortcuts
    NRF_TIMER0->SHORTS = TIMER_SHORTS_COMPARE0_CLEAR_Msk | TIMER_SHORTS_COMPARE0_STOP_Msk;

    Best regards
    Torbjørn

  • I see, I didn't want to write such a massive code, so that was my point when I have created this issue. Thank you for the answers.

  • Hi 

    Any code that will interface hardware registers directly should be put in a driver source file of some kind (similar to the nrfx drivers).  

    Then you can present a more streamlined and efficient API to the application, and you only need to work with the bitfields when you are working on the driver itself. 

    Best regards
    Torbjørn

Related