For some reason (unknown to me) platform_s_timer_set_match_int() was clearing
the timer's CR1 and CR2 regs when the interrupts are to be stopped. This
had the effect of stopping the timer completely so a delay() on that timer
would hang forever. Now the timer keeps running and can be used normally
after the interrupts have been stopped.
If the timer has been used to clock ADC or PWM or to generate interrupts
the reload value is unlikely to be all ones. The reload value will be
all ones if the timer has just been used as an elua timer.
So, when the timer wraps use the real reload value which is in ARR rather
than assuming it is 0xFFFF or 0xFFFFFFFF.
Previously, if the specified delay resulted in a final value that
was wider than the timer width, the code would loop forever because the
timer counter would never reach the value of final.
Now, it checks to see if the timer has wrapped and, if so, reduces the value
of final by the timer's max count value.
An added benefit is that now all timers can delay for up to the maximum
delay handled by the target whereas previously the maximum delay was limited
by the width of the counter.
Now, to use the HSI clock, specify an internal clock frequency in the
"clocks" config section, like this...
clocks = { internal = 16000000, cpu = 84000000 }
Don't specify an external frequency as well as the internal frequency.
The board as supplied does not provide any external clock to the F4.
It could supply an 8MHz clock from the STLINK part but, by default, it
isn't configured to do that.
So just use the HSI instead of the HSE - it won't be good for USB or fast
CAN bit rates but should be fine for bit banging, etc.
The Nucleo boards are like the Discovery boards in that they come with an
attached STLINK-V2 programmer. The MCU's UART2 is routed through the
programmer's USB connection and it appears as a VCP device on the host.
So far, this has only been tested to the extent that the elua shell and
lua prompt appear to be functioning as expected.
stm32f4.cpu.read_mcu_device_id() returns a number containing the 32 bit id.
stm32f4.cpu.read_unique_device_id() returns an array of 3 numbers. The first
number contains bits 0-31, the second number contains bits 32-63 and the
last number contains bits 64-95 of the unique device id.
Before, it was possible for the system timer counter to wrap from high to low
after its value had been read but before the value of cmn_systimer_counter
was read and so the resulting sum of those values would be too large.
By reordering the assignments, we can now detect if cmn_systimer_counter has
been advanced while reading the system timer counter value and, if so, repeat
the assignments to ensure consistent values.
wfe() and wfi() just call the underlying ARM functions.
getclksfreq() returns a table containing these clock frequencies: SYSCLK,
HCLK, PCLK1 and PCLK2.
rnd.setup() initialises the random number generator. rnd.read() will call
this anyway if the RNG hasn't been initialised before you read from it. If
rng.read() ever returns nil to signify a problem, you can call rnd.setup()
to re-initialise the RNG.
rnd.read() returns a 32 bit random number or nil if the generator signals
an error.
The values used produce sampling points around 65-70% which is similar
to the original set of values.
Values courtesy of http://www.bittiming.can-wiki.info/
It was being set to ( ( 1LL << 31 ) - 2 ) which only used 31 bits when 32
are available. By setting it to ( ( 1LL << 32 ) - 2 ) the range of the timer
is doubled to around 4295 seconds. Note that time values greater than
approx 2147 seconds will have the top bit (1 << 31) set and so will appear
to be negative as all numbers are considered to be signed.
Setting cmn_systimer_counter to zero when the systimer exceeded
PLATFORM_TIMER_SYS_MAX would cause time to jump backwards if
cmn_systimer_counter was already greater than PLATFORM_TIMER_SYS_MAX.
So now, instead of zeroing it, we subtract PLATFORM_TIMER_SYS_MAX.
This fixes a problem whereby outputting to the USB UART when the host is
connected but the USB UART is not open would cause the interrupt
handler to be called continuously so it would consume 100% of the CPU.
This is copied from the stm32f2 code with some #if's added so that you can
select the MCU pins used for the CAN signals at compile time. Four configurations
are supported.
For example, the board config file can contain this:
macros = { 'ELUA_BOARD_STM32F4_CAN_PIN_CONFIG_2' }
Now, can.send() returns a boolean result to indicate whether the message
was successfully sent or not. The various platform functions differ in how
they handled the situation where all CAN transmitters are occupied. In
particular, the STM32x and STR9 implementations ignored the status returns
from the underlying libraries and so if all the CAN transmitters were busy,
the latest message simply got thrown away. Now, can.send() returns true/false
to indicate if the message really did get queued for transmission. All
platforms should behave the same as before.