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

undefined reference twi error

Hi,

I hope you can help me. I get an error while compiling. I merge "twi sensor" example from sdk to the "ble app uart" example from sdk. So I customize the sdk_config to enable twi. In addition to that, I add all missing nRF_Drivers to make it work. While compiling, I get the following output:

1> "C:/Program Files/SEGGER/SEGGER Embedded Studio for ARM 4.50/gcc/arm-none-eabi/bin/as" --traditional-format -I../../../config -I../../../../../../components -I../../../../../../components/ble/ble_advertising -I../../../../../../components/ble/ble_dtm -I../../../../../../components/ble/ble_link_ctx_manager -I../../../../../../components/ble/ble_racp -I../../../../../../components/ble/ble_services/ble_ancs_c -I../../../../../../components/ble/ble_services/ble_ans_c -I../../../../../../components/ble/ble_services/ble_bas -I../../../../../../components/ble/ble_services/ble_bas_c -I../../../../../../components/ble/ble_services/ble_cscs -I../../../../../../components/ble/ble_services/ble_cts_c -I../../../../../../components/ble/ble_services/ble_dfu -I../../../../../../components/ble/ble_services/ble_dis -I../../../../../../components/ble/ble_services/ble_gls -I../../../../../../components/ble/ble_services/ble_hids -I../../../../../../components/ble/ble_services/ble_hrs -I../../../../../../components/ble/ble_services/ble_hrs_c -I../../../../../../components/ble/ble_services/ble_hts -I../../../../../../components/ble/ble_services/ble_ias -I../../../../../../components/ble/ble_services/ble_ias_c -I../../../../../../components/ble/ble_services/ble_lbs -I../../../../../../components/ble/ble_services/ble_lbs_c -I../../../../../../components/ble/ble_services/ble_lls -I../../../../../../components/ble/ble_services/ble_nus -I../../../../../../components/ble/ble_services/ble_nus_c -I../../../../../../components/ble/ble_services/ble_rscs -I../../../../../../components/ble/ble_services/ble_rscs_c -I../../../../../../components/ble/ble_services/ble_tps -I../../../../../../components/ble/common -I../../../../../../components/ble/nrf_ble_gatt -I../../../../../../components/ble/nrf_ble_qwr -I../../../../../../components/ble/peer_manager -I../../../../../../components/boards -I../../../../../../components/libraries/atomic -I../../../../../../components/libraries/atomic_fifo -I../../../../../../components/libraries/atomic_flags -I../../../../../../components/libraries/balloc -I../../../../../../components/libraries/bootloader/ble_dfu -I../../../../../../components/libraries/bsp -I../../../../../../components/libraries/button -I../../../../../../components/libraries/cli -I../../../../../../components/libraries/crc16 -I../../../../../../components/libraries/crc32 -I../../../../../../components/libraries/crypto -I../../../../../../components/libraries/csense -I../../../../../../components/libraries/csense_drv -I../../../../../../components/libraries/delay -I../../../../../../components/libraries/ecc -I../../../../../../components/libraries/experimental_section_vars -I../../../../../../components/libraries/experimental_task_manager -I../../../../../../components/libraries/fds -I../../../../../../components/libraries/fifo -I../../../../../../components/libraries/fstorage -I../../../../../../components/libraries/gfx -I../../../../../../components/libraries/gpiote -I../../../../../../components/libraries/hardfault -I../../../../../../components/libraries/hci -I../../../../../../components/libraries/led_softblink -I../../../../../../components/libraries/log -I../../../../../../components/libraries/log/src -I../../../../../../components/libraries/low_power_pwm -I../../../../../../components/libraries/mem_manager -I../../../../../../components/libraries/memobj -I../../../../../../components/libraries/mpu -I../../../../../../components/libraries/mutex -I../../../../../../components/libraries/pwm -I../../../../../../components/libraries/pwr_mgmt -I../../../../../../components/libraries/queue -I../../../../../../components/libraries/ringbuf -I../../../../../../components/libraries/scheduler -I../../../../../../components/libraries/sdcard -I../../../../../../components/libraries/slip -I../../../../../../components/libraries/sortlist -I../../../../../../components/libraries/spi_mngr -I../../../../../../components/libraries/stack_guard -I../../../../../../components/libraries/strerror -I../../../../../../components/libraries/svc -I../../../../../../components/libraries/timer -I../../../../../../components/libraries/twi_mngr -I../../../../../../components/libraries/twi_sensor -I../../../../../../components/libraries/uart -I../../../../../../components/libraries/usbd -I../../../../../../components/libraries/usbd/class/audio -I../../../../../../components/libraries/usbd/class/cdc -I../../../../../../components/libraries/usbd/class/cdc/acm -I../../../../../../components/libraries/usbd/class/hid -I../../../../../../components/libraries/usbd/class/hid/generic -I../../../../../../components/libraries/usbd/class/hid/kbd -I../../../../../../components/libraries/usbd/class/hid/mouse -I../../../../../../components/libraries/usbd/class/msc -I../../../../../../components/libraries/util -I../../../../../../components/nfc/ndef/conn_hand_parser -I../../../../../../components/nfc/ndef/conn_hand_parser/ac_rec_parser -I../../../../../../components/nfc/ndef/conn_hand_parser/ble_oob_advdata_parser -I../../../../../../components/nfc/ndef/conn_hand_parser/le_oob_rec_parser -I../../../../../../components/nfc/ndef/connection_handover/ac_rec -I../../../../../../components/nfc/ndef/connection_handover/ble_oob_advdata -I../../../../../../components/nfc/ndef/connection_handover/ble_pair_lib -I../../../../../../components/nfc/ndef/connection_handover/ble_pair_msg -I../../../../../../components/nfc/ndef/connection_handover/common -I../../../../../../components/nfc/ndef/connection_handover/ep_oob_rec -I../../../../../../components/nfc/ndef/connection_handover/hs_rec -I../../../../../../components/nfc/ndef/connection_handover/le_oob_rec -I../../../../../../components/nfc/ndef/generic/message -I../../../../../../components/nfc/ndef/generic/record -I../../../../../../components/nfc/ndef/launchapp -I../../../../../../components/nfc/ndef/parser/message -I../../../../../../components/nfc/ndef/parser/record -I../../../../../../components/nfc/ndef/text -I../../../../../../components/nfc/ndef/uri -I../../../../../../components/nfc/platform -I../../../../../../components/nfc/t2t_lib -I../../../../../../components/nfc/t2t_parser -I../../../../../../components/nfc/t4t_lib -I../../../../../../components/nfc/t4t_parser/apdu -I../../../../../../components/nfc/t4t_parser/cc_file -I../../../../../../components/nfc/t4t_parser/hl_detection_procedure -I../../../../../../components/nfc/t4t_parser/tlv -I../../../../../../components/softdevice/common -I../../../../../../components/softdevice/s140/headers -I../../../../../../components/softdevice/s140/headers/nrf52 -I../../../../../../components/toolchain/cmsis/include -I../../../../../../external/fprintf -I../../../../../../external/segger_rtt -I../../../../../../external/utf_converter -I../../../../../../integration/nrfx -I../../../../../../integration/nrfx/legacy -I../../../../../../modules/nrfx -I../../../../../../modules/nrfx/drivers/include -I../../../../../../modules/nrfx/hal -I../../../../../../modules/nrfx/mdk -I../config -mcpu=cortex-m4 -mlittle-endian -mfloat-abi=hard -mfpu=fpv4-sp-d16 -mthumb "C:/Users/hp/Desktop/Firmware Entwicklung/nRF5SDK160098a08e2.zip/examples/ble_peripheral/ble_app_uart/pca10100/s140/ses/Output/ble_app_uart_pca10100_s140 Debug/Obj/main.asm" -o "Output/ble_app_uart_pca10100_s140 Debug/Obj/main.o"
1> rm "C:/Users/hp/Desktop/Firmware Entwicklung/nRF5SDK160098a08e2.zip/examples/ble_peripheral/ble_app_uart/pca10100/s140/ses/Output/ble_app_uart_pca10100_s140 Debug/Obj/main.asm"
1> Output/ble_app_uart_pca10100_s140 Debug/Obj/main.o (28.06.2020 20:58:16) is newer than Output/Debug/Exe/ble_app_uart_pca10100_s140.elf (28.06.2020 20:57:32).
1> Linking ble_app_uart_pca10100_s140.elf
1> "C:/Program Files/SEGGER/SEGGER Embedded Studio for ARM 4.50/gcc/arm-none-eabi/bin/ld" -X --omagic -eReset_Handler --defsym=__vfprintf=__vfprintf_long --defsym=__vfscanf=__vfscanf_long -EL --gc-sections "-TC:/Users/hp/Desktop/Firmware Entwicklung/nRF5SDK160098a08e2.zip/examples/ble_peripheral/ble_app_uart/pca10100/s140/ses/Output/ble_app_uart_pca10100_s140 Debug/Obj/ble_app_uart_pca10100_s140.ld" -Map Output/Debug/Exe/ble_app_uart_pca10100_s140.map -u_vectors -o Output/Debug/Exe/ble_app_uart_pca10100_s140.elf --emit-relocs --start-group "@C:/Users/hp/Desktop/Firmware Entwicklung/nRF5SDK160098a08e2.zip/examples/ble_peripheral/ble_app_uart/pca10100/s140/ses/Output/ble_app_uart_pca10100_s140 Debug/Obj/ble_app_uart_pca10100_s140.ind" --end-group
1> C:/Program Files/SEGGER/SEGGER Embedded Studio for ARM 4.50/gcc/arm-none-eabi/bin/ld: Output/ble_app_uart_pca10100_s140 Debug/Obj/nrf_drv_twi.o: in function `nrf_drv_twi_init':
1> C:\Users\hp\Desktop\Firmware Entwicklung\nRF5SDK160098a08e2.zip\integration\nrfx\legacy/nrf_drv_twi.c:186: undefined reference to `nrfx_twi_init'
1> C:/Program Files/SEGGER/SEGGER Embedded Studio for ARM 4.50/gcc/arm-none-eabi/bin/ld: Output/ble_app_uart_pca10100_s140 Debug/Obj/main.o: in function `nrf_drv_twi_enable':
1> C:\Users\hp\Desktop\Firmware Entwicklung\nRF5SDK160098a08e2.zip\examples\ble_peripheral\ble_app_uart\pca10100\s140\ses/../../../../../../integration/nrfx/legacy/nrf_drv_twi.h:513: undefined reference to `nrfx_twim_enable'
1> C:/Program Files/SEGGER/SEGGER Embedded Studio for ARM 4.50/gcc/arm-none-eabi/bin/ld: Output/ble_app_uart_pca10100_s140 Debug/Obj/main.o: in function `nrf_drv_twi_tx':
1> C:\Users\hp\Desktop\Firmware Entwicklung\nRF5SDK160098a08e2.zip\examples\ble_peripheral\ble_app_uart\pca10100\s140\ses/../../../../../../integration/nrfx/legacy/nrf_drv_twi.h:544: undefined reference to `nrfx_twim_tx'
Build failed

