Do folks think having a pin_t type makes sense where the function of the pin can be stored in a standard way? I could see an argument for this — obviously we couldn’t change all the code at once, but we could start by adding that, and then slowly migrate to it.

On 8 Mar 2018, at 23:04, markus wrote:

Hi Miguel,

that is what I'm currently doing. I thought it might be possible to store the alternate function in the pin itself, if a pin variable would have at leas 12 bit. But mynewt does not declare a type for a pin, and there is no standard about the variable size of storing a pin. Some components (including pwm) use a uint8_t - which is barely enough to store the pad id alone.

For now it seems we'll have to put the burden of on the user.

Thanks,
Markus

On Fri, 9 Mar 2018 04:16:44 -0100
Miguel Azevedo <miguella...@gmail.com> wrote:

Hi Markus,

One thing I forgot to mention, and that after giving this some thought
makes some sense, is to pass the pin restriction information (what
channels a pin may accept, etc) using the data parameter on
pwm_dev_init, passed through os_dev_create which is called on
hal_bsp.c. For me it makes sense to have these values stored somewhere
on the BSP (or even MCU), since they look like they are directly
dependent on the board model(or the mcu model?) you're using.

Best regards,

Miguel

On Thu, Mar 1, 2018 at 5:57 PM, Wayne Keenan <wayne.kee...@gmail.com>
wrote:
It is a complicated issue indeed.
Forgetting the pins, the CubeMX tool also resolves conflicts of
clock sources as well. (STM chips are most flexible/interesting :) )

So I'd like to point out that there are other internal parts of
MicroPython that can help guide MyNewt MCU support on clocks too,
without the need for CubeMX.



Thanks,
Wayne

On 1 March 2018 at 18:48, Wayne Keenan <wayne.kee...@gmail.com>
wrote:
That's a good point, but also having used CubeMX myself I always
thought it is very application specific design time choices.  IMHO
What MyNewt MCU support would need is 'a level above that'.

I've perhaps missed something.

But AFAIK the MicroPython CSV files are (easily) parsable
representations of what's in the STM32 data sheets for each MCU,
so it's minus the bespoke tooling, libraries and generated
boilerplate code CubeMX generates.




Thanks,
Wayne

On 1 March 2018 at 17:43, Raoul van Bergen
<raoul.van.ber...@me.com> wrote:

Hi,
Just my opinion from long time experience with STM32.

IF (!) there is anything to be supported for this from external,
it should be the definition files generated by the free CubeMX
tool from STM itself. This tool allows you to first create the
perfect matching pin assignment for your application (it was
already mentioned this can become very complicated) and next it
can generate the complete BSP /HAL support source files based on
the library from STM.

I know some other vendors have similar tools as well.

I am not advocating to use ST's own library at all but at least
the include files generated by CubeMX do hold the proper defines
and macros needed to do the pin assignments correctly and this
tool is kept up-to-date for all STM32 processors at all times, so
"your" STM32 of choice will always be there......

Regards,
Raoul



-----Original Message-----
From: Wayne Keenan [mailto:wayne.kee...@gmail.com]
Sent: 01 March 2018 18:24
To: dev@mynewt.apache.org
Cc: Miguel Azevedo <miguella...@gmail.com>
Subject: Re: recommendations for IO pin declarations

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 <mar...@bibi.ca> 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 <miguella...@gmail.com> 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 <mar...@bibi.ca>
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 <miguella...@gmail.com> 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 <mar...@bibi.ca>
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