"This is a fix to a problem in the handling of the oneshot timer. Due to a wrong assumption concerning the behavior directly after the start of the timer/counter the function sam_oneshot_cancel(…) calculates the wrong remaining time. The code assumes that the counter register is zero directly after the start of the timer, but this is not true. To start the time/counter a software trigger is invoked, this trigger starts the timer/count and sets the counter register to zero, but the reset of the counter register is not performed instantly. According to the datasheet: “The counter can be reset by a trigger. In this case, the counter value passes to zero on the next valid edge of the selected clock.” Thus the counter is set to zero between 0 and USEC_PER_TICK microseconds after the clock was started.
"In my fix I use the freerun count value to determine if at least one tick passed since the start of the timer and thus if the value of the oneshot counter is correct. I also tried to use the function up_timer_gettime(…) to achieve this but, at least if compiled with no optimization the problem vanishes without using the value of the function, the function call takes too long.
"Another problem treated in the fix is that if the oneshot timer/counter is canceled, we only know the remaining time with a precision of USEC_PER_TICK microseconds. This means the calculated remaining time is between 0 and USEC_PER_TICK microseconds too long. To fix this I subtract one tick if the calculated remaining time is greater than one tick and otherwise set the remaining time to zero. By doing so the measured times are much more precise as without it."
"This is a fix to a problem in the handling of the oneshot timer. Due to a wrong assumption concerning the behavior directly after the start of the timer/counter the function sam_oneshot_cancel(…) calculates the wrong remaining time. The code assumes that the counter register is zero directly after the start of the timer, but this is not true. To start the time/counter a software trigger is invoked, this trigger starts the timer/count and sets the counter register to zero, but the reset of the counter register is not performed instantly. According to the datasheet: “The counter can be reset by a trigger. In this case, the counter value passes to zero on the next valid edge of the selected clock.” Thus the counter is set to zero between 0 and USEC_PER_TICK microseconds after the clock was started.
"In my fix I use the freerun count value to determine if at least one tick passed since the start of the timer and thus if the value of the oneshot counter is correct. I also tried to use the function up_timer_gettime(…) to achieve this but, at least if compiled with no optimization the problem vanishes without using the value of the function, the function call takes too long.
"Another problem treated in the fix is that if the oneshot timer/counter is canceled, we only know the remaining time with a precision of USEC_PER_TICK microseconds. This means the calculated remaining time is between 0 and USEC_PER_TICK microseconds too long. To fix this I subtract one tick if the calculated remaining time is greater than one tick and otherwise set the remaining time to zero. By doing so the measured times are much more precise as without it."
In my fix I use the freerun count value to determine if at least one tick passed since the start of the timer and thus if the value of the oneshot counter is correct. I also tried to use the function up_timer_gettime(…) to achieve this but, at least if compiled with no optimization the problem vanishes without using the value of the function, the function call takes too long.
Another problem treated in the fix is that if the oneshot timer/counter is canceled, we only know the remaining time with a precision of USEC_PER_TICK microseconds. This means the calculated remaining time is between 0 and USEC_PER_TICK microseconds too long. To fix this I subtract one tick if the calculated remaining time is greater than one tick and otherwise set the remaining time to zero. By doing so the measured times are much more precise as without it.
This fix removes the disabling of the whole USB peripheral on suspend
interrupt. Its enough to freeze the clock instead.
When disabling the whole peripheral, the next wakeup-interrupt comes
up with an disabled clocking. The unfreeze clock has no effect, because
the master clock is disabled. This makes all registers, including the
IDR unwriteable and the IRQ falls in an endless loop blocking the whole
system.
Furthermore the disabling of the peripheral clock prevents hotplugging
or reconnecting the USB.
sam_i2cbus_initialize
sam_i2cbus_uninitialize
sam_i2cbus_initialize
Or twi_reset is called.
I found this a while back in the stm32 family, so there may be more arch-es with this sort of bug. I suppose any driver that has the notion of "do not set the freq if it is already set" could be suspect.
• SYSIO4: PB4 or TDI Assignment
0: TDI function selected.
1: PB4 function selected.
• SYSIO5: PB5 or TDO/TRACESWO Assignment
0: TDO/TRACESWO function selected.
1: PB5 function selected.
• SYSIO6: PB6 or TMS/SWDIO Assignment
0: TMS/SWDIO function selected.
1: PB6 function selected.
• SYSIO7: PB7 or TCK/SWCLK Assignment
0: TCK/SWCLK function selected.
1: PB7 function selected.
• SYSIO12: PB12 or ERASE Assignment
0: ERASE function selected.
1: PB12 function selected.
The thing I did not add is warning or compilation failure, (to save the next guy the hassle), at ALL the driver points that uses the these pins.
I did remove this
/* To use the USART1 as an USART, the SYSIO Pin4 must be bound to PB4
* instead of TDI
*/
uint32_t sysioreg = getreg32(SAM_MATRIX_CCFG_SYSIO);
sysioreg |= MATRIX_CCFG_SYSIO_SYSIO4;
putreg32(sysioreg, SAM_MATRIX_CCFG_SYSIO);
in sam_lowputc.c in favor of an #error - because the default is an input TDI and driving it blindly to an output TXD1, would be a contention.
use INITS flag to avoid magic reg value to detect power up reset state of rtc
correct a problem clearing interrupt flags (they weren't) which prevented an alarm from ever being used more than once per reset cycle
Error is only triggered if the global variable g_mcan0_msgram is located in RAM at an address beyond 0x20400000 + 0x0000ffff. In this case all send CAN messages have the length zero and the CAN-ID is zero as well.