The dead-trivial routines I linked you towards (and I wrote) do exactly this. And they are VERY SHORT. (However, you may want to add a check for a NULL pointer in the free() function for production use -- I provided those quickly to provide the minimal example of just how easy this stuff is.) The malloc() function "sees" contiguous free blocks as a single block, during allocation. It's really quite simple.
I have a short routine (that I used myself for testing but didn't post) that displays the current state of the heap any time you want to see it. You could use that, for example, to observe and collect empirical data from real world runs. (I'd probably modify it to "write snapshots to memory" for later examination in an embedded system where printf() is problematic.) I think your approach is good -- look at the data. And luckily it is VERY EASY to do, too.
I think I've begun to understand where you are headed. If you are able to show that what is already there (the malloc/free I showed you does what you talked about, already) is good enough, then you don't have to do much at all. Just instrument it, test and verify it, document the results, and move on.
If you really want to move allocated memory so that the largest possible free space is available when you want it, then I think it is easy enough to use two otherwise generic tools and to combine them into a specialized tool perfect for your situation. Very small amount of code required, too.
I'd cobble two generic tools (malloc/free and memory marking) into a customized tool for the purpose. A lot of times, that's what a craftsman has to do. Not everything in every possible variety is ready-made all the time. You know that as well as any. Your case is a constrained one and probably any "good solution" isn't simultaneously also a "broad market solution," broad enough to gain a supporting base anyway. That is, if the already decent malloc/free shows itself unable to meet your needs, of course.
Interesting problem. But I don't think a good solution is at all difficult to come by. Especially since you control the startup code, as well.