stm32f40x: i2c: split initialization

Create a new initialize function that handles the actual initialization,
and make the init method simply grab the I2C lock and then call this
function.

This way, other uses of the initialization, such as in reset, or when
the I2C port is not ready do not need to release the lock before calling
the function.

Change-Id: I52e2dd9015475c75c56b38f8d91cccd6cf0f51f7
(cherry picked from commit 303097729a02484dcb21e4cd20ea957cb3b61eac)
stm32f40x: i2c: Pull up i2c GPIOs

I2C is an open-collector bus, SDA and SCL must be pulled up.  In case
there are no physical pull-ups on the board, enable the internal pull up
resistors.

Change-Id: Ida18eff6af298909e9adf8d54920eda24d0c8f87
(cherry picked from commit 934f0947cc838856d37696b4bc1f0cf4747a09ac)
Add rotary encoder class

Based heavily on the magnetometer class, this class provides an
interface for rotary encoder sensors.

It is not enabled by default.

Change-Id: Ic940bf050a2064c847eed0e7980d78dd61ce43b7
(cherry picked from commit 9639c308e6aa34c7f2b55cf0cea48793c656e3d8)
dev: AMS AS5048B driver

Add a driver for the AMS AS5048B I2C magnetic rotary encoder.  This
rotary encoder fulfills the standard rotary encoder interface.

The calibration used is software calibration, only valid for the life of
the object.

The standard board config struct is used, however instead of placing
config structs in each board file, define a weak, invalid, one in the
driver itself, which can be overridden by a board config.  This not only
keeps the board files clean, but saves data when the driver is not built
in.

Change-Id: I307d193526efc33b526573e826faefe862ecb73e
shell: rotary encoder shell program

Add a standard rotary encoder shell program.  Works just like accel,
gyro, etc.

Change-Id: I6526d90940f807a9f59069830c4955e3bff65d7f
(cherry picked from commit 4350eda611d146aebadc18d26d64baed1ea3bc6d)
stm32f40x: perfcounter: avoid overflow race condition

Since TIM1_CNT and TIM2_CNT are not read atomically, it is possible for
TIM1_CNT to overflow after TIM2_CNT has been read, resulting in an
incorrect complete timer value.

In order to avoid this race condition, ensure that the TIM2_CNT has not
changed after reading TIM1_CNT.  If it has, TIM1_CNT has overflowed and
the read should be restarted.

This depends on the assumption that TIM1 will not always overflow in the
time it takes to go through the loop, otherwise it will be impossible to
break out.  TIM1 is only overflowing every 390us with a 168MHz clock, so
it should be fine.

A preemptive task switch may occur between reading the upper and lower
registers.  Such an event makes it more likely that the loop will fail
upon return to the task, but does not reduce the safety of this loop.

Change-Id: I0457ca7991f3f5e99365f98b482aa05c03d9f4b6
(cherry picked from commit d3f7008ae62e15718c36150bbd2166be9d7390a2)
stm32f40x: perfcounter: use TIM2/TIM5 for 64-bit counter

Use the 32-bit timers 2 and 5 in the same slave mode previously used
with timers 1 and 2.  This provides a 64-bit timer instead of a 48-bit
timer, which will not overflow for about 7000yrs.  The 48-bit timer
overflowed after 19 days.

These timers run at system clock / 2 (probably 84MHz), so multiple the
return value by the prescaler to return approximate system clock cycles.

Change-Id: I6b99f818fef9b3128039f6773cdb8d25af9fc43c
(cherry picked from commit ff6d62714e717685a657349cfb5ed2db4eca3788)
armv7m: atomic: mark operands output only

Inline assembly operands marked as output "=", may be allocated to the
same registers as inputs, as they are assumed not to interfere.  Output
operands set before the inputs are used must be marked as output only
"&" to ensure that they do not share a register with any inputs.

Change-Id: I67adc3123d430d19a0011f6fc2148e044cf82e5e
(cherry picked from commit 5eb255294d89b564a24ef633b26acbc6ee7ce3f1)
dev: add gpio.h include

Class defines are used in dev/hw/gpio.h, they should be included.

Change-Id: I6985a6dfcbc0761bebbccc03d17f83b64832dfd0
(cherry picked from commit b74f65c84c4b1f871b17da5b26f44808431438e1)
stm32f40x: timer: overhaul timer registers

Convert the timer peripheral registers to the modern struct format,
using the raw_mem_ functions to set values in the registers.

Add register bitfield definitions for addition timer registers.

Update the perfcounter to use this format.

Change-Id: I0e8ca336d2e39788b068748e37ff37518821c335
(cherry picked from commit 0fa9302ed36c70eafa85309683c1109c18f4c54e)
dev: add pwm class

Add a PWM class for describing PWM drivers.  This class behaves more
like the GPIO class than other peripheral classes, because it does not
describe a singular peripheral.

Instead, it takes a GPIO obj, and attempts to setup PWM outputs on that
GPIO, either using some hardware peripheral (like a timer), or entirely
in software.

Once allocated, the pulse width can easily be changed.  It may be
possible to change the duty cycle, however often multiple PWM outputs
will share a single timer, so they must share a common duty cycle.

Change-Id: Idc7104578487c01186062bd201cd2a9c7d6d95f8
(cherry picked from commit a4cd22799c290eb11144cf59c29ee1f595416f27)
stm32f40x: hardware pwm driver

Add driver for hardware PWM.  This driver uses timers
1,3,4,8,9,10,11,12,13,14 in the stm32f40x to provide PWM outputs for a
large number of GPIOs.

Each GPIO is mapped to the set of timer channels that can be used to
drive the output.  When creating a PWM object, these channels are
searched for a free channel that is either on an unused timer, or a
timer already configured to the desired duty cycle, as duty cycle is
configured for the entire timer.

The driver is rife with switch case statements used to generalize it for
all of the timers, but the core logic is not too complicated.  The timer
is configured in a simple upcounting mode with the desired duty cycle,
then the output compare units are set up with the desired pulse widths.

Change-Id: If762af0447cab6e329271f08866f2882dd139d55
(cherry picked from commit 961f9a93f4b53a61d15f216c976f8e87edbbbbf1)
shell: add pwm app

Add a simple PWM application, which allows enabling PWM on an arbitrary
GPIO, setting the duty cycle and pulse width.

Currently this completely abandons the instantiated obj, so deleting or
modifying the PWM output is impossible without rebooting.

Change-Id: Ibc09879798757eaf1bf76ebbbe0bb882d998852e
(cherry picked from commit db1ad3dafe0f2b4556881faae7de2c0b1fc85182)