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
> > >>
> > >>
> > >>
> > >
> >
> >
> >
>
>

Reply via email to