Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Zigbee coordinator firmware with RTS / CTS Hardware Flow Control enabled compatible with Sonoff Zigbee 3.0 USB Dongle Plus adapter by ITead #324

Closed
Hedda opened this issue Nov 2, 2021 · 85 comments
Labels

Comments

@Hedda
Copy link
Contributor

Hedda commented Nov 2, 2021

Request Z-Stack 3.x.0 Zigbee coordinator firmware with RTS / CTS Hardware Flow Control enabled and compatible with the new Sonoff Zigbee 3.0 USB Dongle Plus adapter by ITead which hardware support Hardware Flow Control when enabled via dip-switch:

https://sonoff.tech/wp-content/uploads/2021/09/Zigbee-3.0-USB-dongle-plus-firmware-flashing-1-1.docx

(Guide above linked from https://sonoff.tech/product-review/zigbee-3-0-usb-dongle-plus/ written by ITead).

2. Enable hardware flow control and generate firmware (optional) section says "2.1 Import the ZNP project of CC1352P into CCS. Open the .syscfg configuration file in the ZNP project. Enable serial flow control in the UART option in the .syscfg configuration file."

Configuration in the image from that document looks like tick the box for "Flow Control" under "UART" and use configuration:

UART Peripheral = Any(UART0)
TX Pin = DIO13/4 (XDS110 UART)
RC Pin = DIO12/3 (XDS110 UART)
CTS Pin = DIO19/19 (Header)
RTS Pin = DIO18/36 (Header)

image

This request was initially brought up as a wish in #316 but since that issue specifically regarding Zigbee router firmware and nor Zigbee coordinator firmware I thought that I would post a seperate issue as a request for Zigbee coordinator firmware for this.

Would you be willing to compile and host firmware images that support using hardware flow control with this specific dongle?

I understand switching to hardware flow control mode on the new Sonoff Zigbee 3.0 USB Dongle Plus adapter by ITead is done manually via the physical dip-switch on the adapters board but also understand that we need a custom firmware built for it too(?).

Picture from https://itead.cc/product/sonoff-zigbee-3-0-usb-dongle-plus/ show an "DIP switch for hardware flow control":

image

So would need custom coordinator firmware before enabling hardware flow control in the software application like Zigbee2MQTT:

https://www.zigbee2mqtt.io/information/configuration.html

# Optional: RTS / CTS Hardware Flow Control for serial port (default: false)
rtscts: true

Hardware flow control should in theory make for more stable serial communication since the flow control is off-loaded from the application and the system CPU to the MCU, but not sure if it will really be more stable in the real world for Zigbee2MQTT.

PS: Know I read that openHAB's Zigbee developer recommended hardware flow control for commercial use for added stability, however then we are talking about Zigbee Coordinators and Zigbee devices, not about dedicated stand-alone Zigbee routers.

@Koenkk
Copy link
Owner

Koenkk commented Nov 2, 2021

I prefer not to provide additional firmwares since it leads to more confusion for users and more maintenance for me unless it provides a significant improvement.

@Hedda
Copy link
Contributor Author

Hedda commented Nov 2, 2021

Would configuring it in firmware actually break functionality if the same firmware was flashed to another adapter without physical hardware flow control pins connected if the optional hardware flow control setting is not enabled in the application?

That is, if a user flash such firmware with Flow Control activated as per ITead's instructions to for example Tube's CC2652P2 USB Coordinator (based on RFSTAR RF-BM-2652P2) but do not enable it Zigbee2MQTT would that then not connect via SW serial?

https://www.zigbee2mqtt.io/information/configuration.html

# Optional: RTS / CTS Hardware Flow Control for serial port (default: false)
rtscts: false

@Koenkk
Copy link
Owner

Koenkk commented Nov 2, 2021

Not sure, can you investigate this?

@Hedda
Copy link
Contributor Author

Hedda commented Nov 2, 2021

Maybe, if you could provide compiled coordinator firmware with flow control activated so we can test it on different dongles?

If we get a test FW image of such firmware then I can at least ask for help from the communities that requested this feature.

Perhaps it could at first be tested on just the Sonoff Plus dongle which if it works should work with the DIP-switch in both positions as long as we set the correct Flow Control configuration in Zigbee2MQTT (and other applications) that matches.

Only other CC2652 dongle I currently own is a zzh (CC2652R) that is in "production" at home so will not test on it myself now.

@tteck
Copy link

tteck commented Nov 2, 2021

if you could provide compiled coordinator firmware with flow control activated so we can test it on different dongles?

I'd also be willing to test.

@Hedda
Copy link
Contributor Author

Hedda commented Nov 16, 2021

@guozi7788 As this issue and questions are related to your comments about pins for Hardware Flow Control in this PR -> #329

Do you happen to have some connections that you could report this request for firmware to relevant personnel at ITead/Sonoff?

The community would like a pre-compiled firmware image with Hardware Flow Control enabled to test on the SONOFF Zigbee 3.0 USB Dongle Plus by ITead. If someone at ITead/Sonoff or the engineering company it uses could please compile provide such a pre-compiled firmware image then we would get willing testers from the community to test it and report their results.

PS: Tip is that experimental firmware images could be provided by on a GitHub repo similar to the other Sonoff Zigbee 3.0 dongle:

https://github.com/xsp1989/zigbeeFirmware/

@Hedda
Copy link
Contributor Author

Hedda commented Nov 19, 2021

FYI, submitted the question via e-mail to ITead and got a reply email from ITead's project manager for the Sonoff Zigbee 3.0 USB Dongle Plus who unfortunately said that ITead has no plans on maintaining and distributing their own "ITead official" firmware images that supports hardware flow control on it, and continued to say that they currently only plan to provide tutorials on how any user in the community themselves can set up and generate the appropriate tools for building and compiling firmware as needed, meaning that they rely on the community to compile our custom firmware if we want it, (i.e. use community firmware builds like https://github.com/Koenkk/Z-Stack-firmware/tree/master/coordinator/Z-Stack_3.x.0 ).

Again, ITead/Sonoff engineer guozi7788 did however at least confirm in #329 which pins should be mapped when building it:

I have added the information you expect to know in this PR:
BSL Trigger Pin: DIO15
Auto-BSL: yes
LED: DIO_7(Not welded) Power LED(Red)
Hardware Flow Control: DIO13: TX DIO12: RC DIO19: CTS(Need DIP-switch ON) DIO18: RTS(Need DIP-switch ON)

@Merwenus
Copy link

Great, this is the second Zigbee router I bought for them and they suck in different ways, excellent and they just don't care.

@Hedda
Copy link
Contributor Author

Hedda commented Dec 1, 2021

Great, this is the second Zigbee router I bought for them and they suck in different ways, excellent and they just don't care.

Know that there is no point in using Hardware Flow Control firmware if used as a Zigbee router as Zigbee routers are not relying on any serial communication on a host while in operation. Zigbee router just needs power to work.

Hardware Flow Control firmware is only of interest for a Zigbee Coordinator to off-load flow control from CPU to MCU in a setup in a non-dedicated system where you might be running a lot of other stuff on the main System CPU, (like maybe on a Qnap or Synology NAS with a virtual machine than run Linux which in turn also runs other applications than Zigbee2MQTT). It should also be noted that at least so far Software Flow Control firmware has been proven to be stable in practically all real-world scenarios.

@dkwireless
Copy link

Do we have benefits on CC2652P side with HW flow control? If yes then we should pursuit this, if no, I think there is no need...

@Hedda
Copy link
Contributor Author

Hedda commented Dec 3, 2021

Do we have benefits on CC2652P side with HW flow control? If yes then we should pursuit this, if no, I think there is no need...

My guess is that we will not know the benefits of Hardware Flow Control over Software Flow Control without long term testing. That is, make different stress-test comparisons where Hardware Flow Control versus Software Flow Control is put to their limits.

At least on paper Hardware Flow Control should theoretically create a more robust and solid connection, even if used when the system CPU and/or operating system is under very heavy load, which is when a Software Flow Control is more likely to temporarily lag/delays or even drop the connection that can cause missed messages. So if you hypothetically simply want the best theoretical connection that should be possible then Hardware Flow Control is the best, on paper.

Software Flow Control for Zigbee Coordinator adapters/controllers might perhaps make stable enough in a majority or even all of the real-world daily scenarios for home automation usage in private residents, but I understand that Hardware Flow Control is the norm standard for Zigbee in real-world commercial use such as industry, medical (hospitals and hospice or home care), utility companies (e.g. "Smart Energy" meters for electricity, gas, heating, and water utility metering), as well when targeting IoT within commercial buildings (for example lightning and HVAC heating or cooling).

Note that we know that unstable serial connection can cause issues for Z-Stack, which is why Wi-Fi based remote adapters are not recommended. See -> https://www.zigbee2mqtt.io/guide/adapters/#notes

Network adapters connected via WiFi might have reduced stability as the serial protocol does not have enough fault tolerance to handle packet loss or latency delays that can normally occur over WiFi connections. If cannot use a locally connected USB or UART/GPIO adapter then the recommendation is to use a remote adapter that is connected via Ethernet (wired) to avoid issues.

So based on issues we can see over WiFi we can assume that the Z-Stack ZNP interface protocol is currently not designed with robustness enough to deal with a lot of lag/delays and temporarily dropped connections. Instead, it is designed to work with a direct connected Zigbee serial adapter. You can read more about the concept of in robustness computer science https://en.wikipedia.org/wiki/Robustness_(computer_science)

PS: Disclaimer is that I am a bit biased as find it a little hard to be subjective on this topic as professionally I worked as a server infrastructure engineer for over 20-years and there having redundancy and utilizing robust hardware components/systems for high-availability (as well as having backup systems for safe fail-overs) is one of the essential keys to achieving maximum uptime as few unplanned downtimes as possible. Otherwise, all of the robustness must be achieved by application developers by running several instances of all applications and their dependencies in high availability, which is something that usually costs more and is harder to justify the overhead for.

@verjus
Copy link

verjus commented Dec 6, 2021

I was able to enable hardware flow control in Koenkk's firmware by making the following modifications to two files, after following the instructions provided here.

The two files are: ti_drivers_config.c and ti_drivers_config.h. They reside in the syscfg directory, after applying Koenk's patch.

Here is a diff for each file:

diff ti_drivers_config.h ~/syscfg.or/ti_drivers_config.h 
97,104d96
<   /* Owned by CONFIG_DISPLAY_UART as  */
< extern const uint_least8_t CONFIG_GPIO_3_CONST;
< #define CONFIG_GPIO_3 19
< 
< /* Owned by CONFIG_DISPLAY_UART as  */
< extern const uint_least8_t CONFIG_GPIO_4_CONST;
< #define CONFIG_GPIO_4 18
< 
225,226d216
<  *  CTS: DIO19
<  *  RTS: DIO18

and

diff ti_drivers_config.h ~/syscfg.or/ti_drivers_config.h 
97,104d96
<   /* Owned by CONFIG_DISPLAY_UART as  */
< extern const uint_least8_t CONFIG_GPIO_3_CONST;
< #define CONFIG_GPIO_3 19
< 
< /* Owned by CONFIG_DISPLAY_UART as  */
< extern const uint_least8_t CONFIG_GPIO_4_CONST;
< #define CONFIG_GPIO_4 18
< 
225,226d216
<  *  CTS: DIO19
<  *  RTS: DIO18
PCAXS::syscfg>diff ti_drivers_config.c ~/syscfg.or/ti_drivers_config.c
269,272c269,270
<     /* Owned by CONFIG_DISPLAY_UART as RTS */
<     GPIO_CFG_OUTPUT_INTERNAL | GPIO_CFG_OUT_STR_MED | GPIO_CFG_OUT_LOW, /* CONFIG_GPIO_4 */
<     /* Owned by CONFIG_DISPLAY_UART as CTS */
<     GPIO_CFG_INPUT_INTERNAL | GPIO_CFG_IN_INT_NONE | GPIO_CFG_PULL_DOWN_INTERNAL, /* CONFIG_GPIO_3 */
---
>     GPIO_CFG_NO_DIR, /* DIO_18 */
>     GPIO_CFG_NO_DIR, /* DIO_19 */
307,308d304
< const uint_least8_t CONFIG_GPIO_3_CONST = CONFIG_GPIO_3;
< const uint_least8_t CONFIG_GPIO_4_CONST = CONFIG_GPIO_4;
813,814c809,810
<     .ctsPin             = CONFIG_GPIO_3,
<     .rtsPin             = CONFIG_GPIO_4,
---
>     .ctsPin             = GPIO_INVALID_INDEX,
>     .rtsPin             = GPIO_INVALID_INDEX,

The relevant sections of each file should look like this for ti_drivers_config.c

void* gpioUserArgs[31];

const uint_least8_t CONFIG_GPIO_1_CONST = CONFIG_GPIO_1;
const uint_least8_t CONFIG_GPIO_2_CONST = CONFIG_GPIO_2;
const uint_least8_t CONFIG_GPIO_3_CONST = CONFIG_GPIO_3;
const uint_least8_t CONFIG_GPIO_4_CONST = CONFIG_GPIO_4;
const uint_least8_t CONFIG_RF_24GHZ_CONST = CONFIG_RF_24GHZ;

this

    GPIO_CFG_NO_DIR, /* DIO_16 */
    GPIO_CFG_NO_DIR, /* DIO_17 */
    /* Owned by CONFIG_DISPLAY_UART as RTS */
    GPIO_CFG_OUTPUT_INTERNAL | GPIO_CFG_OUT_STR_MED | GPIO_CFG_OUT_LOW, /* CONFIG_GPIO_4 */
    /* Owned by CONFIG_DISPLAY_UART as CTS */
    GPIO_CFG_INPUT_INTERNAL | GPIO_CFG_IN_INT_NONE | GPIO_CFG_PULL_DOWN_INTERNAL, /* CONFIG_GPIO_3 */
    /* Owned by CONFIG_NVS_SPI_0 as Button GPIO */
    GPIO_CFG_OUTPUT_INTERNAL | GPIO_CFG_OUT_STR_MED | GPIO_CFG_OUT_HIGH, /* CONFIG_GPIO_0 */
    GPIO_CFG_NO_DIR, /* DIO_21 */
    GPIO_CFG_NO_DIR, /* DIO_22 */
    GPIO_CFG_NO_DIR, /* DIO_23 */
    GPIO_CFG_NO_DIR, /* DIO_24 */

and this

static const UARTCC26XX_HWAttrsV2 uartCC26XXHWAttrs[CONFIG_UART_COUNT] = {
  {
    .baseAddr           = UART0_BASE,
    .intNum             = INT_UART0_COMB,
    .intPriority        = (~0),
    .swiPriority        = 0,
    .powerMngrId        = PowerCC26XX_PERIPH_UART0,
    .ringBufPtr         = uartCC26XXRingBuffer0,
    .ringBufSize        = sizeof(uartCC26XXRingBuffer0),
    .rxPin              = CONFIG_GPIO_2,
    .txPin              = CONFIG_GPIO_1,
    .ctsPin             = CONFIG_GPIO_3,
    .rtsPin             = CONFIG_GPIO_4,
    .txIntFifoThr       = UARTCC26XX_FIFO_THRESHOLD_1_8,
    .rxIntFifoThr       = UARTCC26XX_FIFO_THRESHOLD_4_8,
    .errorFxn           = NULL
  },
};

and for ti_drivers_config.h

/*
 *  ======== GPIO ========
 */
/* Owned by CONFIG_DISPLAY_UART as  */
extern const uint_least8_t CONFIG_GPIO_1_CONST;
#define CONFIG_GPIO_1 13

/* Owned by CONFIG_DISPLAY_UART as  */
extern const uint_least8_t CONFIG_GPIO_2_CONST;
#define CONFIG_GPIO_2 12

  /* Owned by CONFIG_DISPLAY_UART as  */
extern const uint_least8_t CONFIG_GPIO_3_CONST;
#define CONFIG_GPIO_3 19

/* Owned by CONFIG_DISPLAY_UART as  */
extern const uint_least8_t CONFIG_GPIO_4_CONST;
#define CONFIG_GPIO_4 18

/* Owned by /ti/drivers/RF as  */
extern const uint_least8_t CONFIG_RF_24GHZ_CONST;
// #define CONFIG_RF_24GHZ 28

Then rebuild the firmware.

I tested that it works with the latest dev z2m, with rtscts enabled in the configuration file:

advanced:
  # Optional: Baud rate speed for serial port, this can be anything firmware support but default is 115200 for Z-Stack and EZSP,
  # 38400 for Deconz, however note that some EZSP firmware need 57600.
  #baudrate: 115200
  # Optional: RTS / CTS Hardware Flow Control for serial port (default: false)
  rtscts: true

and of course, the with hardware switch activated. I haven't tested the firmware itself but z2m communicates with the stick.

Hope this is useful to someone. Disclaimer, I haven't tested the firmware's performance or even its ability to pair. I just checked that the firmware allows for the serial port to be open:

Zigbee2MQTT:debug 2021-12-05 20:44:29: Using zigbee-herdsman with settings: '{"adapter":{"concurrent":null,"delay":null,"disableLED":false},"backupPath":"/opt/zigbee2mqtt/data/coordinator_backup.json","databaseBackupPath":"/opt/zigbee2mqtt/data/database.db.backup","databasePath":"/opt/zigbee2mqtt/data/database.db","network":{"channelList":[11],"extendedPanID":[221,221,221,221,221,221,221,221],"networkKey":"HIDDEN","panID":6754},"serialPort":{"path":"/dev/ttyUSB0","rtscts":true}}'
  zigbee-herdsman:controller:log Starting with options '{"network":{"networkKeyDistribute":false,"networkKey":[redacted],"panID":6754,"extendedPanID":[221,221,221,221,221,221,221,221],"channelList":[11]},"serialPort":{"rtscts":true,"path":"/dev/ttyUSB0"},"databasePath":"/opt/zigbee2mqtt/data/database.db","databaseBackupPath":"/opt/zigbee2mqtt/data/database.db.backup","backupPath":"/opt/zigbee2mqtt/data/coordinator_backup.json","adapter":{"disableLED":false,"concurrent":null,"delay":null}}' +0ms
  zigbee-herdsman:adapter:zStack:znp:log Opening SerialPort with /dev/ttyUSB0 and {"baudRate":115200,"rtscts":true,"autoOpen":false} +0ms
  zigbee-herdsman:adapter:zStack:znp:log Serialport opened +6ms
  zigbee-herdsman:adapter:zStack:znp:SREQ --> SYS - ping - {"capabilities":1} +0ms

@tteck
Copy link

tteck commented Dec 6, 2021

@verjus are you gonna share the firmware for testing?

@Hedda
Copy link
Contributor Author

Hedda commented Dec 6, 2021

@verjus Can you also test if Hardware Flow Control firmware work in ZHA too? -> https://www.home-assistant.io/integrations/zha (alternatively you could test with zigpy-znp https://github.com/zigpy/zigpy-znp or zigpy-cli https://github.com/zigpy/zigpy-cli ).

@verjus Can you in addition as well test if Zigbee2MQTT (and ZHA) can still communicate with the stick when hardware switch is deactivated and default config (rtscts: false)?

As brought up previous above, it would be very interesting to know if firmware compiled with Hardware Flow Control support can also be used with via Software Flow Control when not switching over the switch on the Sonoff Plus dongle.

If that is possible then should be no need to release separate firmware for Hardware Flow Control and Software Flow Control.

Would configuring it in firmware actually break functionality if the same firmware was flashed to another adapter without physical hardware flow control pins connected if the optional hardware flow control setting is not enabled in the application?

That is, if a user flash such firmware with Flow Control activated as per ITead's instructions to for example Tube's CC2652P2 USB Coordinator (based on RFSTAR RF-BM-2652P2) but do not enable it Zigbee2MQTT would that then not connect via SW serial?

https://www.zigbee2mqtt.io/information/configuration.html

# Optional: RTS / CTS Hardware Flow Control for serial port (default: false)
rtscts: false

@verjus
Copy link

verjus commented Dec 7, 2021

@Hedda, I did not have time to test extensively but from what I was able to determine, the firmware appears to require the the hardware switch be enabled and that the configuration be set to rtscts: true in order to work.

@tteck I was nervous about sharing the firmware because I did not have time to test it, but if you are willing to take a chance, I've posted it here. I was able to pair and use an EcoSmart 4 button switch that worked fine. Also note that the firmware is based on simplelink_cc13xx_cc26xx_sdk_5_30_01_01, which is more recent that the one used by Koenkk, so I had to make some adjustments to his patches.

If the firmware works, hopefully Koenkk will be able to incorporate the changes in the version he maintains. It would be great if a single firmware worked for both software and hardware flow control, but it doesn't seem to be the case. Maybe he or someone else kind find a way to make it happen.

@tteck
Copy link

tteck commented Dec 7, 2021

Thanks, Koenkk actually has firmware out based on SimpleLink SDK 5.30.00.56

@Koenkk
Copy link
Owner

Koenkk commented Dec 7, 2021

Didn't know there was a new SDK, will update soon.

@Koenkk
Copy link
Owner

Koenkk commented Dec 7, 2021

Done: https://github.com/Koenkk/Z-Stack-firmware/tree/develop/coordinator/Z-Stack_3.x.0/bin

@qosmio
Copy link

qosmio commented Dec 10, 2021

@verjus
I was not able to get it working using the following in my config. Had to remove the rtscts: true value for it to come up.

Firmware version is showing as 20211114, so I know I definitely flashed it correctly.

advanced:
    rtscts: true

PS For those on Raspberry/RPi, kernel version 5.10 has a bug when setting rtscts that seems to flood console with:

Dec 10 00:33:49 rpi4-1 kernel: [  481.403392] cp210x ttyUSB2: failed set request 0x7 status: -32
Dec 10 00:33:49 rpi4-1 kernel: [  481.560288] cp210x ttyUSB2: failed set request 0x7 status: -32
Dec 10 00:33:49 rpi4-1 kernel: [  481.715677] cp210x ttyUSB2: failed set request 0x7 status: -32
Dec 10 00:34:38 rpi4-1 kernel: [  530.079617] cp210x ttyUSB2: failed set request 0x7 status: -32

I updated to release branch next of the kernel with rpi-update
UPDATE_SELF=1 SKIP_WARNING=1 BRANCH=next WANT_PI4=1 RPI_UPDATE_UNSUPPORTED=0 RPI_REBOOT=1 rpi-update

Below is the debug output of Z2M

[12/10/21 01:08:00]
hass@rpi4-1 ~/z2m 55s
➤ DEBUG=* npm start

> [email protected] start
> node index.js

winston:create-logger: Define prototype method for "error"
winston:create-logger: Define prototype method for "warn"
winston:create-logger: Define prototype method for "info"
winston:create-logger: Define prototype method for "http"
winston:create-logger: Define prototype method for "verbose"
winston:create-logger: Define prototype method for "debug"
winston:create-logger: Define prototype method for "silly"
winston:create-logger: Define prototype method for "emerg"
winston:create-logger: Define prototype method for "alert"
winston:create-logger: Define prototype method for "crit"
winston:create-logger: Define prototype method for "error"
winston:create-logger: Define prototype method for "warning"
winston:create-logger: Define prototype method for "notice"
winston:create-logger: Define prototype method for "info"
winston:create-logger: Define prototype method for "debug"
winston:file: written true false
winston:file: logged 78 info  2021-12-10 01:08:15: Logging to directory: 'data/log' filename: log.txt

winston:file: stat done: log.txt { size: 889388 }
winston:file: create stream start data/log/log.txt { flags: 'a' }
winston:file: create stream ok data/log/log.txt
winston:file: file open ok data/log/log.txt
winston:file: written true false
winston:file: written true false
  serialport/bindings loading LinuxBinding +0ms
  serialport/stream .list +0ms
winston:file: logged 889474 info  2021-12-10 01:08:15: Starting Zigbee2MQTT version 1.22.1-dev (commit #3e5a94ea)

winston:file: logged 889537 info  2021-12-10 01:08:15: Starting zigbee-herdsman (0.13.180)

  serialport/stream .list +169ms
  serialport/stream .list +167ms
  zigbee-herdsman:controller:log Starting with options '{"network":{"networkKeyDistribute":false,"networkKey":[REDACTED],"panID":49984,"extendedPanID":[221,221,221,221,221,221,221,221],"channelList":[25]},"serialPort":{"rtscts":true,"path":"/dev/serial/by-id/usb-ITead_Sonoff_Zigbee_3.0_USB_Dongle_Plus_REDACTED-if00-port0","adapter":"auto"},"databasePath":"/srv/hass/z2m/data/database.db","databaseBackupPath":"/srv/hass/z2m/data/database.db.backup","backupPath":"/srv/hass/z2m/data/coordinator_backup.json","adapter":{"disableLED":true,"concurrent":18,"delay":null}}' +0ms
  zigbee-herdsman:adapter:zStack:znp:log Opening SerialPort with /dev/serial/by-id/usb-ITead_Sonoff_Zigbee_3.0_USB_Dongle_Plus_REDACTED-if00-port0 and {"baudRate":115200,"rtscts":true,"autoOpen":false} +0ms
  serialport/stream opening path: /dev/serial/by-id/usb-ITead_Sonoff_Zigbee_3.0_USB_Dongle_Plus_REDACTED-if00-port0 +129ms
  serialport/binding-abstract open +0ms
  serialport/stream _read queueing _read for after open +2ms
  serialport/bindings/poller Creating poller +0ms
  serialport/stream opened path: /dev/serial/by-id/usb-ITead_Sonoff_Zigbee_3.0_USB_Dongle_Plus_REDACTED-if00-port0 +9ms
  serialport/stream _read reading { start: 0, toRead: 65536 } +1ms
  serialport/binding-abstract read +13ms
  zigbee-herdsman:adapter:zStack:znp:log Serialport opened +16ms
  zigbee-herdsman:adapter:zStack:znp:SREQ --> SYS - ping - {"capabilities":1} +0ms
  zigbee-herdsman:adapter:zStack:unpi:writer --> frame [254,0,33,1,32] +0ms
  serialport/stream _write 5 bytes of data +5ms
  serialport/binding-abstract write 5 bytes +5ms
  serialport/bindings/unixRead Starting read +0ms
  serialport/bindings/unixWrite Starting write 5 bytes offset 0 bytesToWrite 5 +0ms
  serialport/bindings/unixRead read error [Error: EAGAIN: resource temporarily unavailable, read] {
  errno: -11,
  code: 'EAGAIN',
  syscall: 'read'
} +2ms
  serialport/bindings/unixRead waiting for readable because of code: EAGAIN +2ms
  serialport/bindings/poller Polling for "readable" +13ms
  serialport/bindings/unixWrite write returned: wrote 5 bytes +4ms
  serialport/bindings/unixWrite Finished writing 5 bytes +0ms
  serialport/stream binding.write write finished +7ms
  zigbee-herdsman:adapter:zStack:znp:log Writing CC2530/CC2531 skip bootloader payload +257ms
  zigbee-herdsman:adapter:zStack:unpi:writer --> buffer [239] +254ms
  serialport/stream _write 1 bytes of data +246ms
  serialport/binding-abstract write 1 bytes +252ms
  serialport/bindings/unixWrite Starting write 1 bytes offset 0 bytesToWrite 1 +247ms
  serialport/bindings/unixWrite write returned: wrote 1 bytes +0ms
  serialport/bindings/unixWrite Finished writing 1 bytes +0ms
  serialport/stream binding.write write finished +1ms
  zigbee-herdsman:adapter:zStack:znp:SREQ --> SYS - ping - {"capabilities":1} +1s
  zigbee-herdsman:adapter:zStack:unpi:writer --> frame [254,0,33,1,32] +1s
  serialport/stream _write 5 bytes of data +1s
  serialport/binding-abstract write 5 bytes +1s
  serialport/bindings/unixWrite Starting write 5 bytes offset 0 bytesToWrite 5 +1s
  serialport/bindings/unixWrite write returned: wrote 5 bytes +0ms
  serialport/bindings/unixWrite Finished writing 5 bytes +0ms
  serialport/stream binding.write write finished +1ms
  zigbee-herdsman:adapter:zStack:znp:log Skip bootloader for CC2652/CC1352 +1s
  serialport/stream #set { brk: false, cts: false, dtr: false, dts: false, rts: false } +251ms
  serialport/binding-abstract set +252ms
  serialport/stream binding.set finished +5ms
  serialport/stream #set { brk: false, cts: false, dtr: false, dts: false, rts: true } +151ms
  serialport/binding-abstract set +156ms
  serialport/stream binding.set finished +4ms
  serialport/stream #set { brk: false, cts: false, dtr: false, dts: false, rts: false } +151ms
  serialport/binding-abstract set +156ms
  serialport/stream binding.set finished +5ms
  serialport/bindings/poller received "readable" +2s
  serialport/bindings/unixRead Starting read +2s
  serialport/bindings/unixRead Finished read 1 bytes +1ms
  serialport/stream binding.read finished { bytesRead: 1 } +17ms
  zigbee-herdsman:adapter:zStack:unpi:parser <-- [0] +0ms
  zigbee-herdsman:adapter:zStack:unpi:parser --- parseNext [0] +0ms
  serialport/stream _read reading { start: 1, toRead: 65535 } +2ms
  serialport/binding-abstract read +23ms
  serialport/bindings/unixRead Starting read +2ms
  serialport/bindings/unixRead read error [Error: EAGAIN: resource temporarily unavailable, read] {
  errno: -11,
  code: 'EAGAIN',
  syscall: 'read'
} +1ms
  serialport/bindings/unixRead waiting for readable because of code: EAGAIN +0ms
  serialport/bindings/poller Polling for "readable" +4ms
  zigbee-herdsman:adapter:zStack:znp:SREQ --> SYS - ping - {"capabilities":1} +720ms
  zigbee-herdsman:adapter:zStack:unpi:writer --> frame [254,0,33,1,32] +720ms
  serialport/stream _write 5 bytes of data +132ms
  serialport/binding-abstract write 5 bytes +132ms
  serialport/bindings/unixWrite Starting write 5 bytes offset 0 bytesToWrite 5 +720ms
  serialport/bindings/unixWrite write returned: wrote 5 bytes +0ms
  serialport/bindings/unixWrite Finished writing 5 bytes +0ms
  serialport/stream binding.write write finished +1ms
  serialport/bindings/poller received "readable" +2s
  serialport/bindings/unixRead Starting read +2s
  serialport/bindings/unixRead Finished read 11 bytes +0ms
  serialport/stream binding.read finished { bytesRead: 11 } +2s
  zigbee-herdsman:adapter:zStack:unpi:parser <-- [254,6,65,128,0,2,1,2,7,1,192] +2s
  zigbee-herdsman:adapter:zStack:unpi:parser --- parseNext [0,254,6,65,128,0,2,1,2,7,1,192] +0ms
  zigbee-herdsman:adapter:zStack:unpi:parser --> parsed 6 - 2 - 1 - 128 - [0,2,1,2,7,1] - 192 +0ms
  zigbee-herdsman:adapter:zStack:znp:AREQ <-- SYS - resetInd - {"reason":0,"transportrev":2,"productid":1,"majorrel":2,"minorrel":7,"hwrev":1} +0ms
  zigbee-herdsman:adapter:zStack:unpi:parser --- parseNext [] +2ms
  serialport/stream _read reading { start: 12, toRead: 65524 } +4ms
  serialport/binding-abstract read +2s
  serialport/bindings/unixRead Starting read +4ms
  serialport/bindings/unixRead read error [Error: EAGAIN: resource temporarily unavailable, read] {
  errno: -11,
  code: 'EAGAIN',
  syscall: 'read'
} +0ms
  serialport/bindings/unixRead waiting for readable because of code: EAGAIN +1ms
  serialport/bindings/poller Polling for "readable" +6ms
  zigbee-herdsman:adapter:zStack:znp:SREQ --> SYS - ping - {"capabilities":1} +6s
  zigbee-herdsman:adapter:zStack:unpi:writer --> frame [254,0,33,1,32] +6s
  serialport/stream _write 5 bytes of data +4s
  serialport/binding-abstract write 5 bytes +4s
  serialport/bindings/unixWrite Starting write 5 bytes offset 0 bytesToWrite 5 +6s
  serialport/bindings/unixWrite write returned: wrote 5 bytes +1ms
  serialport/bindings/unixWrite Finished writing 5 bytes +0ms
  serialport/stream binding.write write finished +3ms
  zigbee-herdsman:adapter:zStack:znp:SREQ --> SYS - ping - {"capabilities":1} +6s
  zigbee-herdsman:adapter:zStack:unpi:writer --> frame [254,0,33,1,32] +6s
  serialport/stream _write 5 bytes of data +6s
  serialport/binding-abstract write 5 bytes +6s
  serialport/bindings/unixWrite Starting write 5 bytes offset 0 bytesToWrite 5 +6s
  serialport/bindings/unixWrite write returned: wrote 5 bytes +1ms
  serialport/bindings/unixWrite Finished writing 5 bytes +0ms
  serialport/stream binding.write write finished +3ms
winston:file: written true false
winston:file: written true false
winston:file: written true false
winston:file: written true false
winston:file: written true false

@verjus
Copy link

verjus commented Dec 11, 2021

@qosmio I did not test the firmware on a Raspberry Pi yet (I have an RPi3+), only on an Ubuntu Desktop (will try this week-end). I am not sure what could be happening. Did you remember to activate the hardware switch on the Dongle? Are you running more than one instance of Z2M? Can you try on different hardware?

On a side note, I am trying to find out what the hardware switch does, but I didn't find a schematic of the dongle. It would be great if the firmware could detect the switch position and activate/deactivate hardware flow control accordingly. It doesn't seem simple, since the option looks hard-coded in the firmware. Does anybody know?

@qosmio
Copy link

qosmio commented Dec 12, 2021

@verjus

@qosmio Did you remember to activate the hardware switch on the Dongle?

I didn’t realize the dip-switch was even available until I checked the manufacturer page. Assumed it was on by design. Unscrewing 2 simple screws and there it was... Just switched it on, set the setting back and it’s working!

Just enabled it 5 minutes ago, will test to see how everything goes. Thanks!

@Hedda
Copy link
Contributor Author

Hedda commented Dec 15, 2021

I didn’t realize the dip-switch was even available until I checked the manufacturer page. Assumed it was on by design.

Again, just to clarify; this is just a feature request, as there not being “hardware flow control” firmware is not really an “issue” (as in a bug or a real problem) for the majority of users with this specific adapter. That is because Hardware flow control is an optional feature that should not be needed for a majority of users and use-case scenarios. Hardware flow control is also an optional feature that to my knowledge does not exist in any of the other readily available Zigbee USB dongles that are compatible with Zigbee2MQTT and the ZHA integration in Home Assistant today as all the others only support “software flow control”. The only real “issue” is that ITead is marketing it as a feature before firmware to actually use that feature for it has been released for general availability and download by end-users.

That is, this ITead Sonoff Zigbee 3.0 USB Dongle Plus adapter does indeed have the pins and paths connected for it between the dongles SoC and its UART-to-USB bridge chip + a dip-switch on the board which can enable or disable “hardware flow control” (which for reference is a physical switch on the board that is set to disable the feature bý default). Noting that users not only need to know about the physical dip-switch, they also need a screwdriver to open the case just to be able to flick the switch to enable hardware flow control mode, so that alone should be an indicator that it is not meant to be used by every end-user (then again, Zigbee2MQTT and Home Assistant ZHA users are not usually a little more tech-savvy than most).

By default this dongle will instead use “software flow control” and what was said above is that we can not simply flip the dip-switch and set the Zigbee2MQTT or ZHA software to use “hardware flow control”, as we would also have to flash it with the other firmware image than standard which has been configured to use “hardware flow control”, and so far no one we know of has compiled and shared such firmware image.

Flow control is used to stabilize serial communication, and you can either not use it (i.e. none == “no flow control”), “software flow control” meaning applications/operating system uses system CPU to handle it, or “hardware flow control” meaning that the USB dongle firmware uses the MCU (microcontroller unit) to handle.

“Hardware flow control” should in theory make for a more stable serial communication between the application and the Zigbee USB dongle when the system CPU is overloaded as flow control has been off-loaded to the MCU, however on the other hand no one is known to have any real issues with the default “software flow control” used by default today so might be there is no real-world reason to use “hardware flow control” other than it being something new that we have not really tested before.

So for any new users stumbling on this discussion will probably think; hardware flow control must be a shiny new feature that I have not tried, that sounds cool, let us try it for kicks. If it works then great, even we see no proof that it performs better than software flow control in the real-worlds we should at least on paper have a more stable hardware setup when using it.

@Hedda
Copy link
Contributor Author

Hedda commented Dec 15, 2021

On a side note, I am trying to find out what the hardware switch does, but I didn't find a schematic of the dongle. It would be great if the firmware could detect the switch position and activate/deactivate hardware flow control accordingly. It doesn't seem simple, since the option looks hard-coded in the firmware. Does anybody know?

@guozi7788 wrote this in #329

Hardware Flow Control: DIO13: TX DIO12: RC DIO19: CTS(Need DIP-switch ON) DIO18: RTS(Need DIP-switch ON)

The same info is also in https://sonoff.tech/wp-content/uploads/2021/09/Zigbee-3.0-USB-dongle-plus-firmware-flashing-1-1.docx

UART Peripheral = Any(UART0)
TX Pin = DIO13/4 (XDS110 UART)
RC Pin = DIO12/3 (XDS110 UART)
CTS Pin = DIO19/19 (Header)
RTS Pin = DIO18/36 (Header)

@verjus saids he did not do an extensive test to determine if firmware with hardware flow control enable also works when dip-switch for it is disabled and application is configured to use software flow control. But if we can confirm that it not working then can assume that the dip-switch probably just is a physical switch that (presumably) physically switches TX and RX input paths (as in changing from one circuit board trace path to another) between the CP2102N USB-to-UART chip to the CC2652P chip from DIO13 (XDS110 UART TX pin) and DIO12 ( (XDS110 UART RX pin) to DIO19 (CTS Pin) and DIO18 (RTS Pin) respectively(?).

If so then that is not as user-friendly as if both paths could be enabled at the same time as then only the firmware would differ.

@guozi7788 could maybe help explain the function of the dip-switch for enabling hardware flow control more exactly in detail?

@Merwenus
Copy link

Done: https://github.com/Koenkk/Z-Stack-firmware/tree/develop/coordinator/Z-Stack_3.x.0/bin

For the record I'm a noob, and my question is does this firmware fix the 5vs20dba antenna problem?
I bought this out of curiousity but the signal rate is so low it drops devices after a while.

@Hedda
Copy link
Contributor Author

Hedda commented Dec 15, 2021

For the record I'm a noob, and my question is does this firmware fix the 5vs20dba antenna problem?

No, FYI; amplification power is a completely different issue not related to HW flow control in any way, please instead see -> #323

@Lefuneste83
Copy link

I am currently testing the HWC FW version of @verjus. It was first a bit fidly to find my devices. I updated to Bullseye and reinstalled the whole compilation environment and it seems to behave fine so far.

I see one issue though. When stopping the service manually, then restarting it, all cleanly waiting for the service to stop, I got this error on restart :

déc. 15 19:47:45 zigbee2mqtt npm[1915]: > [email protected] start /opt/zigbee2mqtt
déc. 15 19:47:45 zigbee2mqtt npm[1915]: > node index.js
déc. 15 19:47:52 zigbee2mqtt npm[1928]: Zigbee2MQTT:info  2021-12-15 19:47:52: Logging to console and directory: '/opt/zigbee2mqtt/data/log/2021-12-15.19-47-49' filename: log.txt
déc. 15 19:47:53 zigbee2mqtt npm[1928]: Zigbee2MQTT:info  2021-12-15 19:47:53: Starting Zigbee2MQTT version 1.22.1-dev (commit #d875b297)
déc. 15 19:47:53 zigbee2mqtt npm[1928]: Zigbee2MQTT:info  2021-12-15 19:47:53: Starting zigbee-herdsman (0.13.182)
déc. 15 19:48:15 zigbee2mqtt npm[1928]: Zigbee2MQTT:error 2021-12-15 19:48:15: Error while starting zigbee-herdsman
déc. 15 19:48:15 zigbee2mqtt npm[1928]: Zigbee2MQTT:error 2021-12-15 19:48:15: Failed to start zigbee
déc. 15 19:48:15 zigbee2mqtt npm[1928]: Zigbee2MQTT:error 2021-12-15 19:48:15: Check https://www.zigbee2mqtt.io/guide/installation/20_zigbee2mqtt-fails-to-start.html for possible solutions
déc. 15 19:48:15 zigbee2mqtt npm[1928]: Zigbee2MQTT:error 2021-12-15 19:48:15: Exiting...
déc. 15 19:48:15 zigbee2mqtt npm[1928]: Zigbee2MQTT:error 2021-12-15 19:48:15: Error: Failed to connect to the adapter (Error: SRSP - SYS - ping after 6000ms)
déc. 15 19:48:15 zigbee2mqtt npm[1928]:     at ZStackAdapter.start (/opt/zigbee2mqtt/node_modules/zigbee-herdsman/src/adapter/z-stack/adapter/zStackAdapter.ts:102:27)
déc. 15 19:48:15 zigbee2mqtt npm[1928]:     at Controller.start (/opt/zigbee2mqtt/node_modules/zigbee-herdsman/src/controller/controller.ts:123:29)
déc. 15 19:48:15 zigbee2mqtt npm[1928]:     at Zigbee.start (/opt/zigbee2mqtt/lib/zigbee.ts:58:27)
déc. 15 19:48:15 zigbee2mqtt npm[1928]:     at Controller.start (/opt/zigbee2mqtt/lib/controller.ts:100:27)
déc. 15 19:48:15 zigbee2mqtt npm[1928]:     at start (/opt/zigbee2mqtt/index.js:97:5)

Which seems similar to this post
Apparently the adapter does not reset itself on system restart.

Any solution from the config line ? Or does someone have any on how to modify the FW to avoid this ?

@Hedda
Copy link
Contributor Author

Hedda commented Dec 16, 2021

Not tested yet myself but I am also wondering if it will continue to always be possible to flash new option --bootloader-sonoff-usb for cc2538-bsl from PR JelmerT/cc2538-bsl#114 when first flashing "hardware flow control" firmware from software flow control mode, and then later when flashing a "software flow control" firmware from hardware flow control mode?

@Hedda
Copy link
Contributor Author

Hedda commented Dec 16, 2021

I see one issue though. When stopping the service manually, then restarting it, all cleanly waiting for the service to stop, I got this error on restart :

...

Which seems similar to this post Apparently the adapter does not reset itself on system restart.

Did you not see the same issue when using new software flow control firmware and are you using it in the same USB-port as then?

20211207 develop branch firmware -> https://github.com/Koenkk/Z-Stack-firmware/tree/develop/coordinator/Z-Stack_3.x.0/bin

If also seen in 20211207 develop branch firmware then should report issue to -> https://github.com/Koenkk/zigbee2mqtt/issues/

PS: Also test with zigbee2mqtt dev branch (a.k.a. Edge ) -> https://www.zigbee2mqtt.io/advanced/more/switch-to-dev-branch.html

@verjus
Copy link

verjus commented Oct 14, 2022

@Bolukan, yes the only difference between Koenkk's original firmware and the version I re-compiled is that hardware flow control is enabled. This means that 2 additional wires are used to perform RTS/CTS flow control instead of the MPU (CC2625P). These wires are enabled when you open up the dongle and activate the switch. In their default position, they are simply not connected and the flow control between the USB-to-UART bridge and the MCU is performed by the MPU in software. The only advantage is that, if the MPU is not very powerful, HFC reduces the overhead on the MPU and presents an advantage. For a relatively powerful MPU (e.g. CC2652P ), the additional burden associated with software flow control is negligible. Note that you also need to configure rtscts: false in the z2m configuration file, to switch to SFC. The version referenced in my last post is simply enabling HFC in the latest firmware posted by Koenkk.

Edited to clarify CPU/MCU confusion.

@Bolukan
Copy link

Bolukan commented Oct 15, 2022

@verjus, thx for replying. My view was the CP2102 lowers the burden for the CC2652P not the PI. Your explanation is different. Could you explain more why the PI favors of HFC?
Good for all readers: you have to open the stick once and apply the hardware switch to enable the CP2102 chip. Second step is you have to instruct the CC2652P (CPU of the stick) to send the commands to the pins of the CP2102 which can be done with RTS/CTS configuration switch or just applying the compilation of verjus.

@verjus
Copy link

verjus commented Oct 15, 2022

@Bolukan, you are right the flow control pertains to the UART connection between the MCU and CP2102 USB-to-UART bridge. Therefore it is selectable by the application (enabled/disabled in z2m configuration "rtscts: true/false"), but the software flow control must be performed in the MCU by the firmware. The additional overhead will indeed be on the CC2652P MCU, not the USB host. I will edit my post above.

@Veldkornet
Copy link

Veldkornet commented Dec 23, 2022

Anyone have a hardware flow control, version of 20221220 ?

@verjus
Copy link

verjus commented Dec 23, 2022

@Veldkornet I will try to recompile the latest version in the coming days.

@verjus
Copy link

verjus commented Dec 25, 2022

@Veldkornet I did not end up compiling 20221220 because it is not a dev version and it uses old versions of the SDK/CC Studio. Instead, I compiled the latest dev version, which can be found here. Note that it's untested. I've just flashed it to my home system and checked for a few minutes that it works (seems so).

@dkwireless
Copy link

@verjus Can you please try recompiling new one?
https://github.com/Koenkk/Z-Stack-firmware/tree/6.10.01.01/coordinator/Z-Stack_3.x.0/bin
If it's not too much trouble?

@Bolukan
Copy link

Bolukan commented Dec 26, 2022

Does it mind it's name contains 1352 and not 2652. I get errors (Unknown record type: 3) on the content. It is related to the hex file not containing 32byte rows like last non-dev release. Still looking how to solve this.
I am using TI's SmartRF Flash Programmer 2 ver. 1.8.2 with SONOFF Zigbee 3.0 stick(s).

@verjus
Copy link

verjus commented Dec 26, 2022

@Bolukan Maybe try python3.7 cc2538-bsl/cc2538-bsl.py --bootloader-sonoff-usb -evw CC1352P2_CC2652P_launchpad_coordinator_20210708.hex

@verjus
Copy link

verjus commented Dec 26, 2022

@dkwireless @Veldkornet I tried to recompile quickly the 6.10.01.01 version but I didn't test it at all. Download it here.

@Bolukan
Copy link

Bolukan commented Dec 26, 2022

@dkwireless @Veldkornet I tried to recompile quickly the 6.10.01.01 version but I didn't test it at all. Download it here.

This one is different and can be flashed.

@Bolukan
Copy link

Bolukan commented Dec 26, 2022

Solved it with srec_cat.exe source.hex -Intel -o target.hex -Intel -address-length=4 -Output_Block_Size=32
An address-length of 3 (bytes) is not accepted by the TI SmartRF Flash Programmer 2

@dkwireless
Copy link

@dkwireless @Veldkornet I tried to recompile quickly the 6.10.01.01 version but I didn't test it at all. Download it here.

Thanks for quick turnaround, however I could not start z2m with this firmware. I have added rtscts: true to config and toggled hw switch to on.

@verjus
Copy link

verjus commented Dec 26, 2022

@dkwireless Not sure if it's related to your issue, but I always have to unplug and plug the dongle after re-reflashing or even restarting Z2M with these firmwares.

@PetrMa
Copy link

PetrMa commented Jul 16, 2023

@dkwireless @VeldkornetZkoušel jsem rychle překompilovat verzi 6.10.01.01, ale vůbec jsem to netestoval. Stáhněte si jej zde .

Hi,
could you please update your firmware with the latest Koenkk version 20230507 ?

Thanks, Regards,
Petr

@dkmn-123
Copy link

Any news regarding hardware flow control of 20230507 ?
Other version with hardware flow control?
Does the bug that sonfoff has to be unplugged after each zha restart still exist?

@xelemorf
Copy link

xelemorf commented Oct 31, 2023

Any news regarding hardware flow control of 20230507 ? Other version with hardware flow control? Does the bug that sonfoff has to be unplugged after each zha restart still exist?

In the relevant FW page here: https://github.com/Koenkk/Z-Stack-firmware/tree/master/coordinator/Z-Stack_3.x.0/bin
For FW: CC1352P2_CC2652P_launchpad_coordinator_20230507.zip
In the Hardware Flow Control column for "SONOFF Zigbee 3.0 USB Dongle Plus by ITead" (CC2652P) is says the following below, which I presume would confirm this to be enabled - unless I misundestood something.

DIO13: TX
DIO12:RC
DIO19: CTS(DIP switch ON)
DIO18: RTS(DIP switch ON)

@xelemorf
Copy link

xelemorf commented Oct 31, 2023

About the HW flow control, I believe this setting would enable it within Z2M
rtscts: true
But if I enable it, Z2M would not start saying failed to communicate with adapter. I have the dip switch on.
So if my assumption is correct with the above setting, this would conclude it's not enabled on FW level.

@xekil
Copy link

xekil commented Apr 16, 2024

Good morning,

I would just like to know if the hardware flow control is functional, finally if there has been feedback from users over time and if it is indeed activated in the latest firmware?

Are there any users who use it and for whom it works with zigbee2MQTT having of course activated the DIP Switch and set the following value to true? rtscts: true

I have over 160 zigbee devices with the SONOFF Model P dongle and am wondering if this option could be beneficial.

THANKS

@xelemorf
Copy link

xelemorf commented Apr 16, 2024

Good morning,

I would just like to know if the hardware flow control is functional, finally if there has been feedback from users over time and if it is indeed activated in the latest firmware?

Are there any users who use it and for whom it works with zigbee2MQTT having of course activated the DIP Switch and set the following value to true? rtscts: true

I have over 160 zigbee devices with the SONOFF Model P dongle and am wondering if this option could be beneficial.

THANKS

I have Dongle-P with DIP switch on but had to set "rtscts: false" else it would not work.

According to the FW (launchpad) release notes hw flow control should be enabled but was unsure if I need to use rtscts: true aswell as it did not work.

Coordinator firmware is 20230507
Having 136 devices so far working flawlessly.

@xekil
Copy link

xekil commented Apr 18, 2024

I have Dongle-P with DIP switch on but had to set "rtscts: false" else it would not work.

According to the FW (launchpad) release notes hw flow control should be enabled but was unsure if I need to use rtscts: true aswell as it did not work.

Coordinator firmware is 20230507 Having 136 devices so far working flawlessly.

Thanks for the answer, I think it is not activated in the software :(

@oliv3r
Copy link
Contributor

oliv3r commented Jul 30, 2024

I realize this discussion has been stale for a while, but most was about 'it unloads the MPU of the software flow control algorithm, and there's not much effect'.

However what I know of normal serial ports, is that hardware flow control definitely becomes important once you increase the speed. If you do 115200 Baud, yeah, hardware flow control doesn't matter that much. But once you go up to 1Mbaud, having reliable communications becomes difficult without hardware flow control. The TI chip can even do 3Mbaud max (as can the USB-UART chip).

Has anybody ever tried this? I also noticed nabu-casa's own dongle also uses hardware flow control, and I even thought I saw they where doing near 1Mbaud communication.

@oliv3r
Copy link
Contributor

oliv3r commented Aug 16, 2024

I was able to enable hardware flow control in Koenkk's firmware by making the following modifications to two files, after following the instructions provided here.

The two files are: ti_drivers_config.c and ti_drivers_config.h. They reside in the syscfg directory, after applying Koenk's patch.

Here is a diff for each file:

diff ti_drivers_config.h ~/syscfg.or/ti_drivers_config.h 
97,104d96
<   /* Owned by CONFIG_DISPLAY_UART as  */
< extern const uint_least8_t CONFIG_GPIO_3_CONST;
< #define CONFIG_GPIO_3 19
< 
< /* Owned by CONFIG_DISPLAY_UART as  */
< extern const uint_least8_t CONFIG_GPIO_4_CONST;
< #define CONFIG_GPIO_4 18
< 
225,226d216
<  *  CTS: DIO19
<  *  RTS: DIO18

and

diff ti_drivers_config.h ~/syscfg.or/ti_drivers_config.h 
97,104d96
<   /* Owned by CONFIG_DISPLAY_UART as  */
< extern const uint_least8_t CONFIG_GPIO_3_CONST;
< #define CONFIG_GPIO_3 19
< 
< /* Owned by CONFIG_DISPLAY_UART as  */
< extern const uint_least8_t CONFIG_GPIO_4_CONST;
< #define CONFIG_GPIO_4 18
< 
225,226d216
<  *  CTS: DIO19
<  *  RTS: DIO18
PCAXS::syscfg>diff ti_drivers_config.c ~/syscfg.or/ti_drivers_config.c
269,272c269,270
<     /* Owned by CONFIG_DISPLAY_UART as RTS */
<     GPIO_CFG_OUTPUT_INTERNAL | GPIO_CFG_OUT_STR_MED | GPIO_CFG_OUT_LOW, /* CONFIG_GPIO_4 */
<     /* Owned by CONFIG_DISPLAY_UART as CTS */
<     GPIO_CFG_INPUT_INTERNAL | GPIO_CFG_IN_INT_NONE | GPIO_CFG_PULL_DOWN_INTERNAL, /* CONFIG_GPIO_3 */
---
>     GPIO_CFG_NO_DIR, /* DIO_18 */
>     GPIO_CFG_NO_DIR, /* DIO_19 */
307,308d304
< const uint_least8_t CONFIG_GPIO_3_CONST = CONFIG_GPIO_3;
< const uint_least8_t CONFIG_GPIO_4_CONST = CONFIG_GPIO_4;
813,814c809,810
<     .ctsPin             = CONFIG_GPIO_3,
<     .rtsPin             = CONFIG_GPIO_4,
---
>     .ctsPin             = GPIO_INVALID_INDEX,
>     .rtsPin             = GPIO_INVALID_INDEX,

The relevant sections of each file should look like this for ti_drivers_config.c

void* gpioUserArgs[31];

const uint_least8_t CONFIG_GPIO_1_CONST = CONFIG_GPIO_1;
const uint_least8_t CONFIG_GPIO_2_CONST = CONFIG_GPIO_2;
const uint_least8_t CONFIG_GPIO_3_CONST = CONFIG_GPIO_3;
const uint_least8_t CONFIG_GPIO_4_CONST = CONFIG_GPIO_4;
const uint_least8_t CONFIG_RF_24GHZ_CONST = CONFIG_RF_24GHZ;

this

    GPIO_CFG_NO_DIR, /* DIO_16 */
    GPIO_CFG_NO_DIR, /* DIO_17 */
    /* Owned by CONFIG_DISPLAY_UART as RTS */
    GPIO_CFG_OUTPUT_INTERNAL | GPIO_CFG_OUT_STR_MED | GPIO_CFG_OUT_LOW, /* CONFIG_GPIO_4 */
    /* Owned by CONFIG_DISPLAY_UART as CTS */
    GPIO_CFG_INPUT_INTERNAL | GPIO_CFG_IN_INT_NONE | GPIO_CFG_PULL_DOWN_INTERNAL, /* CONFIG_GPIO_3 */
    /* Owned by CONFIG_NVS_SPI_0 as Button GPIO */
    GPIO_CFG_OUTPUT_INTERNAL | GPIO_CFG_OUT_STR_MED | GPIO_CFG_OUT_HIGH, /* CONFIG_GPIO_0 */
    GPIO_CFG_NO_DIR, /* DIO_21 */
    GPIO_CFG_NO_DIR, /* DIO_22 */
    GPIO_CFG_NO_DIR, /* DIO_23 */
    GPIO_CFG_NO_DIR, /* DIO_24 */

and this

static const UARTCC26XX_HWAttrsV2 uartCC26XXHWAttrs[CONFIG_UART_COUNT] = {
  {
    .baseAddr           = UART0_BASE,
    .intNum             = INT_UART0_COMB,
    .intPriority        = (~0),
    .swiPriority        = 0,
    .powerMngrId        = PowerCC26XX_PERIPH_UART0,
    .ringBufPtr         = uartCC26XXRingBuffer0,
    .ringBufSize        = sizeof(uartCC26XXRingBuffer0),
    .rxPin              = CONFIG_GPIO_2,
    .txPin              = CONFIG_GPIO_1,
    .ctsPin             = CONFIG_GPIO_3,
    .rtsPin             = CONFIG_GPIO_4,
    .txIntFifoThr       = UARTCC26XX_FIFO_THRESHOLD_1_8,
    .rxIntFifoThr       = UARTCC26XX_FIFO_THRESHOLD_4_8,
    .errorFxn           = NULL
  },
};

and for ti_drivers_config.h

/*
 *  ======== GPIO ========
 */
/* Owned by CONFIG_DISPLAY_UART as  */
extern const uint_least8_t CONFIG_GPIO_1_CONST;
#define CONFIG_GPIO_1 13

/* Owned by CONFIG_DISPLAY_UART as  */
extern const uint_least8_t CONFIG_GPIO_2_CONST;
#define CONFIG_GPIO_2 12

  /* Owned by CONFIG_DISPLAY_UART as  */
extern const uint_least8_t CONFIG_GPIO_3_CONST;
#define CONFIG_GPIO_3 19

/* Owned by CONFIG_DISPLAY_UART as  */
extern const uint_least8_t CONFIG_GPIO_4_CONST;
#define CONFIG_GPIO_4 18

/* Owned by /ti/drivers/RF as  */
extern const uint_least8_t CONFIG_RF_24GHZ_CONST;
// #define CONFIG_RF_24GHZ 28

Then rebuild the firmware.

I tested that it works with the latest dev z2m, with rtscts enabled in the configuration file:

advanced:
  # Optional: Baud rate speed for serial port, this can be anything firmware support but default is 115200 for Z-Stack and EZSP,
  # 38400 for Deconz, however note that some EZSP firmware need 57600.
  #baudrate: 115200
  # Optional: RTS / CTS Hardware Flow Control for serial port (default: false)
  rtscts: true

and of course, the with hardware switch activated. I haven't tested the firmware itself but z2m communicates with the stick.

Hope this is useful to someone. Disclaimer, I haven't tested the firmware's performance or even its ability to pair. I just checked that the firmware allows for the serial port to be open:

Zigbee2MQTT:debug 2021-12-05 20:44:29: Using zigbee-herdsman with settings: '{"adapter":{"concurrent":null,"delay":null,"disableLED":false},"backupPath":"/opt/zigbee2mqtt/data/coordinator_backup.json","databaseBackupPath":"/opt/zigbee2mqtt/data/database.db.backup","databasePath":"/opt/zigbee2mqtt/data/database.db","network":{"channelList":[11],"extendedPanID":[221,221,221,221,221,221,221,221],"networkKey":"HIDDEN","panID":6754},"serialPort":{"path":"/dev/ttyUSB0","rtscts":true}}'
  zigbee-herdsman:controller:log Starting with options '{"network":{"networkKeyDistribute":false,"networkKey":[redacted],"panID":6754,"extendedPanID":[221,221,221,221,221,221,221,221],"channelList":[11]},"serialPort":{"rtscts":true,"path":"/dev/ttyUSB0"},"databasePath":"/opt/zigbee2mqtt/data/database.db","databaseBackupPath":"/opt/zigbee2mqtt/data/database.db.backup","backupPath":"/opt/zigbee2mqtt/data/coordinator_backup.json","adapter":{"disableLED":false,"concurrent":null,"delay":null}}' +0ms
  zigbee-herdsman:adapter:zStack:znp:log Opening SerialPort with /dev/ttyUSB0 and {"baudRate":115200,"rtscts":true,"autoOpen":false} +0ms
  zigbee-herdsman:adapter:zStack:znp:log Serialport opened +6ms
  zigbee-herdsman:adapter:zStack:znp:SREQ --> SYS - ping - {"capabilities":1} +0ms

So I also tried to build the firmware with hardware flow control enabled. With the current SDK this was a bit problematic. The instructions in the document refer to the UART, which doesn't exist anymore. There's UART2 now, which is connected to the DISPLAY. Removing display and just adding the uart will cause havoc. But removing the display, and adding it again allows one to play with the uarts, or maybe there's some magic to do this in the GUI. Regardless, in the end, the ZNP can be hacked/edited to look like this (diff):

diff -u --color znp_CC1352P_2_LAUNCHXL.syscfg znp_CC1352P_2_fastmode.syscfg                                            2024-08-17 00:00:56 [0]
--- znp_CC1352P_2_LAUNCHXL.syscfg	2024-08-16 23:29:13.510582935 +0200
+++ znp_CC1352P_2_fastmode.syscfg	2024-08-16 23:56:07.125021365 +0200
@@ -72,12 +72,16 @@
 
 rfdesign.rfDesign = "LAUNCHXL-CC1352P-2";
 
-Display1.$hardware               = system.deviceData.board.components.XDS110UART;
-Display1.$name                   = "CONFIG_DISPLAY";
-Display1.uart.$name              = "CONFIG_DISPLAY_UART";
-Display1.uart.uart.$assign       = "UART1";
-Display1.uart.uart.txPin.$assign = "boosterpack.4";
-Display1.uart.uart.rxPin.$assign = "boosterpack.3";
+Display1.$name                    = "CONFIG_DISPLAY";
+Display1.uart.$name               = "CONFIG_DISPLAY_UART";
+Display1.uart.flowControl         = true;
+Display1.uart.uart.$assign        = "UART1";
+Display1.uart.uart.txPin.$assign  = "boosterpack.4";
+Display1.uart.uart.rxPin.$assign  = "boosterpack.3";
+Display1.uart.uart.ctsPin.$assign = "boosterpack.19";
+Display1.uart.uart.rtsPin.$assign = "boosterpack.36";
+scripting.suppress("Connected to hardware,@@@.+?@@@ is connected to XDS110 UART on the CC1352P-2 LaunchPad\\. Consider selecting it in 'use hardware' above\\. @@@.+?@@@", Display1.uart.uart, "txPin");
+scripting.suppress("Connected to hardware,@@@.+?@@@ is connected to XDS110 UART on the CC1352P-2 LaunchPad\\. Consider selecting it in 'use hardware' above\\. @@@.+?@@@", Display1.uart.uart, "rxPin");
 
 AESCBC1.$name = "CONFIG_AESCBC_0";
 

Which becomes obvious just removes the 'hardware mapping' and allows one to assign the pins. The suppressions are needed as well of course. So you'd think, great; hardware flow control. Alas. The firmware builds and runs fine, but as before. Toggeling the switch even causes timeout errors. I'll read your post again and dive more deeply into things, especially comparing the generated ti_*_.h files ...

@oliv3r
Copy link
Contributor

oliv3r commented Aug 17, 2024

@verjus can you somehow confirm that hardware flow control was ever working at all for you?

I'm using zigpy-cli (and yes, I patched hwfc into radio.py :) zigpy/zigpy-cli#52) but I flashed your 20221102 firmware (zigpy_znp.api DEBUG Received command: SYS.Version.Rsp(TransportRev=2, ProductId=1, MajorRel=2, MinorRel=7, MaintRel=1, CodeRevision=20221102, BootloaderBuildType=<BootloaderBuildType.NON_BOOTLOADER_BUILD: 0>, BootloaderRevision=None) ) but I don't even have to toggle the switch. Obvisously zigpy also doesn't enable hardware flow control

zigpy.serial DEBUG Opening a serial connection to '/dev/ttyUSB0' (baudrate=115200, xonxoff=False, rtscts=False)

Since my own firmware wasn't doing it either, I now wonder what/how/why. I'll be changing the baudrate next, just to confirm that something actually changes here ...

Which I can confirm now, is not doing anything. So those SDK settings are completly ignored/unused.

zigpy_znp.uart DEBUG Connecting to /dev/ttyUSB0 at 57600 baud
...
TimeoutError

Of course everything works fine with 115200.

And if we look at ti_drivers_config.c we see it's setup properly

const DisplayUart2_HWAttrs displayUart2HWAttrs = {
    .uartIdx      = CONFIG_DISPLAY_UART,
    .baudRate     = 57600,
    .mutexTimeout = (unsigned int)(-1),
    .strBuf       = displayUART2Buffer,
    .strBufLen    = Display_UART2BUFFERSIZE
};
...
static const UART2CC26X2_HWAttrs uart2CC26X2HWAttrs[CONFIG_UART2_COUNT] = {
  {
    .baseAddr           = UART0_BASE,
    .intNum             = INT_UART0_COMB,
    .intPriority        = (~0),
    .rxPin              = CONFIG_GPIO_DISPLAY_UART_RX,
    .txPin              = CONFIG_GPIO_DISPLAY_UART_TX,
    .ctsPin             = CONFIG_GPIO_DISPLAY_UART_CTS,
    .rtsPin             = CONFIG_GPIO_DISPLAY_UART_RTS,
    .flowControl        = UART2_FLOWCTRL_HARDWARE,
    .powerId            = PowerCC26XX_PERIPH_UART0,
    .rxBufPtr           = uart2RxRingBuffer0,
    .rxBufSize          = sizeof(uart2RxRingBuffer0),
    .txBufPtr           = uart2TxRingBuffer0,
    .txBufSize          = sizeof(uart2TxRingBuffer0),
    .txPinMux           = IOC_PORT_MCU_UART0_TX,
    .rxPinMux           = IOC_PORT_MCU_UART0_RX,
    .ctsPinMux          = IOC_PORT_MCU_UART0_CTS,
    .rtsPinMux          = IOC_PORT_MCU_UART0_RTS,
    .dmaTxTableEntryPri = &dmaUart0TxControlTableEntry,
    .dmaRxTableEntryPri = &dmaUart0RxControlTableEntry,
    .rxChannelMask      = 1 << UDMA_CHAN_UART0_RX,
    .txChannelMask      = 1 << UDMA_CHAN_UART0_TX,
    .txIntFifoThr       = UART2CC26X2_FIFO_THRESHOLD_1_8,
    .rxIntFifoThr       = UART2CC26X2_FIFO_THRESHOLD_4_8
  },
};

So flowcontrol, baudrate, everything is adjusted, but nothing happens.

The only thing left going for this is, that Itead has
image
which indicates UART, instead of UART2; but then it's still CONFIG_DISPLAY_UART. I'll do a build with the UART assigned different pins; maybe put TX on the CTS pin; that should result in a non-functional serial console ... and supprise, that does actually supress any output ... weird. So the settings of the UART are honored, just not the baudrate and flowcontrol settings ...

@oliv3r
Copy link
Contributor

oliv3r commented Aug 17, 2024

I just took some pictures under the microscope to trace pins out, but I verified it with the multimeter anyway, so those traces won't offer much of value. Anyway, what's interesting, from my first sights, it seems that the on/off switch is merly an open/close between the USB chip and the MCU.

What strikes me as very odd however, connecting those pins however, causes regular 2 wire TX/RX to fail. Flipping the switch and all is fine again. Further more, programming always works. So no idea why this would have any effect at all. I'll double check, but even if those pins are pulled high or low by the switch somehow, how should that affect anything? Unless the CN2102 behaves oddly when you pull those pins .. I'll check that datasheet first.

So I just looked at those pins, and they are most certainly connected to something. I haven't be able to find where the pins lead (other then a resistor) the switch does certainly more then just disconnect something. (could be still as simple as a pull-up on the RTS line; but that doesn't explain it not working ...

So thinking about it for a bit; if the USB chip, is getting its CTS line pulled up; then the this will cause comms to halt/fail. However, if the host isn't using hardware duplex comms, then what does the chip care? But no idea if the hwfc does anything with the USB chip from the protocol side. I would think so?

@oliv3r
Copy link
Contributor

oliv3r commented Aug 24, 2024

So a TI expert at e2e more or less confirmed. At least for the baudrate, these settings do nothing. Most likely also for flow-control ... https://e2e.ti.com/support/wireless-connectivity/zigbee-thread-group/zigbee-and-thread/f/zigbee-thread-forum/1401511/cc2652p-cannot-change-baudrate-flowcontrol-or-rather-the-settings-have-no-effect/5372429#5372429

@verjus
Copy link

verjus commented Aug 30, 2024

Hi @oliv3r,

I don't have more information on this but, at the time, I had reached out to ITEAD because I was hoping to detect the position of the switch within the firmware, but they indicated that the switch is not connected to anything when it's closed:


Frankie in SONOFF[email protected]

Hi
When it is closed, it is not connected to any place, it is disconnected. The switch is to switch hardware flow control or software flow control.

attachment

Regards,
Frankie in SONOFF

On Tue, 21 Dec at 11:49 AM , Verjus wrote:
Hello Frankie,

Thanks, but that doesn't answer my question. I already changed it myself and it works fine. 

What I was wondering is whether the firmware could be programmed to be changed dynamically
depending on the position of the hardware switch. So the question is what does the switch do exactly?
I realize that it connects the CTS to GPIO18 and RTS to GPIO19 when it's on, but what does it do when
it's off? Does it connect GPIO18/19 to 3V or GND? The idea would be to query at boot time GPIO18
and/or 19 to determine the position of the Switch and assign

    .ctsPin             = CONFIG_GPIO_3,
    .rtsPin             = CONFIG_GPIO_4,
or
    .ctsPin             = GPIO_INVALID_INDEX,
    .rtsPin             = GPIO_INVALID_INDEX,

Thanks,
Verjus

    From: Frankie in SONOFF <[email protected]>
    Sent: Monday, December 20, 2021 12:04 AM
    To: Verjus
    Subject: Re: [#477138] Firmware hardaware control flow
     
    Dear  Verjus
    If you change the firmware yourself, use GPIO12, GPIO13 as UART



    Regards,
    Frankie in SONOFF

        On Mon, 13 Dec at 5:43 AM , Verjus wrote:
         Hello,
        I managed to activate hardware flow control on Koenk's Zigbee2mqtt firmware and it seems to work fine. I would like to know if I can create a single firmware for both software and hardware flow control. To do so, I would need to read the state of the hardware switch on the device. I don't have a schematic and would like to know what the switch does. My guess is that it connects the cp2102N CTS/RTS to the cc2652p, but what about the other software mode? Is it possible to read the state of the switch by looking at DIO_18 or DIO_19 and setting
            .ctsPin             = CONFIG_GPIO_3,
            .rtsPin             = CONFIG_GPIO_4,
        or
            .ctsPin             = GPIO_INVALID_INDEX,
            .rtsPin             = GPIO_INVALID_INDEX,

        depending or the result? If so, I would be happy to try incorporate this to the firmware.

        Thank you,
        Verjus

@oliv3r
Copy link
Contributor

oliv3r commented Aug 30, 2024

@verjus thanks for your reply.

So my board must be different :p because there's definitely a trace going from the 'off' position to a resistor. Also the pin reads 'high'. I haven't traced out the resistor :p but it is certainly going somewhere.

Sadly, Neither your firmware nor my builds do anything special with hardware flow control enabled. The firmware works as before and enabling the switch makes things simply 'not work'. I scoped the signals and at least RTS was doing something from the MCU. Of course could also be that zigpy-znp isn't properly enabling HWFC :p so I have on my TODO list to try mqtt2zigbee to see if that does work. Just want to reproduce what you where doing. Once I get hwfc going, I want to switch to 1M or more :)

As for the dynamic switch detection, it's not really beneficial imo. I've done some work to build the image via docker, so building an image is trivial. In addition to that, building now works with configuration files instead of patches, and after that, via the CI, once that is in place, things are fully automated so having an additional target firmware is also trivial. Support requests aside of course, which is a valid point. But the clear benefit would in that case (if stable) be 1M + HWFC. (maybe even 3 MBaud :p)

One more question; are you still using HWFC and is it actually working for you? How have you confirmed it is actually working?

@verjus
Copy link

verjus commented Aug 30, 2024

Maybe check with ITEAD ([email protected]) if they updated the hardware (I bought the device as soon as it came out)? I agree that it is possible that the hardware flow control was never enabled. The only indication I had was that "rtscts: true" became necessary, but that's not much of a indication that HFC is actually enabled and working. Even it is is, it's not clear whether the difference is material. All I did was follow ITEAD's instruction to enable HFC in the firmware.

@oliv3r
Copy link
Contributor

oliv3r commented Sep 1, 2024

Maybe check with ITEAD ([email protected]) if they updated the hardware (I bought the device as soon as it came out)? I agree that it is possible that the hardware flow control was never enabled. The only indication I had was that "rtscts: true" became necessary, but that's not much of a indication that HFC is actually enabled and working. Even it is is, it's not clear whether the difference is material. All I did was follow ITEAD's instruction to enable HFC in the firmware.

@verjus thanks. But are you still using/doing this?

Anyway, I'm pretty sure itead has probably zero idea. The engineers engineered and that's that.

image
is what I see on my dongle, where I did actually measure that resistor :) I haven't managed to trace out the rest after that resistor however, also due to patience :p , but the switch most defiantly turns 'on' that connection on those green/yellow traces. The useless thing is, (for green/CTS) of course is, that that resistor 'normally' connects to the CPN2102. So the MCU is simply 'disconnected'. For the RTS, I have no idea, didn't check, but it's impossible that 'disconnecting' the RTS suddenly connects it to something else.

I'll check with MQTT and rtscts: true, but Without the switch, everything just works, and with the switch on, nothing works, even enabling hardware flow control. I wonder if I could ask support for the schematic ... It's not like I could desolder all parts and just draw it anyway ...

What you describe btw, is exactly how it should work, if hwfc is enabled, you shouldn't be able to communicate as buffers never get refilled due to the RTS/CTS behavior.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests