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

TWIM issue

Hello ,
I am working on a project which contains I2C communication,
When I test the twi scanner example on my sensor and it works fine
But when I do the combination with the usbd_ble_uart example to send the data to uart I encountered a problem during an I2C read operation. My code stuck in this infinite loop

bool transmission_finished = false;
        do {
            if (nrf_twim_event_check(p_twim, NRF_TWIM_EVENT_SUSPENDED))
            {
                transmission_finished = true;
            }

            if (nrf_twim_event_check(p_twim, NRF_TWIM_EVENT_STOPPED))
            {
                nrf_twim_event_clear(p_twim, NRF_TWIM_EVENT_STOPPED);
                transmission_finished = true;
            }

            if (nrf_twim_event_check(p_twim, NRF_TWIM_EVENT_ERROR))
            {
                nrf_twim_event_clear(p_twim, NRF_TWIM_EVENT_ERROR);

                bool lasttx_triggered = nrf_twim_event_check(p_twim, NRF_TWIM_EVENT_LASTTX);
                uint32_t shorts_mask = nrf_twim_shorts_get(p_twim);

                if (!(lasttx_triggered && (shorts_mask & NRF_TWIM_SHORT_LASTTX_STOP_MASK)))
                {
                    // Unless LASTTX event arrived and LASTTX_STOP shortcut is active,
                    // triggering of STOP task in case of error has to be done manually.
                    nrf_twim_task_trigger(p_twim, NRF_TWIM_TASK_RESUME);
                    nrf_twim_task_trigger(p_twim, NRF_TWIM_TASK_STOP);

                    // Mark transmission as not finished yet,
                    // as STOPPED event is expected to arrive.
                    // If LASTTX_SUSPENDED shortcut is active,
                    // NACK has been received on last byte sent
                    // and SUSPENDED event happened to be checked before ERROR,
                    // transmission will be marked as finished.
                    // In such case this flag has to be overwritten.
                    transmission_finished = false;
                }

                if (lasttx_triggered && (shorts_mask & NRF_TWIM_SHORT_LASTTX_SUSPEND_MASK))
                {
                    // When STOP task was triggered just before SUSPEND task has taken effect,
                    // SUSPENDED event may not arrive.
                    // However if SUSPENDED arrives it always arrives after ERROR.
                    // Therefore SUSPENDED has to be cleared
                    // so it does not cause premature termination of busy loop
                    // waiting for STOPPED event to arrive.
                    nrf_twim_event_clear(p_twim, NRF_TWIM_EVENT_SUSPENDED);

                    // Mark transmission as not finished yet,
                    // for same reasons as above.
                    transmission_finished = false;
                }
            }
        } while (!transmission_finished);

Although I tried to copy all the configuration performed in the example of twi scanner

Please Help me .

