If you take a look at MicroPython, it has CSV files describing the Alternate Functions of pins for many STM32 devices.
Files matching *_af.csv under: https://github.com/ micropython/micropython/tree/master/ports/stm32/boards Perhaps the Mynewt STM32 MCU support could/should import and use them? Thanks, Wayne On 1 March 2018 at 17:06, markus <[email protected]> wrote: > I didn't explain this correctly, let me start again. > > First off, this is not PWM specific, it is the way how STM32's map > internal peripherals to IO pads (also known as pins). > > Each IO pad can be operated in up to 16 different functions, called > alternate functions. At reset each pad assumes AF0, it's default function, > which can be changed at runtime. I've attached an excerpt of the AF table > (not sure if attachments make it through). > > Taking the IO pin PA1 as an example which has the following AF assignments > 0 ... - > 1 ... TIM2_CH2 > 2 ... - > 3 ... TSC_G1_IO2 > 4 ... - > 5 ... - > 6 ... - > 7 ... USART2_RTS_DE > 8 ... - > 9 ... TIM15_CH1N > 10... - > ..... > > At reset the pin assumes AF0, which has no alternate function which means > it is operating as a regular IO pin. If you reconfigure the pin for AF1, > then it will output whatever channel 2 of timer 2 is configured to do. If > you configure the pin for AF9 it will output whatever the complementary > channel 1 of timer 15 is configured for (regardless of you configured > channel 2 of timer 2 to do). > > So for mcu peripherals, if their signals need to be connected to a pad, > one doesn't just need the pin number, but one also needs the AF number. > > If you look at the instantiation of the uart here: > https://github.com/apache/mynewt-core/blob/master/hw/bsp/ > nucleo-f413zh/src/hal_bsp.c#L45 > you'll notice GPIO_AF7_USART3, which is required in order to connect the > signals of UART3 to the io pins. > > > > On Thu, 1 Mar 2018 09:50:16 -0300 > Miguel Azevedo <[email protected]> wrote: > > > > Unfortunately there is no universal AF value for pwm channels, on > > > some pins it's 1, on some it's 6 ... , some pins cannot be used as > > > pwm channel outputs at all and some pins could be used as the > > > output of multiple channels. > > > > Not sure I got it right. > > So you can configure a given pin using 1 or 6 depending on whether you > > want it to output a single pwm chan or multiple? > > Having a single gpio output multiple channels feels a lot like an > > uncommon feature btw. > > > > > It's bad enough that only certain pins work for a given > > > timer/channel but it's even worse because the driver also needs to > > > know the AF number to use. > > It definitely does not look great but it feels that you will need > > either a lot of #ifdefs or have the driver knowing these restrictions. > > Aren't these restrictions described on some .h from stm? > > > > > As an additional crux, the HW timer to be used (TIM1 above) > > > typically gets defined by the BSP in hal_bsp_init, whereas > > > pwm_chan_config is application runtime code. I would prefer to > > > break the coupling, or at least make it less fragile. > > > > I see, I'm not sure about that one. I mean it does not make much sense > > to me, because one might want to reconfigure channels on runtime, just > > take a look at what we're doing on pwm_test on last PR. > > > > It sounds like stm PWM has a bunch of limitations you have to deal > > with and there are some things you probably won't be able to run from. > > I already implemented two PWM drivers using the current interface, I > > think we should be flexible at this stage regarding the API interface > > so it will be useful for you. > > However I feel that having an AF field by default doesnt make much > > sense. > > > > Thanks, > > > > On Thu, Mar 1, 2018 at 2:51 AM, markus <[email protected]> wrote: > > > This is the implementation of pwm_configure_channel: > > > > > > static int > > > stm32f3_pwm_configure_channel(struct pwm_dev *dev, uint8_t cnum, > > > struct pwm_chan_cfg *cfg) { > > > stm32f3_pwm_dev_t *pwm; > > > > > > assert(dev->pwm_instance_id < PWM_COUNT); > > > assert(cnum < STM32F3_PWM_CH_COUNT); > > > > > > pwm = &stm32f3_pwm_dev[dev->pwm_instance_id]; > > > > > > if (STM32F3_PWM_CH_DISABLED != pwm->ch[cnum].config) { > > > return -1; > > > } > > > > > > if (STM32F3_PWM_CH_NOPIN != cfg->pin) { > > > if (hal_gpio_init_af(cfg->pin, > > > (uint8_t)(uintptr_t)cfg->data, > > > HAL_GPIO_PULL_NONE, > > > 0)) { > > > return -1; > > > } > > > } > > > > > > pwm->ch[cnum].duty = 0; > > > pwm->ch[cnum].pin = cfg->pin; > > > pwm->ch[cnum].invert = cfg->inverted; > > > pwm->ch[cnum].update = 0; > > > pwm->ch[cnum].enabled = 0; > > > pwm->ch[cnum].configure = 1; > > > > > > return 0; > > > } > > > > > > On an STM to connect the output pad with the PWM channel I have to > > > configure it for the alternate function (which is done by > > > hal_gpio_init_af). The AF value, the result of > > > `(uint8_t)(uintptr_t)cfg->data` is a value between 0 and 15 which > > > determines what the pin is used for. > > > > > > Unfortunately there is no universal AF value for pwm channels, on > > > some pins it's 1, on some it's 6 ... , some pins cannot be used as > > > pwm channel outputs at all and some pins could be used as the > > > output of multiple channels. > > > > > > With the construct above the application has to make a call like: > > > > > > struct pwm_chan_cfg cfg; > > > cfg.pin = 8; > > > cfg.inverted = false; > > > cfg.data = (void*)6; > > > pwm_chan_config(pwm, 0, &cfg); > > > > > > But this ONLY works if `pwm` is bound to the mcu's TIM1 and you use > > > channel 0. For TIM1 and channel 1 the app would have to use > > > `pin=9/data=6`. > > > > > > It's bad enough that only certain pins work for a given > > > timer/channel but it's even worse because the driver also needs to > > > know the AF number to use. > > > > > > As an additional crux, the HW timer to be used (TIM1 above) > > > typically gets defined by the BSP in hal_bsp_init, whereas > > > pwm_chan_config is application runtime code. I would prefer to > > > break the coupling, or at least make it less fragile. > > > > > > Does this make sense? > > > Markus > > > > > > > > > On Thu, 1 Mar 2018 01:58:46 -0300 > > > Miguel Azevedo <[email protected]> wrote: > > > > > >> Hi markus, > > >> > > >> > `struct pwm_chan_config` only specifies the pin number. I've been > > >> > using the `data` member to put the burden on the application to > > >> > specify the "correct" number for the alternate function > - but I > > >> > find this a little unsatisfactory. > > >> That sounds a lot driver/hw specific. Can you show us the code for > > >> that? > > >> > > >> Thanks, > > >> Miguel > > >> > > >> On Wed, Feb 28, 2018 at 9:57 PM, markus <[email protected]> wrote: > > >> > While writing a PWM driver for the STM32s mcu family I came > > >> > across the issue of assigning output pins for a pwm channel. > > >> > > > >> > PWM output in STM32s is done by configuring a pin for "alternate > > >> > functions" - where specific pins have specific (possible) > > >> > alternate functions. In other words, only a very limited number > > >> > of timer:channel:pin combinations are possible, each one > > >> > requiring a very specific alternate function. > > >> > > > >> > `struct pwm_chan_config` only specifies the pin number. I've been > > >> > using the `data` member to put the burden on the application to > > >> > specify the "correct" number for the alternate function - but I > > >> > find this a little unsatisfactory. > > >> > > > >> > So I was wondering if somebody has a recommendation, better > > >> > approach to solving this issue? > > >> > > > >> > Have fun, > > >> > Markus > > >> > > >> > > >> > > > > > > > > > > >
