there return of a read operation that times out with no data received
is inconsistent:
```
Adafruit CircuitPython 7.3.0-beta.1-31-g73f6b4867-dirty on 2022-04-30; Adafruit Feather RP2040 with rp2040
>>>
>>> import board, busio
>>> print(board.UART().read(5))
None
Adafruit CircuitPython 6.3.0 on 2021-06-01; FeatherS2 with ESP32S2
>>> import board,busio
>>> print(board.UART().read(5))
None
Adafruit CircuitPython 7.3.0-beta.1 on 2022-04-07; Adafruit Feather STM32F405 Express with STM32F405RG
>>> import board, busio
>>> print(board.UART().read(5))
None
Adafruit CircuitPython 7.3.0-beta.1-31-g73f6b4867-dirty on 2022-04-28; Teensy 4.1 with IMXRT1062DVJ6A
>>> import board, busio
>>> print(board.UART().read(5))
b''
```
Since I have a PR on this file anyway, I thought I would put in the change to make it consistent
with the other 3 board types I tried. Can not say about any of the others.
.. and enable it on atmel-samd and raspberrypi. On trinket_m0 this saves
96 net bytes of flash. There are 216 bytes actually saved by reducing
the flash storage size of the property descriptors, but added code in
several paths takes back over half of the 'raw savings'.
By organizing the "get-only" and "get-set" (but no delete) properties
each in a different section, we can represent then more efficiently.
Testing performed: that a get-only property can still be gotten but
can't be set or deleted; that a get-set property can sill be gotten or
set but can't be deleted. Tested on pygamer.
Because this requires linker file support, I only enabled it on two of
the ports.
As I mentioned in issue #6310 while investigating that the Teensy port
did not support RS485_dir pin on normal GPIO pins, I found that it
was not implemented either as well on some other ports.
So was curious to implement it for RP2040 using same approach as I did
for the MIMXRT in the Pull Request #6328
That is I setup the specified pin as a normal GPIO pin in output mode
and then when you do a write operation it sets the GPIO pin logically
high, and when the write completes I set it logically low.
Note: knowing when I can set it low can be tricky, as you need to make
sure the full output has completed otherwise the data will be corrupted.
I am using: uart_tx_wait_blocking(self->uart);
Which looks like it is supposed to wait until the busy status is no
longer set, which the Reference manual mentioned, but this is leaving
the line logically set longer than I would like.
however I have tried running it with my hacked up version of the
Python Robotis DynamixelSDK and was able to talk to some AX servos.
I did have to change the library slightly for the RP2040, as the
library was erroring out when you did something like uart.read(5)
and it timed out without receiving anything. The RP2040 returned
None whereas I think the Teensy returned an empty set, which is what
it looks like the PySerial original code expects.
Not sure if anyone is interested in this, but thought i would
put it out as PR and see.
The existing code was setup that allowed you to specify an RTS
pin to be used as an RS485 direction pin, however there are no
RTS pins that are exposed on any of the Teensy 4.x boards.
Instead Arduino code base allowed you to specify any GPIO pin to
work instead. So I added the code in to facilitate this.
In addition the alternative code to wrap your own GPIO pin set high and low
around call(s) to uart.write() will not currently work, unless maybe you
fudge it and add your own delays as the write will return after the last
byte was pushed onto the UART’s hardware FIFO queue and as such if you
then immediately set the IO pin low, it will corrupt your output stream.
The code I added detects that you are setup to use the RS485 pin and
before it returns will wait for the UART’s Transfer complete status flag
to be set.
Now a 'once' and a 'loop' buffer can be specified.
'once' is useful for things like writing a neopixel strip in the background,
if you can guarantee the buffer contents are stable until the write is complete.
'loop' is useful for periodic things, like pwm & servos.
both together are useful for some special cases of pwm/servo, where a
transitional waveform needs to be played for one repetition and then
a new waveform needs to be played after that.
The API is renamed to reflect that it's a more generic 'background'
operation.
There were two main issues with the PWM support.
The first is they would fail to work properly if the board goes
into low power mode, when you do things like: time.sleep(0.25)
Can make partially work with this by turning on the proper flags
in each of the FlexPWMTimer Timers/sub-timers, but this did not
appear to work if for example you have both A and B channels
enabled.
Second main problem is that the code did not work with the X
channel of each timer/sub-timer. It looks like someone had
earlier started support for this, But was not sufficient.
Needed to bypass the SDK code and get it closer to the PJRC code.
That is we set the PWM_CTRL_FULL_MASK, which then uses base->SM[submodule].VAL1 to control
when the timer is reset, so it sets up your cycle/frequency. But then this implies that X channel
which uses 0, 1 has to be handled specially. So for the different channels:
A - Uses VAL2 to turn on (0) and VAL3=duty to turn off
B - Uses VAL4 to turn on (0) and VAL5 to turn off
X - As mentioned above VAL1 turns off, but its set to the timing for freqency. so
VAL0 turns on, so we set it to VAL1 - duty
Renamed the board both name of directory within boards, but also the
name reported board name: board_id -- sparkfun_teensy_micromod
Adafruit CircuitPython 7.3.0-beta.0-10-g2a3eb49da-dirty on 2022-04-10; SparkFun Teensy MicroMod Processor with IMXRT1062DVL6A
While testing out this and the new MicroMod Teensy port, @mjs513
and myself found it desirable to have logical pin names for the
different Serial UART objects. It is a lot easier and clearer
to use and maintain to do something
like: uart4 = busio.UART(board.TX4, board.RX4)
than have to go look up the pin numbers for each board.
I fixed a couple issues in the pin name definitions.
The pin names are sort of Teensy centric in that the priority is given
to the pin names you would use in Arduino like D0, D1, ...
But also added names for the MicroMod names in particular the names
on the front of the ATP carrier board
Also updated manufacturer to be both PJRC and Sparkfun
As mentioned in issue #6241 the commit to setup port hooks is now
causing all input/output that are to go to the Mu window to also
go to the LpUart that is defined the port serial.c
and in this case it goes to lpuart4, which on Teensy 4, 4.1 is
used on Arduino Serial2. With this new code this port no longer
works properly.
This is one way to solve it, in that there is a #if defined() that
if not set, all of the code in this file is ignored and the higher
level supervisor stub versions of these functions will be used, which
don't interfere with Serial2 and my test sketch works again.
Note: the PR for Switch to Port Serial Hooks, also changed code in
other ports. I have not tried to see how.
There are other more global fixes for this, in which maybe a higer
level #if that disables the code within the top level supervisor. Or
could be software controlled
Again this may not be the final solution, but at least it gets
Serial2 up and running agin.
I instrumented RTC_Handler and determined that on SAMD51 it was possible
for the interrupt to be delivered well before the actual overflow of the
RTC COUNT register (e.g., a value as small as 0xffff_fffd could be seen
at the time of overflow)
Rather than depending on the overflow interrupt coming in at the same time
as COUNT overflows (exactly), rely only on observed values of COUNT in
_get_count, overflowing when it wraps around from a high value to a low
one.
With this change, PLUS a second change so that it is possible to warp
the RTC counter close to an overflow and test in 20ms instead of 3 days,
there was no problem detected over 20000+ overflows. Before, a substantial
fraction (much greater than 10%) of overflows failed.
Fixes#5985
Change to common-hal/rtc/RTC.c for time warping (plus make rtc_old_count non-static):
```patch
void common_hal_rtc_set_calibration(int calibration) {
+
+ common_hal_mcu_disable_interrupts();
+
+ RTC->MODE0.COUNT.reg = 0xffffff00;
+ rtc_old_count = 0;
+ do {
+ while ((RTC->MODE0.SYNCBUSY.reg & (RTC_MODE0_SYNCBUSY_COUNTSYNC | RTC_MODE0_SYNCBUSY_COUNT)) != 0) { }
+ }
+ while(RTC->MODE0.COUNT.reg < 0xffffff00);
+ common_hal_mcu_enable_interrupts();
+
+ mp_printf(&mp_plat_print, "Warping RTC in calibration setter count=%08x rtc_old_count=%08x\n", RTC->MODE0.COUNT.reg, rtc_old_count);
```
Test program:
```python
import time
from rtc import RTC
i = 0
while True:
RTC().calibration = 1 # Warps to ~16ms before overflow, with patch to RTC code
t0 = time.monotonic_ns()
et = t0 + 20_000_000 # 20ms
while (t1 := time.monotonic_ns()) < et: pass
i += 1
print(f"{i:6d}: duration {t1-t0}")
if t1-t0 > 200_000_000: break
print()
```
To me, it made more sense to track which boards go together in a cluster;
when reviewing a request to actually use a duplicate vid/pid, you want
to know what board(s) it is aliasing.
I also revamped the detection of non-USB boards so that a board .mk file
that couldn't be parsed by the code here would raise a problem instead
of just being skipped for the purposes of checking.
There were some lines with comments on the end, and some variation in
capitalization of the IDs. These are all normalized and a (sometimes
unfriendly!) error printed when it's incorrect.
Before this, here were some ways to trick the duplicate vid/pid checker:
```
USB_PID = 0XABCD
USB_PID = 0xAbCd
USB_PID = 0xABCD # harmless comment?
```
None of these things were ever done on purpose.
This board has both types of USB connectors, a display and buttons
to select items on the display. It also has a micro-B connector for
the UART output.
Removes:
* AUTORESET_DELAY_MS which never did anything but was introduced
somehow.
* CIRCUITPY_BOOT_BUTTON in all but one ESP board because they all have
them. There is a default based on the strapping pins.
* BOARD_USER_SAFE_MODE_ACTION because it was all the same for boards
with boot buttons. Now the safe mode code manages the message.
This unifies the delay into the post-run delay that also waits
for user input and fake sleep. This ensures we always delay.
Previous code would only delay if the code.py was running when
autoreload was triggered. Now it will always delay.
We also now suspend autoreload when a USB write starts and then
resume on completion. This should prevent reloading in between
sectors of a single write.
- Add reset for autoreload. De-request ticks.
- Separate state a little more in autoreload.c
- Rename some routines.
- Remove redundant settings of CIRCUITPY_AUTORELOAD_DELAY_MS.
This allows you to list and explore connected USB devices. It
only stubs out the methods to communicate to endpoints. That will
come in a follow up once TinyUSB has it. (It's in progress.)
Related to #5986