Beware that this post is related to an SDK in maintenance mode
More Info: Consider nRF Connect SDK for new designs
This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

Are there any examples to program the nrf52 at a lower level bypassing all the bloat/ 10 layers of abstraction in the SDK? TIA.

Are there any examples to program the nrf52 at a lower level bypassing all the bloat/ 10 layers of abstraction in the SDK? TIA.

I often hear that things were more straight forward in the old SDKs ( ver 9 or so). can someone with experience in those please chime in?

Parents
  • Hello,

    You are probably not surprised, but I would not say that everything was easier in the older SDKs. What sort of application are you looking at? A very basic example would be the SDK17.0.2\examples\peripheral\pin_change_int, but I suspect that is not what you are looking for. 

    Is there a particular reason why you would want to bypass the bloat abstraction layers?

    Best regards,

    Edvin

  • Hello Edvin, thank you for getting back.

    My main reasons by bypassing multiple layers of abstraction are:

    1. As my project grows, I do not want to keep merging examples. Today, I need a simple code that does periodic advertising. Nothing more. But next I need to add uart, down the road I need to add i2c and at some point flash storage. Yes, each of these have been beautifully captured (individually) in an example. But I find the process of merging examples, cumbersome. I have tried using winmerge to carefully combine sdk_config.h, not reliable. I have tried to pull up two cmsis tools and go over it line by line, yet I run into issues. I have tried using the master copy of sdk_config.h and it is missing PRS(peripheral resource). Its not even a true master copy. I want to acknowledge that the individual examples are great to do a demo. My clients were wowed and I won a contract. The on going maintenance of code is hard. 

    I plan to use NRF52 as the main MCU in many non wireless application, since the nrf hardware in my opinion is better compared to many other MCU vendors. So I need a fool proof way to rapidly maintain my products/ code base without running into issues. 

    2. Collaboration as a team is hard. I have to send code to my colleagues, who will now have to install the same sdk and place the code under example and compile. Each developer needs to download a 100mb SDK, insert my files at the right point in order to work. 

    3. The current examples tend to do this : example code --> library --> driver --> driver mapping(legacy/ nrfx) --> hal. In the process each library uses 2 or 3 other libraries, which I don't need (eg say logging). As an example the uart peripheral uses atomic, balloc, and a bevy of other libraries, which don't contribute much. 

    Of all the reasons, #1, merging examples is the main pain. Its quite embarrassing to tell my clients I have uart working, but I need 7 days to figure out how to merge it into mainline code. It takes time away from product development and forces one to spend time understanding the inner workings of the sdk, and this is not a one time investment, it must repeated each time a new module is to be added. 

  • I believe that most of the frustration is related to the sdk_config.h file, and I understand. It is a bit tedious to merge these. What I usually do is to start with an example using the softdevice (if you intend to use BLE now or in the future for this project), and then add whatever peripheral that you need. Start with the files that are the highest layer (containing the functions used from your main.c file), and then keep adding whatever they need. If you want to strip something out, feel free to do so, but test this in the peripheral example first, so that you know it is working the way you intend to.

    Then, when it stops complaining about the missing header files as you have made sure they are all in your include path, it will probably start complaining on the missing functions. Make sure that the .c files are included (check in the peripheral example for that peripheral where it is found). If it is already added and the compiler can't find it, it is because of the header guard (sdk_config.h definitions). If you copy paste from the peripheral example, then it likely already have the correct things turned on. Now, you can't just copy the entire file. Look at the specific file that you are trying to include, and try to copy including the correct "indents" (<e>, <h>, <q>, </e>, </h>, </q>), in case you are using CMSIS or the configuration wizard in Keil.

    Regarding collaboration. As long as you have the project the correct amount of folders down from the SDK root folder, it doesn't really matter where you put it. The include paths are typically 6 folders up (SDK root) and then the paths to the files. As long as the people you are working with keeps the project in the same folder location, and you don't change any files outside your project folder, I believe you should be fine.

    FYI: I use to copy the projects that I want to test into a folder called "test" in the "SDK\examples\" folder. This way, I can copy any example into this folder, and it has the same relative path to the driver files. 

    So yes. It is a bit tedious, and I am sorry. There is not much I can do about that, unfortunately, other than trying to give some hints on the way. 

    As for the BLE part of your application: Do you only intend to beacon? Or do you intend to have it connectable sometime in the future? The reason I ask is because there are two advertising approaches. You have probably seen the ble_app_beacon example. This is a very simplified beacon example, and works great for just that. However, if you intend to make the device connectable, I would suggest that you start with another example. Either one that looks like your final product, or the ble_app_template example. The reason for this is that if you use the ble_app_beacon example, you'll have one extra job porting the advertisements to the advertising module used in connectable devices (which the ble_app_beacon example doesn't use).

    Best regards,

    Edvin

  • Hi Edvin, 

    I will try again to be careful while merging the sdk_config.h. Just to give you an example, I have been stuck last 3 days adding uart to a BLE central example. So one followup question:

    1. Can a bad sdk_config.h result in run time errors? In my case im 99.99% my uart is not working due to a bad sdk_config.h, but it compiles fine. 

    I also wanted to share that my long term plan is to move to bare metal programming for peripherals due to the sdk complexities. I hope this feedback can be passed on to the sdk team.  On the other hand, the nrf52 datasheet is very well written and easy to read. 

    Now coming to BLE. I have both examples (beacon and advertisements) running fine. 

    My question would be: if I made calls directly to the Soft Device API can I bypass the sdk_config.h? I'm willing to put in the time to understand how the BLE stack works, if I can avoid dealing the with sdk_config. My plan is to setup the system at register level, do all the inits at register level. Could you please confirm if I can avoid the sdk_config, by making direct calls to the SD API. 

    Thanks

    Hari

  • Hello Hari,

    The only thing that sdk_config.h does is setting a bunch of definitions. If you look up a particular definition, you will see that it is being used somewhere in the drivers or libraries. 

     

    haricane said:
    1. Can a bad sdk_config.h result in run time errors?

     Yes. E.g. a sdk_config configuring the UART baudrate can cause runtime errors if the baudrate doesn't match the incoming data. What sort of runtime errors are you seeing? Are you lacking data? Do you get the ERROR_COMMUNICATION event?

    haricane said:
    if I made calls directly to the Soft Device API can I bypass the sdk_config.h?

     

    You can do everything quite bare metal if you like, but that looks like it would require a lot of work, and I don't think we can help you as efficiently with that part, since that job is already done when writing the libraries and drivers. 

  • Hello Edwin, 

    Thanks, your previous responses have helped me understand the sdk_config.h a bit better. I was able to get UART working. I believe UART 0 instance was not enabled. I've also come up with a few ways to work around the sdk_config.h without going bare-metal and still reusing much of the nrf driver and library work. 

    Thank you and to your colleagues for your help. This can be closed out.  

  • I guess it is also worth mentioning a file that may confuse even more, which is the apply_old_config.h. You should at least look at it. When the nrfx drivers were introduced, they added these new NRFX_... definitions in sdk_config.h, which are used in the drivers. However, even though you set them in sdk_config.h, they will be overwritten in apply_old_config.h, to the value that the non-NRFX definitions are set to. Just look at the file, and you should see how it does this. Either, you need to use the "legacy" definitions, or you need to remove them and use the NRFX definitions. (It is the same drivers that are used either way). This may cause confusion, because setting:
    NRFX_UART0_ENABLED to 1 may be undone because UART0_ENABLED was set to 0, and this part from apply_old_config:

    #if defined(UART_ENABLED)
    
    #undef NRFX_UART_ENABLED
    #define NRFX_UART_ENABLED   (UART_ENABLED && NRFX_UART0_ENABLED)
    #undef NRFX_UARTE_ENABLED
    #define NRFX_UARTE_ENABLED  (UART_ENABLED && (NRFX_UARTE0_ENABLED || NRFX_UARTE1_ENABLED))
    
    #if defined(UART0_ENABLED)
    #undef NRFX_UART0_ENABLED
    #define NRFX_UART0_ENABLED   (UART0_ENABLED && UART_LEGACY_SUPPORT)
    #undef NRFX_UARTE0_ENABLED
    #define NRFX_UARTE0_ENABLED  (UART0_ENABLED && UART_EASY_DMA_SUPPORT)
    #endif

    Best regards,

    Edvin

