KurtE
Senior Member+
Hi @mjs513 - Hope your wife is doing better!
Some of this stuff is still sort of voodoo for me as well. More or less I learned it from example... (@Paul's changes back for T3.x in trying to remove the dependencies on c++ constructor ordering and the like... So the constructor has the keyword constexpr
Which I don't know the exact requirements (I have looked them up and the like) and sometimes I have had to do some trial and error to make work...
But some of the basic things is that all member variables must be initialized or filled in by constructor...
What typically I would have liked to do with for example SPIClass is to simply pass in the address of the Hardware define as well as the pointer to the register structure... Which sort of works, but then when someone else references it in their class, example SerialFlash, you end up with some cryptic errors... Which happened recently.
So instead we pass in a generic pointer (ujintptr_t). So in the FlexIOHandler case we have, some of this, in the class like:
So the constructor has three addresses passed in all of them as uintptr_t type, which then the constructor assigns the passed in values into member variables, which in my case are in the protected section. So port_addr = myaddr; ...
Then we use the the registers, we use the helper function port, which casts the address back to a reference to the underlying register set.
So in this case we would do something like port().PARAM
Edit: and then to create the objects, I have the lines, like
Hope that helps
Some of this stuff is still sort of voodoo for me as well. More or less I learned it from example... (@Paul's changes back for T3.x in trying to remove the dependencies on c++ constructor ordering and the like... So the constructor has the keyword constexpr
Which I don't know the exact requirements (I have looked them up and the like) and sometimes I have had to do some trial and error to make work...
But some of the basic things is that all member variables must be initialized or filled in by constructor...
What typically I would have liked to do with for example SPIClass is to simply pass in the address of the Hardware define as well as the pointer to the register structure... Which sort of works, but then when someone else references it in their class, example SerialFlash, you end up with some cryptic errors... Which happened recently.
So instead we pass in a generic pointer (ujintptr_t). So in the FlexIOHandler case we have, some of this, in the class like:
Code:
class FlexIOHandler {
public:
...
constexpr FlexIOHandler(uintptr_t myport, uintptr_t myhardware, uintptr_t callback_list)
: port_addr(myport), hardware_addr(myhardware), _callback_list_addr(callback_list) {
}
IMXRT_FLEXIO_t & port() { return *(IMXRT_FLEXIO_t *)port_addr; }
const FLEXIO_Hardware_t & hardware() { return *(const FLEXIO_Hardware_t *)hardware_addr; }
...
protected:
uintptr_t port_addr;
uintptr_t hardware_addr;
uintptr_t _callback_list_addr;
uint8_t _used_timers = 0;
uint8_t _used_shifters = 0;
bool _irq_initialized = false;
};
Then we use the the registers, we use the helper function port, which casts the address back to a reference to the underlying register set.
So in this case we would do something like port().PARAM
Edit: and then to create the objects, I have the lines, like
Code:
static FlexIOHandler flexIO1((uintptr_t)&IMXRT_FLEXIO1_S, (uintptr_t)&FlexIOHandler::flex1_hardware, (uintptr_t)flex1_Handler_callbacks);
Hope that helps