Parents
  • Hello nikola,

    When I test the twi scanner example on my sensor and it works fine

    Thank you for clarifying this - then we know that there is no issue with your hardware connections. 

    But when I do the combination with the usbd_ble_uart example to send the data to uart I encountered a problem during an I2C read operation. My code stuck in this infinite loop

    Which priority are you using for your TWI and USBD IRQ's?
    The TWI peripheral examples does not have to account for the fact that it may be interrupted at any time (such as by the SoftDevice), so I suspect the issue here is that the TWI transfer or post-processing is being interrupted at an inopportune time, which causes it to get stuck in this loop. If this is the case, you will either have to change your tranmission_finished implementation, or add some sort of watchdog / timer / specific error handling to this loop, in order to break out if this occurs.
    Lets start by identifying exactly why it does wrong, and then look into what we may do to avoid it.

    Best regards,
    Karl

  • Thank you for answering me
    I solved this error
    but I have another problem concerning the execution of the two processes in the same while loop  when I put the two commands together in while (true) of main.c the sensor sends the data until a given moment and it stops the execution
    i want to know how i can run both codes in the same while loop

  • Hello,

    I see that you are still not checking all your error codes. Please fix this, and confirm when you have done so.

    To answer your original question about why there is never more than 1 thing happening in your code, this likely is due to the multiple while(1) / for(;;) loops in your main function.

    As far as a general code review goes on the code you have posted, there is a lot to talk about in your main function.
    You main function seems to contain a cascade of lesser functions, all in one giant mix - this is far from best practice. Do these parts all work independently?

    Furthermore, utilizing interrupts in your code to branch and jump in the flow of the code execution is essential when working with microcontrollers and embedded systems, and I strongly recommend that you look into how you may move 98% of your current main() code into interrupt handles or separate functions outside of main(). The main context is the lowest priority interrupt level, and is meant to be interrupted by any other IRQ in your program.

    You are also defining a lot of functions within your main() function. This is not allowed in standard C code, and should not happen. It would surprise me if the compiler accepts this in the first place. Move all function definitions outside of main.

    You are also using a lot of RAM to declare and store variables that you use for your configuration, which I believe are static ones. If this is the case, you should instead use defines, so that the compiler can deal with them.
    Since all these variables are defined in the scope of your main function they will persist throughout the program. Memory optimization might not be a concern at the moment, but it too is an important concept to know about when working with embedded development.

    On a general note, I notice that you are using a lot of magic numbers in your code. I strongly recommend that you make properly names define's for each of these numbers, to drastically increase your code's readability and maintainability. You will save a lot of time and frustration in the long run by doing so.

    There is still a lot more that can be said and commented on in the code as well unfortunately, but let us start with the things I have mentioned here already, and take it from there.

    Please know that I do not intend to sound crass in any part of my reply - everything I am pointing out is only in the interest of improving your overall project and code, and hopefully save you from a lot of tedious work and frustration down the road.

    Please do not hesitate to ask if any part of my feedback is unclear, or in the case that you should have any additional questions.

    Best regards,
    Karl

  • P.S - please use the Insert -> File option when sharing a file of code that does not fit into a single Insert -> Code prompt.

  • I see that you are still not checking all your error codes. Please fix this, and confirm when you have done so.

    i don't know how i can do it can you give me an example

  • You need to review and verify that every SDK function that you use, that return an error code, has that error code passed to an APP_ERROR_CHECK, or other error handling.

    For example, in your code you have the following lines:

    err_code = nrf_drv_twi_tx(&m_twi, MX30105_ADDR,&FIFO_Write_PointerADD, 1, false);
    nrf_delay_ms(5);
    err_code = nrf_drv_twi_rx(&m_twi, MX30105_ADDR, &FIFO_Write_Pointer,1);
    nrf_delay_ms(5);
    if (err_code != NRF_SUCCESS)
    {
        NRF_LOG_INFO(" ERROR IN Write Pointer:  0x%x", FIFO_Write_Pointer);
        NRF_LOG_FLUSH();
        error = 1;
    }

    Here you see that the first of these two returned error codes are never actually checked or used for anything, before it is immediately overwritten.
    If this error code should ever come back with a value != NRF_SUCCESS, you will never know about it and proceed as usual, which could break the continuation of your program.

    Best regards,
    Karl

  • nd I strongly recommend that you look into how you may move 98% of your current main() code into interrupt handles or separate functions outside of main()

    how can I do this please

Reply Children
  • You can start by moving all function definitions outside of main(), for example. Then, you need to determine which of them should be called as part of an interrupt service routine, and then implement that routine.

    Are you familiar with interrupt service routines / IRQ's / callback functions?
    If not, I recommend that you familiarize yourself with this subject through either a video series or blog series on the topic, for example. The scope of it is too broad to cover here in a comment, but in essence; Interrupts lets the CPU be alerted to events that has occurs outside of the regular program flow (main), so that it can jump to a different section of the code to handle this event, before resuming its regular program flow (main). Interrupts are the cornerstone of an event-triggered embedded system.

    Bet regards,
    Karl

  • when I add APP_ERROR_CHECK I have got this error 

  • you need to determine which of them should be called as part of an interrupt service routine, and then implement that routine.

    I don't understand you very well Can you expalin to me in another way

  • nikola said:
    when I add APP_ERROR_CHECK I have got this error 

    Great, this means that the function actually did return an error. Please view the entire error message, it will say which line of your code that generated the NRF_ERROR_INVALID_ADDR error. Then you will need to look at the API reference for that function, to determine why it would return this particular error.

    nikola said:
    I don't understand you very well Can you expalin to me in another way

    I am not sure that my written text answers here might be the best way for you to learn about interrupts and events. Perhaps it could help you to take a look at this third party video tutorial on the topic.
    I strongly recommend that you get a good understanding of this fundamental embedded C concept before you continue the development of your application, as it will be impossible to create an application with the functionality and complexity that you describe above without understanding and using interrupts and events.

    Best regards,
    Karl

Related