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

  • Hello again Simon,

    simon1516 said:

    Could you guide me how to use such a timer? I defined "#define TWIM_transmission_time APP_TIMER_TICKS(10) " to get a timer with 10ms delay time. So now, I would like to use this timer in my "twim_handler". Nothing should happen, if the timer isn´t expired. The timer should restart, if it is expired and an twim event was done. Could you give me a small Syntax for this?

    I have already included "app_timer.h", so I think it would make sense to use this.



    Yes, it would be easiest to use the app_timer to create and manage the timer.
    However, could you first try to see what the required delay is, by using nrf_delay?
    It might be that your TWI slave requires some delay between transfer.

    It is slightly more work to implement the solution without wasted CPU cycles. Could you detail for me what transfers you will make - how frequent are they, and how many bytes are in each transfer?
    If you are only doing pairs of two and two bytes ( R/W commands ) then you could perhaps solve this by using the DESC_TXTX and DESC_TXRX, for example. It would mean a lot less work to use the already implemented features of the TWIM driver, so lets look at that first if possible, or depending on your specification we might use the NRFX_TWIM_FLAG_HOLD_XFER feature instead.

    simon1516 said:
    Could you tell me, how to get this Information?

    Yes, please check your sdk_config file, to see if the NRF_LOG_DEFERRED is defined as 1 or 0, and if it is 1, what is then the size of NRF_LOG_BUFSIZE? 

    simon1516 said:
    Here I think I have to debug again (because debugging is working now :-) ). I will try this and give you a short Feedback the next days!

    Great, that sounds like a good plan - I look forward to hearing your findings!

    Best regards,
    Karl

  • Hi Karl,

    here I am again with new findings.

    _______________________________________________________

    However, could you first try to see what the required delay is, by using nrf_delay?
    It might be that your TWI slave requires some delay between transfer.

    It seems so. I measured a few write/read procedures with different timing parameters. The result:

    I have to implement at least the following:

     nrf_delay_us(500);
     
        /* Read */
       err_code = nrfx_twim_xfer(&m_twim, &lm75b_reading, NULL);
       APP_ERROR_CHECK(err_code);
    
     nrf_delay_us(500);

    BEFORE and AFTER my read process a delay of 500us. If I reduce the number of us more, the read process didn´t work correctly (I checked this with printing the values by uart and I could see that the transmission didn´t work with lower timing). Could you maybe give me a syntax for replacing this with app_timer ?

    ___________________________________________________________

    Could you detail for me what transfers you will make - how frequent are they, and how many bytes are in each transfer?

    - I would like to read 14 bytes each transfer (https://invensense.tdk.com/wp-content/uploads/2016/06/DS-000189-ICM-20948-v1.3.pdf chapteer 7.1, register "2D" to "3A"). Accelerometer-Value X, Y, Z (each 2 bytes), Gyroscope-Value X, Y, Z (each 2 bytes) and Temperatur-Value (2 bytes). So in sum 14 bytes.

    - I would like to read the 14 bytes every 10ms. This frequency should be changeable.

    ____________________________________________________________

    Yes, please check your sdk_config file, to see if the NRF_LOG_DEFERRED is defined as 1 or 0, and if it is 1, what is then the size of NRF_LOG_BUFSIZE? 

    NRF_LOG_DEFERRED is "1" and NRF_LOG_BUFSIZE is "1024".

    Do I have the option to deactivate this log-deferring? I am not really sure if I need it.

    _______________________________________________________________

    Where does the application stop after three minutes, is it a particular place in the code?

    In debug terminal I just can see the message "Logs dropped ()" as described above. There is no line number printed out to see where the error happened. Here a screenshot from the error:

    Thank you for helping us with our product development :-)

    Kind regards

    Simon

  • Hello Simon,

    simon1516 said:
    BEFORE and AFTER my read process a delay of 500us. If I reduce the number of us more, the read process didn´t work correctly (I checked this with printing the values by uart and I could see that the transmission didn´t work with lower timing). Could you maybe give me a syntax for replacing this with app_timer ?

    500 us does not sound too bad in this case ( depending on your if you are reading 14 bytes every transfer, or only two, see my question below ).
    You can read about the app timer's usage and syntax in the library documentation, or in the Timer example or see its usage demonstrated in the Timer example from the SDK. Please let me know if anything should be unclear here, so I can provide more detail.
    What will you have your application doing in this time?
    I guess the simplest case for power consumption would be to start the timer, then immediately go to sleep ( for example using sd_app_evt_wait() or similar ).

    simon1516 said:

    - I would like to read 14 bytes each transfer (https://invensense.tdk.com/wp-content/uploads/2016/06/DS-000189-ICM-20948-v1.3.pdf chapteer 7.1, register "2D" to "3A"). Accelerometer-Value X, Y, Z (each 2 bytes), Gyroscope-Value X, Y, Z (each 2 bytes) and Temperatur-Value (2 bytes). So in sum 14 bytes.

    - I would like to read the 14 bytes every 10ms. This frequency should be changeable.

    Thank you for clarifying on this.
    Are you doing the 14 byte read as a single read, or 7 x 2-byte reads?

    simon1516 said:

    NRF_LOG_DEFERRED is "1" and NRF_LOG_BUFSIZE is "1024".

    Do I have the option to deactivate this log-deferring? I am not really sure if I need it.

    Deferred logging means that the logs are put into a buffer when you call NRF_LOG_INFO(), but not actually processed ( since processing it at that particular time in the code might be unwanted ). The logs therefore needs to be processed from the buffer, which you can do using NRF_LOG_PROCESS(). This is ideally done when the processor is free from other tasks. A good implementation of this is shown in many of our examples, for instance the BLE Proximity Peripheral example, in which the NRF_LOG_PROCESS is called when the CPU is idling. If there are no more logs to process, the application goes to sleep.
    You could set NRF_LOG_DEFERRED to 0 to surpress this. It might make some of your functions take longer to complete, since logs are processed as they are called, but I would think it should make no difference for your application here.

    simon1516 said:
    In debug terminal I just can see the message "Logs dropped ()" as described above. There is no line number printed out to see where the error happened. Here a screenshot from the error:

     Yes, attempt to disabled deferred logging as I recommend above, and let me know if this resolves the issue.

    simon1516 said:
    Thank you for helping us with our product development :-)

    Absolutely, it is no problem at all Simon - I am happy to help! :) 

    Best regards,
    Karl

  • Hi Karl,

    _________________________________________________________

    Please let me know if anything should be unclear here, so I can provide more detail.
    What will you have your application doing in this time?

    The Chip should go to sleep, when no transmission is required. So the Syntax should be:

    if Timer is expired

    {

    one TWIM procedure

    restart Timer

    }

    I´ve tried to implement this but unfortunaly I get an error if I try to create a new timer. I do the following:

        APP_TIMER_DEF(my_timer_id); // define new timer
        err_code=app_timer_create(&my_timer_id,APP_TIMER_MODE_REPEATED, NULL); //Create this timer, Time mode repeated because timer should restart every time it is expired. I´m not sure what to insert for "NULL"
        APP_ERROR_CHECK(err_code); // Check if Timer was created successfully

    I debugged this and debug terminal shows me, that the error is here: app_timer2.c:559 --> (ASSERT(timeout_handler);)

    I´m not really sure, what to insert in the "app_timer_create" for timeout_handler. I read that there is a function coming in, which is executed when the timer is expired. Could you please give me an example for this?

    ________________________________________________________________

    Are you doing the 14 byte read as a single read, or 7 x 2-byte reads?

    I´m doing this actually with one read with 14 bytes. This works fine :-)

    _______________________________________________________________

    Yes, attempt to disabled deferred logging as I recommend above, and let me know if this resolves the issue.

    I disabled deferred logging. Now there are no longer errors with this, so this works too :-)

    _______________________________________________________________

    In debug terminal I just can see the message "Logs dropped ()" as described above. There is no line number printed out to see where the error happened. Here a screenshot from the error:

    To this error again: Disabling the deffered logging solves that there are no longer the messages "Logs dropped ()". But the main problem was not solved. I debugged again. And the code stops every time after exactly three minutes, because it is calling "static void sleep_mode_enter(void)"  and "err_code = sd_power_system_off();"

    Exactly three minutes, this is the time, the system is advertising for BLE devices! If I connect with nRF connect Mobile App to the nRF Chip, the TWIM doesn´t stop. The transmission is working until BLE connection is closed. So after advertising, the chip is calling the sleep mode was the explanation here.

    Like it works is okay, because TWIM just has to send data if a BLE connection is established. I just want to give you feedback for this.

    ______________________________________________________________________

    Have a nice weekend, I hope we can solve my Timer issue together.

    Kind regards

    Simon

  • Hello Simon,

    simon1516 said:

    I debugged this and debug terminal shows me, that the error is here: app_timer2.c:559 --> (ASSERT(timeout_handler);)

    I´m not really sure, what to insert in the "app_timer_create" for timeout_handler. I read that there is a function coming in, which is executed when the timer is expired. Could you please give me an example for this?

    You may not provide NULL as the event_handler argument here, this is the reason why it ASSERTS. Are you familiar with using ASSERT?
    If you are unsure what you should provide as arguments to a function, or how to use a function, please see the functions API Refernce.
    In this case, from the app_timer_create API Reference you can see that the third argument is the event_handler, which is the function to be called when the timer expires.
    In your case, you may therefore do a TWIM transfer for each expiration, for example.

    An example for an event_handler function is for instance the saadc_event_handler from the SAADC example.
    This is the function that is called every time the SAADC generates an event - which then is used to handle those events.
    So, when a DONE event is generated, the saadc_event_handler is the function that process the samples that are collected.
    Or, in your case, the timers event handler is the function you would like to call every time the timer expires.

    simon1516 said:
    I´m doing this actually with one read with 14 bytes. This works fine :-)

    Great, I am glad to hear that!
    In that case, adding a 500 us delay before the transfer should not increase your power consumption too much.

    simon1516 said:
    I disabled deferred logging. Now there are no longer errors with this, so this works too :-)

    Great! Just keep in mind that this adds some processing time to each NRF_LOG_* line in your function. So, if you have a function with a lot of debugging write-outs you it will take much longer to complete with DEFERRED LOGGING set to 0.

    simon1516 said:

    To this error again: Disabling the deffered logging solves that there are no longer the messages "Logs dropped ()". But the main problem was not solved. I debugged again. And the code stops every time after exactly three minutes, because it is calling "static void sleep_mode_enter(void)"  and "err_code = sd_power_system_off();"

    Exactly three minutes, this is the time, the system is advertising for BLE devices! If I connect with nRF connect Mobile App to the nRF Chip, the TWIM doesn´t stop. The transmission is working until BLE connection is closed. So after advertising, the chip is calling the sleep mode was the explanation here.

    Like it works is okay, because TWIM just has to send data if a BLE connection is established. I just want to give you feedback for this.

    Good catch, I am happy to hear that you were able to identify the root of the behavior! This is exactly the time that your device is advertising.
    You may disable this feature, but it is a very good power-saving feature. What it does is make the device sleep if it has been without a connection for too long - conserving power by reducing RADIO ON time.
    In your situation, it sounds like you should keep this feature, if you only need to be awake when in a connection.
    Thank you for the feedback on this, I too am curious to hear about the problems resolve.

    simon1516 said:
    Have a nice weekend, I hope we can solve my Timer issue together.

    Thank you Simon, I did indeed have a nice weekend! I hope yours was as well.

    I think we are close to solving the Timer issue. I look forward to hearing if my comments above were helpful in resolving it!

    Best regards,
    Karl