But I don´t know what I´m making wrong.

Could you help me with that?

Thanks in advance

Parents
  • Hello,

    Which SDK are you using?
    If you are using the newer versions in which nrf_drv_* is legacy, you will notice that they are forwarding macros to the new nrfx_ drivers.
    Therefore, you will need to also add the nrfx_ drivers to your project for the TWI functionality to work. Namely, it seems you are missing nrfx_twim.c. You can see from the error codes that the problem is nrf_drv_twi_* making calls to undefined "nrfx_twim_*" functions.
    I would also recommend you that you work directly with the nrfx_ drivers, instead of using the legacy layers - this will decrease future work in which you will have to port your code to the nrfx_ drivers, since nrf_drv is already legacy.

    For future reference, it would be beneficial if you were specific when saying that you have added "all missing nRF_drivers to make it work" - which drivers have you added, and which changes have you made to sdk_config?

    Please let me know if this does not resolve your problem, or if anything regarding the nrfx_* vs. nrf_drv_* drivers should be unclear.

    Best regards,
    Karl

  • Hi,

    I´m using SDK 16.

    Namely, it seems you are missing nrfx_twim.c.

    I don´t think so. I added it in the folder "nRF_Drivers as shown in screenshot attached.

    I have added the twi drivers in the BLE Uart example, to make TWI work (the same drivers are used in TWI Sensor example of SDK):

    - nrfx_twim.c

    - nrf_drv_twi.c

    In addition to that, I customized sdk_config. In general I enabled all TWI options. Nothing special I think. I attached the sdk_config if it would help you for analyzing.

    53234.sdk_config.h

    Another thing is, that the application is compiling well in "release" build configuration, but not in "debug" configuration. But when I compile in "release", the BLE application doesn´t work.

    Because of nrfx_twim.c is already in my driver folder the problem exists furthermore. Is there something else I could try? Thanks in advance.

    Simon

  • Hi Karl,

    I am a Little bit confused.

    If you are attempting to declare a timer instance, you will need to use the _TIMER_INSTANCE macro. You can see this being done in line 72 of the SAADC example.

    Okay, but in this example it seems that there is a library "nrf_drv_timer.h" is used. But I already use "app_timer.h". So I don´t think that I need both, or not? If I include additional the "nrf_drv_timer.h" I get errors with my NRFX_Timer driver. I think in this example an other Driver is used, can this be?

    If you are attempting to declare a timer instance, you will need to use the _TIMER_INSTANCE macro. You can see this being done in line 72 of the SAADC example.

    I think for this I have to enable a few things in sdk_config, but I also use app_timer in my project for other Things.

    So do I have to include the new library (as shown in example) or can I just work with my app_timer library?

    Thanks in Advance.

    Kind regards

    Simon

  • Hello Simon,

    simon1516 said:
    I am a Little bit confused.
    simon1516 said:
    Okay, but in this example it seems that there is a library "nrf_drv_timer.h" is used. But I already use "app_timer.h". So I don´t think that I need both, or not? If I include additional the "nrf_drv_timer.h" I get errors with my NRFX_Timer driver. I think in this example an other Driver is used, can this be?

    I am sorry for any confusion I might have caused here, my mistake. I thought you were using the TIMER driver directly. If you are using the app_timer library, you will not need ot use the _TIMER_INSTANCE macro, but you will need to use the APP_TIMER_DEF macro instead.
    If you are using the app_timer library, then you do not need to use the TIMER peripheral drivers directly - the app_timer library handles this for you.

    simon1516 said:
    So do I have to include the new library (as shown in example) or can I just work with my app_timer library?

    I am sorry about my confusion here, I thought you intended to use the TIMER driver, not the app_timer library. You may just use the app_timer library as you already are, no need to worry about the TIMER driver.

    Best regards,
    Karl

  • Hi Karl,

    so now I just use my app_timer.h library but someting went wrong in my implementation.

    For creating my timers I do the following:

    /**@brief Function for initializing the timer module.
     */
    static void timers_init(void)
    {
    
        ret_code_t err_code = app_timer_init();
        APP_ERROR_CHECK(err_code);
        APP_TIMER_DEF(my_timer_id);
        err_code=app_timer_create(&my_timer_id,APP_TIMER_MODE_REPEATED, read_sensor_data);
        APP_ERROR_CHECK(err_code);
    }

    But when I try to start the timer in my main function, then I get an error because "my_timer_id" is not declared in here:

    Could you explain me how to declare this const?

    If I say "#define my_timer_id 3" for example I get an error because of integer value is not possible here.

    Is there an example of using this app_timer? I didn´t find much using this app_timer :-/

    Thanks in advance

    Kind regards

    Simon

  • Hello Simon,

    You can see the necessary steps for using the application timer library in its documentation. It seems to me that you are close to making it work, you will just need to move your APP_TIMER_DEF, and possibly also enable the timers in the sdk_config file.

    simon1516 said:
    But when I try to start the timer in my main function, then I get an error because "my_timer_id" is not declared in here:

    You should move your APP_TIMER_DEF to the top of your file - right next to your #define's.
    Could you also verify for me that APP_TIMER_ENABLED, TIMER_ENABLED, and NRFX_TIMER_ENABLED is defined to 1 in the sdk_config? You will also need to have the particular timer instance ENABLE set to 1 ( seem to me like you are using timer instance 3 ).

    Hope this helps! :) 

    Best regards,
    Karl

  • Hi Karl,

    I am here again with new findings:

    __________________________________

    you will just need to move your APP_TIMER_DEF, and possibly also enable the timers in the sdk_config file

    Thats it. After moving "APP_TIMER_DEF(my_timer_id);" to the top of main.c the compilation works fine. But how can there be an ID (Integer Value) for my timer? I just give it the name my_timer_id. Do I have to give an ID at all? If I trying to do that, I get an error:

    __________________________________

    Could you also verify for me that APP_TIMER_ENABLED, TIMER_ENABLED, and NRFX_TIMER_ENABLED is defined to 1 in the sdk_config? You will also need to have the particular timer instance ENABLE set to 1 ( seem to me like you are using timer instance 3 ).

    Everything is set to "1".

    NRFX_TIMER0_ENABLED to NRFX_TIMER4_ENABLED is set to 1.

    __________________________________

    If I don´t define the "#define my_timer_id 3" the compiling works fine. Then the main loop is running. But after the expiration of the timer (#define TWIM_transmission_time          APP_TIMER_TICKS(10000)) the code stucks with NRF_BUSY error. It´s the same error like posted on 24. August 2020 7:54 p.m. (although I didn´t change anything on this function since then). So the behaviour is confusing a little bit.

    In my main loop is not much code.

    This works:

            nrf_delay_ms(20);
           // ret_code_t err_code = app_timer_start(my_timer_id, TWIM_transmission_time, NULL);
           // APP_ERROR_CHECK(err_code);
            read_sensor_data();

    This doesn´t work:

            nrf_delay_ms(20);
            ret_code_t err_code = app_timer_start(my_timer_id, TWIM_transmission_time, NULL);
            APP_ERROR_CHECK(err_code);
          //  read_sensor_data();

    Where is the difference? The only difference is, that in first example the function "read _sensor_data()"  is called automatically and in the second example the function "read _sensor_data()"  is called by expiration of the timer. Because of that, I don´t think there is someting wrong with my function rather someting with the timer procedure...

    __________________________________

    So, I hope you see something that I don´t see, which I can fix :-)

    Kind regards

    Simon

