Issues with RMT TransmitterChannel and ReceiverChannel
Library/API/IoT binding
nanoFramework.Hardware.Esp32.Rmt
Visual Studio version
VS2022
.NET nanoFramework extension version
2022.14.1.2
Target name(s)
ESP32_S3_BLE, XIAO_ESP32C3, ESP32_C3_REV3, ESP32_C6_THREAD
Firmware version
1.14.0.59
Device capabilities
No response
Description
Hi, I found a probably issue on nanoFramework.Hardware.Esp32.Rmt v2.0.35
with this code:
var rxChannelSettings = new ReceiverChannelSettings(3)
{
// 1us clock ( 80Mhz / 80 ) = 1Mhz
//ClockDivider = 80,
// no filter
EnableFilter = true,
FilterThreshold = 100,
// max time 1us clock
//IdleThreshold = ushort.MaxValue,
IdleThreshold = 40_000,
// timeout after 1 second
ReceiveTimeout = TimeSpan.FromSeconds(1),
EnableDemodulation = false
};
using var rxChannel = new ReceiverChannel(rxChannelSettings);
I receive:
++++ Exception System.Exception - CLR_E_DRIVER_NOT_REGISTERED (3) ++++
++++ Message:
++++ nanoFramework.Hardware.Esp32.Rmt.ReceiverChannel::NativeRxInit [IP: 0000] ++++
++++ nanoFramework.Hardware.Esp32.Rmt.ReceiverChannel::.ctor [IP: 001a] ++++
on ESP32_S3_BLE XIAO_ESP32C3 ESP32_C3_REV3 ESP32_C6_THREAD
workaround is to manualy set the channel
var rxChannelSettings = new ReceiverChannelSettings(3)
{
EnableFilter = true,
FilterThreshold = 100,
IdleThreshold = 40_000,
ReceiveTimeout = TimeSpan.FromSeconds(1),
//Inserting this work but non on all boards
**Channel = 4,**
EnableDemodulation = false
};
using var rxChannel = new ReceiverChannel(rxChannelSettings);
but this work only on ESP32_S3_BLE non on C3 and not on C6
this problem affect also other classes using Esp32 Rtm: Iot.Device.DHTxx.Esp32.DhtBase constructor (workaround ok only on S3)
[nanoFramework.IoT.Device/DhtBase.csdevices/Dhtxx.Esp32/DhtBase.cs]https://github.com/nanoframework/nanoFramework.IoT.Device/blob/develop/devices/Dhtxx.Esp32/DhtBase.cs
NeoPixel.NeopixelChain (affected only C3 and C6) this sample is using TransmitterChannel samples/Hardware.Esp32.Rmt/NeoPixelStrip/NeoPixel/NeopixelChain.cs https://github.com/nanoframework/Samples/blob/main/samples/Hardware.Esp32.Rmt/NeoPixelStrip/NeoPixel/NeopixelChain.cs
I find the exception on C++ code but I've not IDE and skills to investigate: ....nanoFramework.Hardware.Esp32.Rmt/nanoFramework_hardware_esp32_rmt_native_nanoFramework_Hardware_Esp32_Rmt_ReceiverChannel.cpp::NativeRxInit___I4 ....nanoFramework.Hardware.Esp32.Rmt/nanoFramework_hardware_esp32_rmt_native_nanoFramework_Hardware_Esp32_Rmt_TransmitterChannel.cpp::NativeTxInit___I4
Thanks for attention.
N.
How to reproduce
Try to use Dht22 with Dhtxx.Esp32 or initialize ReceiverChannelSettings without an explicit channel in settings. For XIAO_ESP32C3, ESP32_C3_REV3, ESP32_C6_THREAD: Try to initialize ReceiverChannelSettings with or without an explicit channel in settings.
Expected behaviour
No response
Screenshots
No response
Sample project or code
var rxChannelSettings = new ReceiverChannelSettings(3)
{
// 1us clock ( 80Mhz / 80 ) = 1Mhz
//ClockDivider = 80,
// no filter
EnableFilter = true,
FilterThreshold = 100,
// max time 1us clock
//IdleThreshold = ushort.MaxValue,
IdleThreshold = 40_000,
// timeout after 1 second
ReceiveTimeout = TimeSpan.FromSeconds(1),
EnableDemodulation = false
};
using var rxChannel = new ReceiverChannel(rxChannelSettings);
Aditional information
XIAO_ESP32C3, ESP32_C3_REV3, ESP32_C6_THREAD has problem with TransmitterChannel and ReceiverChannel
Have you setup the pins properly and checked they can be used for this RMT function for the C3 and C6? See: https://docs.espressif.com/projects/esp-idf/en/stable/esp32c3/api-reference/peripherals/gpio.html (and similar for the C6)
Have you setup the pins properly and checked they can be used for this RMT function for the C3 and C6? See: https://docs.espressif.com/projects/esp-idf/en/stable/esp32c3/api-reference/peripherals/gpio.html (and similar for the C6)
Yes, I tried all pin but no one is working for C3 and C6.
I add: also this this parameter in esp32 s3 cause exception and must be commented to work: //ClockDivider = 80,
Tell me if can do some more tests.
Yes, I tried all pin but no one is working for C3 and C6.
How are you setting the pins in your code?
Yes, I tried all pin but no one is working for C3 and C6.
How are you setting the pins in your code?
var rxChannelSettings = new ReceiverChannelSettings(0)
tried also
var rxChannelSettings = new ReceiverChannelSettings(0) { PinNumber = 0, ....
0 in that case is the pin number. Have you tried any other pin number? I think 0 is not the best to use on a C3 like 4, 5, 8, 9?
0 in that case is the pin number. Have you tried any other pin number? I think 0 is not the best to use on a C3 like 4, 5, 8, 9?
Yes I tried. I've an update: The problem seem to be related to the channel on C3 and C6 only setting channel to 2 or to 3 is working. From https://docs.espressif.com/projects/esp-idf/en/v4.3/esp32c3/api-reference/peripherals/rmt.htm
The RMT has four channels numbered from zero to three. The first half (i.e. Channel 0 ~ 1) channels can only be configured for transmitting, and the other half (i.e. Channel 2 ~ 3) channels can only be configured for receiving.
I've also found (this can be inserted in documentation of nanoframework, I think is usefull):
The ESP32 has 8 channels, each of them can be either receiver or transmitter The ESP32-C3 has 4 channels, Channel<0> and Channel<1> hardcoded for transmitting signals and Channel<2> and Channel<3> hardcoded for receiving signals. The ESP32-C6 has 4 channels, Channel<0> and Channel<1> hardcoded for transmitting signals and Channel<2> and Channel<3> hardcoded for receiving signals. The ESP32-H2 has 4 channels, Channel<0> and Channel<1> hardcoded for transmitting signals and Channel<2> and Channel<3> hardcoded for receiving signals. The ESP32-S2 has 4 channels, each of them can be either receiver or transmitter. The ESP32-S3 has 8 channels, Channel<0>-Channel<3> hardcoded for transmitting signals and Channel<4>-Channel<7> hardcoded for receiving signals.
all this is explain the problem and difference of working channels I found between C3-C6/S3
Now the open points are:
- without an explicit channel the constructor for TransmitterChannel and ReceiverChannel fails often
- ClockDivider = 80 in the ChannelSettings cause exception, I will investigate a bit more on this.
Thanks for support.
@NazzaN thank you very much for all your testing and investigation on this issue. Yes, agreed that this should be in the documentation. Most obvious location seems to be in the repo README. Following that, it's probably better to update the IntelliSense comment on the constructor to point to the readme for details. I suppose that you are able to build the fw locally in order to test your changes/fixes to the clock divider...
@NazzaN thank you very much for all your testing and investigation on this issue. Yes, agreed that this should be in the documentation. Most obvious location seems to be in the repo README. Following that, it's probably better to update the IntelliSense comment on the constructor to point to the readme for details. I suppose that you are able to build the fw locally in order to test your changes/fixes to the clock divider...
I can do some check on C# code but this logic in on cpp: /nanoFramework_hardware_esp32_rmt_native_nanoFramework_Hardware_Esp32_Rmt_ReceiverChannel.cpp
there is also code for all specific boards, maybe something is changed in sdk, I've not skills to fix this
there is also code for all specific boards, maybe something is changed in sdk, I've not skills to fix this
+1, thanks a lot for the investigation! Before the fix, maybe just the update on the README from the repo and a special note about the C3/C6 will be a great start! Now, with the history of the conversation in this issue, it will allow for a later fix.
@NazzaN understood! No worries, we'll take it from here. You've already done a lot of work digging into this. 👌🏻
@NazzaN understood! No worries, we'll take it from here. You've already done a lot of work digging into this. 👌🏻
It's a great project, I'm happy to help in some way!
Hey all, I just hit this bug with the HC-SR04 library on this ESP32 board:
System Information
HAL build info: nanoCLR running @ ESP32 built with ESP-IDF v5.4.2
Target: ESP32_REV0
Platform: ESP32
Firmware build Info:
Date: Nov 1 2025
Type: MinSizeRel build, chip rev. >= 0, without support for PSRAM
CLR Version: 1.14.0.92
Compiler: GNU ARM GCC v14.2.0
OEM Product codes (vendor, model, SKU): 0, 0, 0
Serial Numbers (module, system):
00000000000000000000000000000000
1000000000C8C9A3D19DEC
Target capabilities:
Has nanoBooter: NO
IFU capable: NO
Has proprietary bootloader: YES
HC-SR04 has a dependency on the ESP32 RMT library and, by default, does not specify a channel number. The RMT library, as far as I can recall, should attempt to find the next available channel.
My whole dev environment was nuked previously so it'll take me a bit of time to get set up again with NF and investigate this but I wanted to let you know that I'm looking into this.
It appears that the RMT drivers that nf uses currently have been "deprecated". The docs are referencing new types and the ones used by nf are now moved to /driver/deprecated/rmt_legacy.c.
I am not 100% sure this is why we're seeing this error but I can't rule it out yet.
@MrCSharp22 thanks for reporting this. And yes, there is already an open issue to track the migration to the new versions.
After further investigation, looks like there are 2 issues here:
- Dedicated TX/RX RMT Channels
As per @NazzaN's comment, some boards have dedicated (potentially exclusive) channels for TX and RX.
The current automatic channel allocation logic in the native nf RMT lib does not account for this fact.
CLR_INT32 Library_nanoFramework_hardware_esp32_rmt_native_nanoFramework_Hardware_Esp32_Rmt_RmtChannel::FindNextChannel()
{
for (signed int channel = RMT_CHANNEL_0; channel < RMT_CHANNEL_MAX; ++channel)
{
if (registredChannels.find(CHANNEL(channel)) == registredChannels.end())
{
return channel;
}
}
return -1;
}
I believe we should update this code to handle these cases appropriately. I think we can set specific flags per device target to control how the channel allocation logic in this method can behave.
- GPIO Pin Restrictions
(This is what I ran into above)
ESP's RMT driver allows only specific GPIO pins to be used for input/output.
soc_caps.h has the following macro which rmt_set_gpio(...) in rmt_legacy.c uses to validate the output pin:
#define SOC_GPIO_VALID_OUTPUT_GPIO_MASK (SOC_GPIO_VALID_GPIO_MASK & ~(0ULL | BIT34 | BIT35 | BIT36 | BIT37 | BIT38 | BIT39))
This means any GPIO pin >= 34 is considered input-only and cannot be used for RMT TX.
I see 2 possible ways we can handle this:
- throw an exception from the managed library but might not be very helpful considering we don't allow string messages to keep RAM usage low.
- or; explain this restriction in the managed library's README file.
I guess the good news here is that we can roll out a fix for this fairly quickly and it should have no impact on backwards compatibility.
Hey all. I've opened a PR for the GPIO pin restrictions. I'll work on the dedicated RMT channels later this week when I have a bit more time on my hands. Cheers :)