MQX SPI file write during interrupt

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

MQX SPI file write during interrupt

Jump to solution
1,723 Views
jamamohamed
Contributor II

Hi all,

I am new to using MQX and have been trying to get a host-driven nRF8001 driver ported, but am having trouble with SPI during interrupts.

As of how my main issue stems from not being able to use SPI during a software interrupt task. Because the spi file was open by my main task, the interrupt is not allowed to use that same pointer and just doesn't write. Am because it is in an interrupt, I don't want to have to open a new file and reconfigure everything every single time.

What is the typical way in MQX to do this kind of processing during an interrupt?

Best Regards,

Jama

Tags (3)
1 Solution
1,471 Views
RadekS
NXP Employee
NXP Employee

Yes, this is type of operation for which will be better to use some synchronization object instead of task_block()/task_ready() functions.

In case of interrupt it is better mark somewhere that some event happened instead of execution of direct action.

If your application is based on 1:1 flow control (1 interrupt: 1 transfer: 1 interrupt: and so on) you can use for example simple lwevent with LWEVENT_AUTO_CLEAR option. In interrupt you will just post event (let say that it is value change 0 ->1).

If some task, waits for this event it will clear this event (1 ->0) and task will become active/ready (depends on priority). This all happens in protected mode inside scheduler.

If more interrupts comes and there isn’t waiting task for event, nothing happened (event will be already set 1 ->1). If after that task will execute lwevent_wait() function, task will continue without stop because event was already set prior we wait for them (event will be cleared in this ).

If you want implement some buffer for data and occurrence of interrupts do not need exactly fits to transfers, semaphore or rather lightweight semaphore will be better choice. This object could be used as counting – post will increase counter, wait will decrease counter. When counter=0 task will became blocked until next post…

Typical solution is that tasks running in endless loops. However if task returns, it will be destroyed and you have to call task_create (or similar function) for execute this task again.

I would like to recommend do not use this concept since it could be sometimes dangerous. Task_destroy is asynchronous operation and it could work correctly only under specific conditions.

I would like to recommend this link to Essentials of MQX RTOS Application Development:

http://www.freescale.com/webapp/sps/site/training_information.jsp?code=WBT_MQX_RTOS_COURSE

It contains a lot of useful information and I hope it helps you

I hope it helps you.

Have a great day,
RadekS

-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------

View solution in original post

4 Replies
1,471 Views
RadekS
NXP Employee
NXP Employee

As first I would like to note, that it is bad idea to use any IO functions inside interrupt – even it could work under some conditions.

Very simplified reason: Typically we use IO drivers in interrupt mode – we do not wasting time in loop until data are transmitted. In case of Cortex M4 core, interrupt routine could be interrupted by interrupt with higher priority. However question is now which IO operation should have higher priority – it could be different in every application and it could depend on current state. Therefore IO operation should be used only in tasks/functions and interrupt routines should contain minimum code otherwise task priorities, scheduler and OS itself is almost useless.

Typical solution: interrupt routines contains minimum code just for handling flags, basic data manipulation and signalize for status change – by synchronization objects like lwevent or semaphore…

You could create some high priority task for sending data over SPI. This task will be blocked by waiting for lwevent. So, if you receive data in interrupt routine, place it into RAM and set lwevent. When you leave from interrupt, scheduler will automatically detect that SPI task could run as next…

If you want execute any time consuming process, please execute it inside task/function if possible.

I hope it helps you.

Have a great day,
RadekS

-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------

0 Kudos
Reply
1,470 Views
jamamohamed
Contributor II

Hi RadekS,

Yes, I realized that doing that sort of processing in the interrupts would be bad. So in my tests, I called task_ready on my high priority SPI task after loading data into a queue. The problem I'm having is that during the SPI task, if an interrupt occurs and calls task_ready and the SPI task is 1 step away from calling block - the task_ready doesn't do anything, the function blocks, and then the SPI transfer is missed. And because I do transfers on interrupt edges, it will never again see that edge and the system will fail to transfer anything ever again.

So my question is, how do I prevent this critical scenario from occurring? If the interrupt is missed, my main task would be the only one running and I would rather not have it constantly run the SPI task. Or would the correct way be to make sure the main task calls task_ready enough?

I would also like to know what happens when a task returns? Is it destroyed, or does it become ready again?

This is my first time using RTOS, so sorry for my lack of understanding.

Thank you for the help!

0 Kudos
Reply
1,472 Views
RadekS
NXP Employee
NXP Employee

Yes, this is type of operation for which will be better to use some synchronization object instead of task_block()/task_ready() functions.

In case of interrupt it is better mark somewhere that some event happened instead of execution of direct action.

If your application is based on 1:1 flow control (1 interrupt: 1 transfer: 1 interrupt: and so on) you can use for example simple lwevent with LWEVENT_AUTO_CLEAR option. In interrupt you will just post event (let say that it is value change 0 ->1).

If some task, waits for this event it will clear this event (1 ->0) and task will become active/ready (depends on priority). This all happens in protected mode inside scheduler.

If more interrupts comes and there isn’t waiting task for event, nothing happened (event will be already set 1 ->1). If after that task will execute lwevent_wait() function, task will continue without stop because event was already set prior we wait for them (event will be cleared in this ).

If you want implement some buffer for data and occurrence of interrupts do not need exactly fits to transfers, semaphore or rather lightweight semaphore will be better choice. This object could be used as counting – post will increase counter, wait will decrease counter. When counter=0 task will became blocked until next post…

Typical solution is that tasks running in endless loops. However if task returns, it will be destroyed and you have to call task_create (or similar function) for execute this task again.

I would like to recommend do not use this concept since it could be sometimes dangerous. Task_destroy is asynchronous operation and it could work correctly only under specific conditions.

I would like to recommend this link to Essentials of MQX RTOS Application Development:

http://www.freescale.com/webapp/sps/site/training_information.jsp?code=WBT_MQX_RTOS_COURSE

It contains a lot of useful information and I hope it helps you

I hope it helps you.

Have a great day,
RadekS

-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------

1,471 Views
jamamohamed
Contributor II

Using events helped me find another error I've been having. It seems like MQX completely misses some edge driven interrupts. I did not have too much time to look into it, so I simply set a reasonable timeout for events and put a manual check on the interrupt line to catch anything I may have missed. The system works nows.

0 Kudos
Reply