If your code isn't working as the clock speed reduces it sounds like you're keeping all the interupt sources alive (nested interupts) when your servicing an interupt routine. With all the interupts enabled all the time, you will jump out of some code and into a higher order interupt if one occurs, only returning to a lower order interupt once the highest order one has finished.
This can lead to major timing issues if the interupt priorities aren't properly managed especially with communication ports such as a UART & SD CARD. If one assumes the GPIO are connected to the outside of your box, then the GPIO interupts will happen "at will" in a data logger and can't be predicted so keeping these routines very short is advantageous.
This may lead to setting a maximum GPIO toggle rate for these external pins so your code remains valid (maximum 100Hz on any external Input pin, and a maximum of 2 KHz across all inputs for example).
If you want to reduce current then you run in active mode at a higher clock speed, by altering the code so that all routines are event driven and go into a sleep or wait mode for the rest of the time to reduce the supply current. A few microcontrollers have extremely low current Wait modes by 75% of active mode (CPU off, peripherals on) but most only reduce the current by ~20-30% from active mode.
One or two micro vendors can even keep the peripherals running in deep sleep modes with fast wake-up, but most micro's usually turn off all the peripherals in deep sleep and only allow the the GPIO, WDT, POR, BOR or an RTC to wake up a micro.