Reply
  • Hi Karl,

    I am here again with new findings:

    __________________________________

    you will just need to move your APP_TIMER_DEF, and possibly also enable the timers in the sdk_config file

    Thats it. After moving "APP_TIMER_DEF(my_timer_id);" to the top of main.c the compilation works fine. But how can there be an ID (Integer Value) for my timer? I just give it the name my_timer_id. Do I have to give an ID at all? If I trying to do that, I get an error:

    __________________________________

    Could you also verify for me that APP_TIMER_ENABLED, TIMER_ENABLED, and NRFX_TIMER_ENABLED is defined to 1 in the sdk_config? You will also need to have the particular timer instance ENABLE set to 1 ( seem to me like you are using timer instance 3 ).

    Everything is set to "1".

    NRFX_TIMER0_ENABLED to NRFX_TIMER4_ENABLED is set to 1.

    __________________________________

    If I don´t define the "#define my_timer_id 3" the compiling works fine. Then the main loop is running. But after the expiration of the timer (#define TWIM_transmission_time          APP_TIMER_TICKS(10000)) the code stucks with NRF_BUSY error. It´s the same error like posted on 24. August 2020 7:54 p.m. (although I didn´t change anything on this function since then). So the behaviour is confusing a little bit.

    In my main loop is not much code.

    This works:

            nrf_delay_ms(20);
           // ret_code_t err_code = app_timer_start(my_timer_id, TWIM_transmission_time, NULL);
           // APP_ERROR_CHECK(err_code);
            read_sensor_data();

    This doesn´t work:

            nrf_delay_ms(20);
            ret_code_t err_code = app_timer_start(my_timer_id, TWIM_transmission_time, NULL);
            APP_ERROR_CHECK(err_code);
          //  read_sensor_data();

    Where is the difference? The only difference is, that in first example the function "read _sensor_data()"  is called automatically and in the second example the function "read _sensor_data()"  is called by expiration of the timer. Because of that, I don´t think there is someting wrong with my function rather someting with the timer procedure...

    __________________________________

    So, I hope you see something that I don´t see, which I can fix :-)

    Kind regards

    Simon

