Change TIMER_MIN_TRY_TICKS from 2us to 90 instructions.
On newer chips 2us is a large amount of time - for example on the
520Mhz stm32h723 it would be 1040 instructions. Using a large time
can result in "busy waiting" in the irq handler when the cpu may be
better spent running tasks.
The armcm_timer.c code is used on most ARM cortex-M chips and on all
of these chips the SysTick timer should be tied directly to the
instruction counter. This change should be safe because it should not
take more than 90 instructions to reschedule the timer on any of these
chips. Also, all of these chips should be able to exit the irq
handler and reenter it in less than 90 instructions allowing more time
for tasks to run if the next timer is more than 90 timer ticks in the
future.
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
The TIMER_IDLE_REPEAT_TICKS was intended to reduce the number of cases
where timers would defer to tasks when tasks are mostly idle.
However, with commit ea546c78 this became less important because
timers now only defer to tasks if tasks are consistently busy for two
consecutive calls to sched_check_set_tasks_busy().
The TIMER_IDLE_REPEAT_TICKS mechanism could result in extended task
delays if timers do become busy. Timers can become busy in normal
operation if timers are scheduled to run more than 500,000 times a
second (every 2us or faster). This can occur on stepper movement when
using high microstep settings. If timers become busy, it could take
up to 1ms for tasks to next be given an opportunity to run (two calls
to sched_check_set_tasks_busy() at 500us per call). This wouldn't
typically be an issue if tasks are also busy, but in some loads tasks
may need to run periodically in such a way that the task status
alternates between idle and busy. In this case, the
TIMER_IDLE_REPEAT_TICKS mechanism could effectively limit the number
of task wakeups to only ~1000 per second.
The "USB to canbus bridge" code uses tasks to transfer data to/from
USB and canbus. If timers become busy, the limiting of task wakeups
could lead to a situation where the effective bandwidth becomes
severely constrained. In particular, this can be an issue on USB
implementations that do not support "double buffering" (such as the
stm32 usbotg code). There are reports of "Timer too close" errors on
"USB to canbus bridge" mode as a result of this issue.
Fix by removing the TIMER_IDLE_REPEAT_TICKS check. Check for busy
tasks every TIMER_REPEAT_TICKS instead (100us).
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
The Linux kernel reports a canbus message as transmitted when it gets
the echo frame back. Processing the message prior to sending the echo
frame can lead to odd looking debugging logs (as the response messages
may appear to predate the request messages). This doesn't impact the
Klipper code, but it does make analyzing logs harder. Fix by sending
the echo frame prior to processing the frame.
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
Don't limit the canbus_notify_tx() wakeup to cases where notify_local
is set - perform the wakeup whenever the host_status field indicates
the main task has work pending.
This fixes a small race condition where the main task could block
sending a usb echo frame, and the canbus_send() code gets called as
the usb bandwidth becomes available but before a usb wakeup
notification is sent. In that situation, the usb code may not issue a
wake event and the echo frames may be delayed.
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
It seems the Linux kernel will consider a maximum size usb packet to
be a transaction that will continue into the next usb packet. It will
thus hold on to the traffic from the first packet until it gets the
next packet. However, if the mcu has no further data to send after
the first packet then the data could get delayed for an extended
period of time.
To avoid this, check for transmissions that could end on a maximum
sized packet and send that data in two packets instead. This avoids
this unusual corner case.
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
Move the definition of the usb endpoint sizes from usb_cdc.h to
usb_cdc_ep.h . This allows individual boards to override the default
endpoint sizes.
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
If the low-level canbus stops working then it could become impossible
to send messages to and from the canbus bridge node itself. This can
make it difficult to diagnose canbus problems.
Change the canbus bridge code to detect if message transmits become
stalled for 50+ milliseconds and go into a "discarding" state. In
this discarding state, messages destined for the canbus will be
discarded until the canbus becomes active again. In this discarding
state it will therefore be possible to transmit messages to and from
the canbus bridge node.
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
Add support for a new get_canbus_status command to canserial.c .
Add new canbus_stats.py module that will periodically query canbus
mcus for connection status information.
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
Rename sched_tasks_busy() to sched_check_set_tasks_busy() and change
it to only return true if tasks are active (running or requested) for
two consecutive calls. This makes it less likely that timers will
yield to tasks except when tasks really are notably backlogged.
This also makes it less likely that multiple steppers controlling the
same rail will be interrupted by tasks mid-step. This should slightly
improve the timing, and make it less likely that a halt during
homing/probing will occur with these steppers taking a different
number of total steps.
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
It seems recent arm gcc versions no longer build correctly using the
"--specs=nano.specs --specs=nosys.specs" linker flags. Replace those
linker flags with "-nostdlib -lgcc -lc_nano".
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
Avoid calling memset() and memcpy() prior to copying the ram and
clearing the bss. Also, place both ResetHandler() and
reset_handler_stage_two() in an explicit ".text.armcm_boot" linker
section. These changes make it easier to support targets that want to
run all code in ram.
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
Prioritize sending responses back to the host over transmitting new
messages from the host. Otherwise, the gs_usb host usb
acknowledgments could saturate the usb bandwidth for extended periods.
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
Read USB messages arriving from the host into a queue. This makes it
less likely that USB "bulk out" packets will be NAK'ed on the USB bus,
which improves USB bus utilization.
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
There is no need to heavily prioritize the sending of canbus packets
over USB. A single check to flush the incoming canbus packets is
sufficient.
Also, be sure to wake up canserial_notify_tx() even if canhw_send()
blocks.
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
The canserial code already advertizes a receive window, so the host
should never flood the canserial code. Remove the extra scheduling
checks to simplify the usb_canbus code.
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
A buffer of only 8 canbus packets is only 64 bytes of data, which
could be exceeded if the usb-to-canbus mcu gets busy doing other work.
Increase the buffer to 32 packets.
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
Check for the build symbol prior to calling bootloader_request().
Enable the build symbol on rp2040, atsam, and atsamd chips.
This also enables serial bootloader requsts on rp2040, atsam, and
atsamd.
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
Rename the build symbol. This is in preparation for enabling
HAVE_BOOTLOADER_REQUEST on usb and canbus.
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
Rename canserial_send() to canbus_send() and canserial_set_filter() to
canbus_set_filter(). This makes it more clear where the code should
reside.
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
Rename canbus_send() to canhw_send() and rename canbus_set_filter() to
canhw_set_filter(). This makes it more clear where the code should
reside.
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
Specify the arm architecture flash bootup address for each chip type
in Kconfig using a new FLASH_BOOT_ADDRESS setting.
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
An mcu device acting as an "mcu bridge" should only be reset after
other normal devices are reset - otherwise the bridge wont be able to
pass along the reset message to the downstream mcus.
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
Use bootloader_request() instead of try_request_canboot(). This
allows the bootloader machanism to work for more bootloaders.
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
Rename this board API function to a more generic name. This is in
preparation for calling the function from the canbus code.
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
Support a USB interface that shows up as a canbus adapter to linux.
Route both local and real canbus packets over that interface.
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
Rename the canbus.c code to canserial.c and introduce new wrapper
functions in canbus.c that connect the low-level canbus hardware code
to the high-level canserial.c code.
This is in preparation for adding "usb to canbus bridge mode".
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
Move the uuid hash calculation to canbus.c and call canbus_set_uuid()
from src/stm32/chipid.c . This simplifies the low-level canbus
hardware code.
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
Previously the code had canbus_read() which was called from task
context (for admin messages), and canbus_process_data() which was
called from irq context (used for data messages). Change that to a
single canbus_process_data() function that is called from irq context
(used for all messages). This simplifies the low-level hardware
specific canbus code and should make it easier to support other
hardware implementations.
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
Create a single CanData global variable to track the canbus state.
ARM micro-controllers generally produce better code when global
variables are in a struct.
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
When CanBoot is detected set its bypass signature when a
reset is requested.
Add a "try_request_canboot()" method that may be called
from from USB and Canbus bootloader requests.
Signed-off-by: Eric Callahan <arksine.code@gmail.com>