Reply
  • Hello Simon,

    simon1516 said:

    I debugged this and debug terminal shows me, that the error is here: app_timer2.c:559 --> (ASSERT(timeout_handler);)

    I´m not really sure, what to insert in the "app_timer_create" for timeout_handler. I read that there is a function coming in, which is executed when the timer is expired. Could you please give me an example for this?

    You may not provide NULL as the event_handler argument here, this is the reason why it ASSERTS. Are you familiar with using ASSERT?
    If you are unsure what you should provide as arguments to a function, or how to use a function, please see the functions API Refernce.
    In this case, from the app_timer_create API Reference you can see that the third argument is the event_handler, which is the function to be called when the timer expires.
    In your case, you may therefore do a TWIM transfer for each expiration, for example.

    An example for an event_handler function is for instance the saadc_event_handler from the SAADC example.
    This is the function that is called every time the SAADC generates an event - which then is used to handle those events.
    So, when a DONE event is generated, the saadc_event_handler is the function that process the samples that are collected.
    Or, in your case, the timers event handler is the function you would like to call every time the timer expires.

    simon1516 said:
    I´m doing this actually with one read with 14 bytes. This works fine :-)

    Great, I am glad to hear that!
    In that case, adding a 500 us delay before the transfer should not increase your power consumption too much.

    simon1516 said:
    I disabled deferred logging. Now there are no longer errors with this, so this works too :-)

    Great! Just keep in mind that this adds some processing time to each NRF_LOG_* line in your function. So, if you have a function with a lot of debugging write-outs you it will take much longer to complete with DEFERRED LOGGING set to 0.

    simon1516 said:

    To this error again: Disabling the deffered logging solves that there are no longer the messages "Logs dropped ()". But the main problem was not solved. I debugged again. And the code stops every time after exactly three minutes, because it is calling "static void sleep_mode_enter(void)"  and "err_code = sd_power_system_off();"

    Exactly three minutes, this is the time, the system is advertising for BLE devices! If I connect with nRF connect Mobile App to the nRF Chip, the TWIM doesn´t stop. The transmission is working until BLE connection is closed. So after advertising, the chip is calling the sleep mode was the explanation here.

    Like it works is okay, because TWIM just has to send data if a BLE connection is established. I just want to give you feedback for this.

    Good catch, I am happy to hear that you were able to identify the root of the behavior! This is exactly the time that your device is advertising.
    You may disable this feature, but it is a very good power-saving feature. What it does is make the device sleep if it has been without a connection for too long - conserving power by reducing RADIO ON time.
    In your situation, it sounds like you should keep this feature, if you only need to be awake when in a connection.
    Thank you for the feedback on this, I too am curious to hear about the problems resolve.

    simon1516 said:
    Have a nice weekend, I hope we can solve my Timer issue together.

    Thank you Simon, I did indeed have a nice weekend! I hope yours was as well.

    I think we are close to solving the Timer issue. I look forward to hearing if my comments above were helpful in resolving it!

    Best regards,
    Karl

