Callbacks with MPU


I’m writing code that will most likely use a callback function. My problem is that I have the MPU enabled. I’m predicting that this will cause a hard fault due to unauthorized memory access when the callback function is called since this function will most likely reside outside the task that calls it.

I realize that there are queues and events that I can use. Would generating an event and catching it be the best substitute for a direct callback? I’d rather use the best or standard technique for this.



Because task code is generally NOT very localized, because it likely calls all sorts of various library code (which because it is shared CAN’T be localized to the task), when running under an MPU, generally there is one segment assigned that gives Read Only Access to all of the “Code” segment. Then a Read-Write segment is created for the Stack, and additional segments for any global structures that it needs to access.

Thus, a normal callback isn’t a problem, unless it needs data access to things the task calling the callback couldn’t access.

This is different than a SECURE memory architecture, where there is a “security zone” where code running in the security zone has full access (possibly limited by a MPU) and code outside the the security zone has no access to data or code in the security zone except via specifically defined gates. In a SECURE architecture, it is difficult to have a callback cross the security zone.

To amplify a few points that @richard-damon made.

The callback will be executed with the privilege of the calling task. If the callback “calling” task and the callback “owning” task are privilege “peers” and isolated from each other, then sharing variables directly will not be possible (MPU exception) but using a queue will still be possible because that will copy the data with the kernel (supervisor level privilege)

If your callback is going to be executed by a task with supervisor privilege (kernel callback such as a timer) then your callback will have access to everything. Be careful because you can build in a security hole or at least a bug that is hard to track down.

Thanks guys, but this is precisely why I’m asking for the best technique. Let’s assume that one or both tasks are not privileged.

If you are developing the API and you want to be sure that the two tasks are fully isolated, then I would recommend a queue to pass data and event notifications for signals.

Often the callback is present to allow code to asynchronously notify other code. If you are not sure of your notification channel, (queue, semaphore, task notification, etc) then you might use a callback to inject the desired notification. This callback is an opportunity to break task isolation which might be important to you.

Thanks Julicher. Ok, it looks like the best method is via message queue.

Remember that defining a call-back interface means that your routine is allowing “unknown” code to run with its abilities. There are cases this makes sense, but they tend to imply that the whole program is to be considered “trusted”.

Use of an MPU doesn’t mean you don’t trust the code, but it could be just for safety purposes, you want to limits its ability. Then a callback might make sense to allow the client task to define how it wants to be notified.