Reply
  • I guess it is also worth mentioning a file that may confuse even more, which is the apply_old_config.h. You should at least look at it. When the nrfx drivers were introduced, they added these new NRFX_... definitions in sdk_config.h, which are used in the drivers. However, even though you set them in sdk_config.h, they will be overwritten in apply_old_config.h, to the value that the non-NRFX definitions are set to. Just look at the file, and you should see how it does this. Either, you need to use the "legacy" definitions, or you need to remove them and use the NRFX definitions. (It is the same drivers that are used either way). This may cause confusion, because setting:
    NRFX_UART0_ENABLED to 1 may be undone because UART0_ENABLED was set to 0, and this part from apply_old_config:

    #if defined(UART_ENABLED)
    
    #undef NRFX_UART_ENABLED
    #define NRFX_UART_ENABLED   (UART_ENABLED && NRFX_UART0_ENABLED)
    #undef NRFX_UARTE_ENABLED
    #define NRFX_UARTE_ENABLED  (UART_ENABLED && (NRFX_UARTE0_ENABLED || NRFX_UARTE1_ENABLED))
    
    #if defined(UART0_ENABLED)
    #undef NRFX_UART0_ENABLED
    #define NRFX_UART0_ENABLED   (UART0_ENABLED && UART_LEGACY_SUPPORT)
    #undef NRFX_UARTE0_ENABLED
    #define NRFX_UARTE0_ENABLED  (UART0_ENABLED && UART_EASY_DMA_SUPPORT)
    #endif

    Best regards,

    Edvin

Children
No Data
Related