Children
  • Hello Simon, 

    simon1516 said:
    Thats it. After moving "APP_TIMER_DEF(my_timer_id);" to the top of main.c the compilation works fine.
    simon1516 said:
    But how can there be an ID (Integer Value) for my timer? I just give it the name my_timer_id. Do I have to give an ID at all? If I trying to do that, I get an error:

    You do not need to give your timer an integer ID, no. The APP_TIMER_DEF creates an instance with that name. So, what you would do is basically:

    APP_TIMER_DEF(m_twi_timer);
    ..
    err_code = app_timer_init();
    ..
    err_code = app_timer_create(&m_twi_timer, APP_TIMER_MODE_SINGLE_SHOT, twi_timer_handler);
    APP_ERROR_CHECK(err_code);
    ..
    err_code = app_timer_start(m_twi_timer, TWI_TRANSMISSION_DELAY, NULL);
    APP_ERROR_CHECK(err_code);
    ..
    

    If you would like to see the source of the compiler error you are getting here, go to the definition of APP_TIMER_DEF and see what argument it expects, vs. the integer "3" you provided.

    simon1516 said:

    Everything is set to "1".

    NRFX_TIMER0_ENABLED to NRFX_TIMER4_ENABLED is set to 1.

    Thank you for confirming this.

    simon1516 said:
    APP_TIMER_TICKS(10000)

     This is a 10,000 ms delay, i.e 10 s. Is this the intended delay?

    simon1516 said:
    the code stucks with NRF_BUSY error

    Which function is returning this error code, nrfx_twim_xfer? And, what do you mean by "stuck", does the device reset?

    simon1516 said:
    Where is the difference? The only difference is, that in first example the function "read _sensor_data()"  is called automatically and in the second example the function "read _sensor_data()"  is called by expiration of the timer.

    The difference is that the CPU is free to continue with other tasks in the meantime, while the timer is running. In your current setup, this means that the CPU will run for 10 seconds while the timer is still running. The question then becomes, what are you doing in these 10 seconds? If the code above is your entire main loop then the CPU will immediately enter the loop again, and try to start the timer again in the next loop iteration. From the 

    app_timer_start

    documentation we see that this function call is ignored if the timer is already started.
    What you should instead do is therefore to either go to sleep, or perform some other task.
    Could you show the entire contents of your current main function?

    Best regards,
    Karl

  • If you would like a more fully-fledged tutorial on the app_timer, then I highly recommend taking a look at this one written by my colleague.
    The tutorial is a bit old, but the general approach and theory still holds true for the app_timer in the newest SDK.

    Best regards,
    Karl

  • Hi Karl,

    thanks for your support!

    So, what you would do is basically:

    I´m doing it like this, so I think setting up the timer is correct.

     This is a 10,000 ms delay, i.e 10 s. Is this the intended delay?

    No, it was just for testing the procedure while watching the timer expiration. In normal mode, we would like to process a TWIM with BLE transfer each 10ms, maybe 20ms. In your opinion, does it make sense to set the chip into sleep modus for this small time? If we expect, a data transfer needs about 2ms...then the chip could sleep for 8ms until the next transfer - a long time?

    What could be a good way to handle this? After each transfer, I can call "sleep_mode_enter()". And then the system is off? Is it possible, to wake up with timer expiration as interrupt? Is there an easy example for this?

    documentation we see that this function call is ignored if the timer is already started.

    Okay, but ignoration should be okay for me or not? But someting aborts in my application. But I´m with you, that the timer should just start at one time. Because of that, I moved this from my main loop to the initialization of my main application. So there the timer starts just one time. I´ve added the actual project file for you which includes main.c for analyzing this.

    Which function is returning this error code, nrfx_twim_xfer? And, what do you mean by "stuck", does the device reset?

    Correct. It´s the function "nrfx_twim_xfer" again. The complete error message is:

    <error> app: ERROR 17 [NRF_ERROR_BUSY] at C:\Users\hp\Desktop\Firmware Entwicklung\nRF5SDK160098a08e2.zip\examples\ble_peripheral\ble_app_uart_with_twim v0.2\main.c:826
    PC at: 0x0003137B

    Karl, thanks for you help! I think it´s time to add an actual project file (attached) for analyzing.

    ble_app_uart_with_twim v0.6.zip

    Simon

  • Hello Simon,

    simon1516 said:
    thanks for your support!

    No problem at all, I am happy to help! 

    simon1516 said:
    No, it was just for testing the procedure while watching the timer expiration. In normal mode, we would like to process a TWIM with BLE transfer each 10ms, maybe 20ms. In your opinion, does it make sense to set the chip into sleep modus for this small time? If we expect, a data transfer needs about 2ms...then the chip could sleep for 8ms until the next transfer - a long time?

    I would say 8 ms is quite a long time, especially if it is every 10 ms. That means you potentially have the CPU sleeping ( drawing significantly less power ) for 80% of the time ( unless you are doing something else in your application as well ). It is definitely better than having the CPU perform NOP cycles for the duration, with regards to power consumption.
    You can see the different power consumption scenarios here.

    If you want to take it up another notch, you could look into using Radio Notifications to perform your TWIM transfers right before the next connection event. But, this is not required at this time. Lets first finish the work with the timer!

    simon1516 said:
    What could be a good way to handle this? After each transfer, I can call "sleep_mode_enter()". And then the system is off? Is it possible, to wake up with timer expiration as interrupt? Is there an easy example for this?

     Yes, the power manage module makes this quite easy. As you probably have seen in most of the SDK examples the only thing happening in the main while() loop is a function called "idle_state_handler". If you look into this idle state handler, you will see that it is merely a call to the nrf_pwr_mgmt_run function ( if there are no logs to process ). This function places the CPU in the "Wait for event" state. Once an event is generated, the CPU will handle it accordingly.
    So, it is both very easy to set up ( just use the provided power management module ), and easy to use - I highly recommend giving it a try! It will significantly increase the battery life of your device.

    simon1516 said:
    Okay, but ignoration should be okay for me or not? But someting aborts in my application.

    That the second timer_start is being ignored is fine, yes.
    For example, if your main loop keeps fetching data somewhere, and trying to process the data by sending it over TWIM. If your TWIM only happens at the end of the timer, and that timer is too long, then data will "build up" rapidly, since it is not being processed in time.

    When you say that something aborts in your application, are you then talking about the NRF_BUSY_ERROR returned from nrfx_twim_xfer?

    simon1516 said:

    Correct. It´s the function "nrfx_twim_xfer" again. The complete error message is:

    <error> app: ERROR 17 [NRF_ERROR_BUSY] at C:\Users\hp\Desktop\Firmware Entwicklung\nRF5SDK160098a08e2.zip\examples\ble_peripheral\ble_app_uart_with_twim v0.2\main.c:826
    PC at: 0x0003137B

    As we can see from the nrfx_twim_xfer documentation, NRF_ERROR_BUSY will be returned when the driver is not yet ready for a new transfer, such as if it is still working on the previous transfer and you attempt to start a new one.

    Taking a quick look through your project I have the following questions:
    - what is the b_Battery_Pin define for?
    - all your "regX" variables should have proper names. I.e READ_XXX, or CTRL_XXX. You could also have a separate header file that defines all the possible commands for the sensor, which makes them easy to invoke. This increases readability and reduces that chance of mistyping a command / reading the wrong register.
    - your "my_timer_id" timer is set to be in REPEATED mode, I do not know if this is intentional? As I understood it you would just like to start the timer in between each transfer, to ensure that enough time passes for the device to be ready for the next transfer, was it not so? With the current REPEATED timer, triggering read_sensor_data you still rely on nrf_delay_ms in between your transfers.
     

    simon1516 said:
    Karl, thanks for you help!

    It is no problem at all, Simon!

    Best regards,
    Karl

  • Hi Karl,

    Thanks for this. So it make sense, setting CPU in sleep mode. I will try it :-)

    _____________________________________________________________

    My timers are working now, I get it! :-) In my case I call two times "nrfx_twim_xfer" in one read procedure. Because of that, I have declared two timers now. I had to split my read function in two parts (because a timer can just call one function after expiration).

    First timer: Repeatet, because I would like to send data in an special time intervall.

    Second timer: NOT repeatet; If First timer expired, second timer start´s - because of TWIM needs this time for processing well.

    In my case, first timer 1000ms,second timer 10ms. I try to reduce this the next days, we´ll see how much works.

    _____________________________________________________________

    Taking a quick look through your project I have the following questions:
    - what is the b_Battery_Pin define for?
    - all your "regX" variables should have proper names. I.e READ_XXX, or CTRL_XXX. You could also have a separate header file that defines all the possible commands for the sensor, which makes them easy to invoke. This increases readability and reduces that chance of mistyping a command / reading the wrong register.
    - your "my_timer_id" timer is set to be in REPEATED mode, I do not know if this is intentional? As I understood it you would just like to start the timer in between each transfer, to ensure that enough time passes for the device to be ready for the next transfer, was it not so? With the current REPEATED timer, triggering read_sensor_data you still rely on nrf_delay_ms in between your transfers.

    - b_Battery_Pin was just for testing - setting a Pin high from the nrf52833 to high. Our custom board includes a battery management chip - this Pin high shall activate/enable the IC on the board.

    - Yes, this is a good point. I have to do that. But making code better to read, doesn´t make fun :-) Please give me a few days for that.

    - You´re right. But in each transfer I start a timer. But I need a second timer, to start the transfer. Because of that, I implemented two timers for this.

    _____________________________________________________________

    I try to implement the idle_state_handler the next days for better battery life. I haven´t done it yet, but I will give you a feedback here soon.

    Thank you and kind regards

    Simon

Related