How do I redirect timer output for STM32F10x to a given GPIO pin?
In my opinion, the question is unclear, so here's what I understood, correct me if I'm wrong: you want to generate a PWM signal, but you want to programmatically switch the GPIO from which it is output, among a set of 16 pins. So maybe at one time you need it being output from PA0, but after a while you want to output it from PA1, and later from PA2, and so on up to PA15. (All GPIO pin numbers are just an example, of course). I'll answer assuming that my interpretation is correct.

The problem

In the STM32 series, you can't just connect an output from a peripheral to any pin of your liking. There may only be a few alternate function remaps available. Certainly you can't just switch a single signal to any of 16 different GPIOs. So, there's no "clean" solution to this problem. Anything you do will feel like a hack. You'll have to be pragmatic here, and despite thinking that any of the following solutions are "ugly", you'll have to choose based on objective requirements: cost, power consumption, CPU load, jitter, etc.

External Hardware

There's of course a solution involving external hardware, as mentioned above: maybe a decoder, in which you apply a single PWM signal in the input, and use 4 GPIOs from your MCU to select which one of 16 pins will output the signal in question. Another possibility is 16 AND gates: one input from every AND gate connected to the same GPIO generating the PWM signal, and then 16 GPIOs connected to the other 16 AND inputs. But I assume you don't care about a hardware solution.

Software only

Then there's a software solution, which you have already described: trigger an interrupt from the timer and set/reset GPIOs during the interrupt handler. I see nothing wrong with this, especially if you're dealing with low frequency signals. A couple hundred kHz should be doable without any optimizations, and a couple MHz might be doable if you programmed the registers directly rather than using the standard peripheral library. Of course, if you have hard real time requirements that might compete for CPU time with this interrupt handler; a high frequency PWM signal; low jitter requirement; lots of interrupts firing; and/or a high CPU load, this solution might not be acceptable. Still, I find nothing wrong with it otherwise. I'd use it without any objections if it didn't conflict with any other requirements.

Multiple timer peripherals

Finally, here's a solution using only the timer peripherals, but unfortunately it involves using many timers at once. Each timer has 4 different channels. Using all 4 channels of each of 4 different timers, you can meet the requirement of 16 GPIOs. An alternative that requires less timers is to selectively remap the timer pins. To illustrate, the following set of 16 GPIOs, plus TIM3 and TIM4, can be used:


PA6 - TIM3_CH1 (no remap)
PA7 - TIM3_CH2 (no remap)
PB0 - TIM3_CH3 (no remap)
PB1 - TIM3_CH4 (no remap)
PC6 - TIM3_CH1 (full remap)
PC7 - TIM3_CH2 (full remap)
PC8 - TIM3_CH3 (full remap)
PC9 - TIM3_CH4 (full remap)
PB6 - TIM4_CH1 (no remap)
PB7 - TIM4_CH2 (no remap)
PB8 - TIM4_CH3 (no remap)
PB9 - TIM4_CH4 (no remap)
PD12 - TIM4_CH1 (remap)
PD13 - TIM4_CH2 (remap)
PD14 - TIM4_CH3 (remap)
PD15 - TIM4_CH4 (remap)


Now, the way to do this is to configure TIM3 and TIM4 using the exact same time base unit configurations (which depend on your PWM signal frequency). Then, configure all 4 channels of both timers, again using an identical configuration for all channels.

At this point, you can disable all outputs by programing all 4 CCR registers of both TIM3 and TIM4 (either directly or using the TIM_SetCompareX(), with X = 1,...,4, standard peripheral library functions). Depending whether you want an inactive output to be low or high, you can set the CCR registers to either 0 or a value higher than the auto-reload register value configured in the time base unit.

Now you'll need to activate one of the 16 GPIOs you want. Depending on which GPIO you want to use, you may need to enable or disable the alternate function remap feature for that timer -- check the GPIO_PinRemapConfig() function in the standard peripheral library. Then, for the specific timer and channel that corresponds to the GPIO you want to use, you'll want to configure the CCR register (again using the TIM_SetCompareX() functions) to produce the exact duty cycle you want for your PWM signal.

When switching to another one of your 16 GPIOs, remember to set the CCR register previously in use to 0 or a high enough value (as explained two paragraphs above), which disables the GPIO currently in use, and then go through the procedure explained in the previous paragraph to enable a new one.

Efficiency: this solution uses only two timers (note that you'd have to use one anyway) and every channel on these two timers. It doesn't require external hardware, and it doesn't require firing an interrupt at the rate of your signal -- you initialize the timers once, and then do some further configurations every time you want to change from one GPIO to another. I've given this some thought and I don't think there exists any other solution that would use less resources than what I'm proposing.