> I'm note sure whether such an optimisation is the right approach, even though > it saves memory. > > The underlying problem is how dynamic the current Arduino SPI library is, > preferring to use a dynamic SPI.begin() method that allows the chip select > pin to be declared at runtime. That leads to the necessity of compiling in > the Arduino PIN table, i.e. a data structure that defines each physical MCU > pin each Arduino PIN is. That takes about 0.5 kb. Before SPI all of our > code was carefully written so that the table could be optimised away at > compile time. With the SPI.begin() interface that is no longer possible, at > least not without link-time constant propagation. And I think that wouldn't > help either, I doubt even LLVM is able to do large enough constant inferences > to be able to do that. > > The latest commit in feature-coap-temp now connects the ENC28J60 code > directly to our own low-level SPI API, written in C, allowing the dynamic > Arduino SPI interface to be bypassed. While that saves memory, it also makes > our ENC28J60 incompatible with other Arduino-compatible stacks. I came to the conclusion that we most probably want both the dynamic, Arduino style C++ interface and a lower-level, Ell-i style statically allocated C interface. Hence, I refactored the SPI library quite heavily, structuring it better from this point of view. I also updated the ENC28J60 slightly, to use the new SPI library. The code compiles and is now pushed to the feature-coap-temp branch; this time I didn't have energy to test whether it works or not. If you find out that it doesn't, please let me know immediately. I'm not completely happy with the ELL-i style C interface to SPI, yet, though. The main thorn is the need to define the slave select pin as a static const member variable: https://github.com/Ell-i/Runtime/blob/feature-coap-temp/stm32/libraries/CoAP/arch/enc28j60/ENC28J60Class.h#L35 If I define it as a non-static const member variable, then the pinMode and digitalWrite functions won't get optimised away with constant propagation, leasing to code bloat with some 800 bytes due to the compiler including the GPIOPIN table into the object code: https://github.com/Ell-i/Runtime/blob/feature-coap-temp/stm32/libraries/CoAP/arch/enc28j60/ENC28J60Class.h#L35 That we don't want; we want the table to be optimised away at the compile time. And that requires that the slave select pin used in pinMode and digitalWrite is a compile-time constant. I still need to contemplate how that could be done without a static member variable. Most probably I will need to inline more of the ENC28J60 code so that it gets compiled along with the user program, as the user program will have all the required knowledge there, including the const ENC28J60 instance, etc. But I haven't figured out how exactly to do it, yet. Will continue another day, don't know if I'll have time tomorrow or on Wednesday. Another smaller issue is that the current enc28j60 interface takes quite a lot of space, about 1800 bytes. I have some ideas how to optimise that, but it needs to wait until I get the C-style SPI interface ready first. I think that we could also create two ENC28J60<->SPI interfaces, one using this lower-level C-style API, and another using the dynamic Arduino-style C++ API. How to make the difference between those at compile time still needs to be figured out, though. In any case, it looks like that we'll need some more link-time intelligence for our makefiles anyway. --Pekka