Children
  • Hi Karl,

    I´m sorry for late reply.

    You may not provide NULL as the event_handler argument here, this is the reason why it ASSERTS. Are you familiar with using ASSERT?

    No, not really. I don´t know for what this is for.

    _______________________________________________

    If you are unsure what you should provide as arguments to a function, or how to use a function, please see the functions API Refernce.

    Okay, I get it. I did it the same way like provided by the SAADC example. So now, every time the timer expires, my "sensor_data_read" function should be called. This is, what I would like to have.

    Unfortunaly, it doesn´t work completely. I tried to start my timer in the main loop. While compiling I get a warning. Could you tell me, what is the reason for this?

    I commented out my "read_sensor_data" function because it is called automatically by expiration of the time (i hope so :-) ).

    I think there is something wrong with the definition of my timer_id. As described in the nordic InfoCenter, I declared this variable as a static. Do I have to pay attention to something other?

    Thanks in Advance,

    Simon

  • Hello Simon,

    simon1516 said:
    I´m sorry for late reply.

    Do not worry about this at all, it is no problem.

    simon1516 said:
    No, not really. I don´t know for what this is for.

    Using ASSERTs in your code is a very helpful tool when debugging, to make sure certain conditions are always fulfilled before executing code.
    Here is a brief explanation. In this case, the ASSERT tells us that you did not provide the function with the required parameters, and it therefore can not continue.

    simon1516 said:

    Okay, I get it. I did it the same way like provided by the SAADC example. So now, every time the timer expires, my "sensor_data_read" function should be called. This is, what I would like to have.

    Unfortunaly, it doesn´t work completely. I tried to start my timer in the main loop. While compiling I get a warning. Could you tell me, what is the reason for this?

    Please tell me what the warning said - there is no way for me to see this from your included picture. What are you trying to do in your static const my_timer_id = 3; line?
    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.

    simon1516 said:
    I commented out my "read_sensor_data" function because it is called automatically by expiration of the time (i hope so :-) ).

    Cool, lets get this timer configuration out of the way, so we may see if it works!

    simon1516 said:
    I think there is something wrong with the definition of my timer_id. As described in the nordic InfoCenter, I declared this variable as a static. Do I have to pay attention to something other?

    Yes, as I mentioned above you will need to use the INSTANCE macro. If you are uncertain about how something like this should be done, the fastest way to find out is to check a similar example and see how it is implemented there! :) 
    You will also need to make sure that the timer is enabled in your sdk_config file ( but since you did not receive a compiler error I think it already is ).
    Also here you may check the sdk_config file of the example, to see that it matches up on the particular functionality you are interested in using.

    Best regards,
    Karl

  • 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

Related