fix: update DALI double send delay and increase SPIRAM malloc reserve size

This commit fix the crash risk when bus abnormal.

Signed-off-by: Tony <tonylu@tony-cloud.com>
This commit is contained in:
Tony
2026-06-16 06:07:06 +08:00
parent 49dcd8785b
commit 3fca7161fc
11 changed files with 321 additions and 35 deletions
+5
View File
@@ -73,6 +73,10 @@
#define CONFIG_GATEWAY_USB_SETUP_READ_TIMEOUT_MS 20
#endif
#ifndef CONFIG_DALI_BUS_RESET_PULSE_MS
#define CONFIG_DALI_BUS_RESET_PULSE_MS 10
#endif
#ifndef CONFIG_GATEWAY_485_CONTROL_BAUDRATE
#define CONFIG_GATEWAY_485_CONTROL_BAUDRATE 9600
#endif
@@ -1284,6 +1288,7 @@ extern "C" void app_main(void) {
usb_config.rx_buffer_size = static_cast<size_t>(CONFIG_GATEWAY_USB_SETUP_RX_BUFFER);
usb_config.tx_buffer_size = static_cast<size_t>(CONFIG_GATEWAY_USB_SETUP_TX_BUFFER);
usb_config.read_timeout_ms = static_cast<uint32_t>(CONFIG_GATEWAY_USB_SETUP_READ_TIMEOUT_MS);
usb_config.reset_pulse_ms = static_cast<uint32_t>(CONFIG_DALI_BUS_RESET_PULSE_MS);
s_usb_setup_bridge = std::make_unique<gateway::GatewayUsbSetupBridge>(*s_controller,
*s_dali_domain,
usb_config);
+1 -1
View File
@@ -2919,7 +2919,7 @@ CONFIG_DALI_CUSTOM_HALF_BIT_TIME_X100_US=0
CONFIG_DALI_TX_STOP_CONDITION_US=0
CONFIG_DALI_RX_STOP_CONDITION_US=0
CONFIG_DALI_QUERY_RESPONSE_TIMEOUT_MS=30
CONFIG_DALI_DOUBLE_SEND_DELAY_MS=20
CONFIG_DALI_DOUBLE_SEND_DELAY_MS=30
CONFIG_DALI_FORWARD_ACTIVITY_WAIT_MS=20
CONFIG_DALI_FORWARD_AFTER_BACKWARD_WAIT_MS=10
CONFIG_DALI_FORWARD_MAX_WAIT_MS=50
+4 -4
View File
@@ -1861,7 +1861,7 @@ CONFIG_SPIRAM_USE_MALLOC=y
CONFIG_SPIRAM_MEMTEST=y
CONFIG_SPIRAM_MALLOC_ALWAYSINTERNAL=16384
CONFIG_SPIRAM_TRY_ALLOCATE_WIFI_LWIP=y
CONFIG_SPIRAM_MALLOC_RESERVE_INTERNAL=32768
CONFIG_SPIRAM_MALLOC_RESERVE_INTERNAL=65535
# CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY is not set
# CONFIG_SPIRAM_ALLOW_NOINIT_SEG_EXTERNAL_MEMORY is not set
# end of SPI RAM config
@@ -2480,9 +2480,9 @@ CONFIG_LWIP_HOOK_IP6_INPUT_DEFAULT=y
#
# mbedTLS
#
CONFIG_MBEDTLS_INTERNAL_MEM_ALLOC=y
# CONFIG_MBEDTLS_INTERNAL_MEM_ALLOC is not set
# CONFIG_MBEDTLS_EXTERNAL_MEM_ALLOC is not set
# CONFIG_MBEDTLS_DEFAULT_MEM_ALLOC is not set
CONFIG_MBEDTLS_DEFAULT_MEM_ALLOC=y
# CONFIG_MBEDTLS_CUSTOM_MEM_ALLOC is not set
CONFIG_MBEDTLS_ASYMMETRIC_CONTENT_LEN=y
CONFIG_MBEDTLS_SSL_IN_CONTENT_LEN=16384
@@ -2646,7 +2646,7 @@ CONFIG_STDATOMIC_S32C1I_SPIRAM_WORKAROUND=y
# CONFIG_NVS_ENCRYPTION is not set
# CONFIG_NVS_ASSERT_ERROR_CHECK is not set
# CONFIG_NVS_LEGACY_DUP_KEYS_COMPATIBILITY is not set
# CONFIG_NVS_ALLOCATE_CACHE_IN_SPIRAM is not set
CONFIG_NVS_ALLOCATE_CACHE_IN_SPIRAM=y
# end of NVS
#
+20 -2
View File
@@ -109,13 +109,31 @@ config DALI_BUS_POWER_CHECK_INTERVAL_MS
power-down. This lets the HAL recover when the bus was already powered
before gateway startup and no RX edge is generated.
config DALI_BUS_FAIL_EVENT_DELAY_MS
int "Bus fail event delay ms"
range 1 60000
default 45
help
Continuous low-bus duration required before publishing the legacy FF FD
bus-abnormal raw frame for the first time. Repeat reports are controlled
separately by DALI_BUS_ABNORMAL_REPORT_INTERVAL_MS.
config DALI_BUS_ABNORMAL_REPORT_INTERVAL_MS
int "Legacy bus abnormal report interval ms"
range 0 60000
default 3000
help
Interval for publishing the legacy two-byte FF FD bus-abnormal raw frame
while the native DALI bus is power-down. Set to 0 to disable the report.
Repeat interval for publishing the legacy two-byte FF FD bus-abnormal raw
frame while the native DALI bus remains failed. Set to 0 to disable both
the first and repeated reports.
config DALI_BUS_RESET_PULSE_MS
int "Bus reset low pulse ms"
range 1 1000
default 10
help
Default duration for the native physical DALI bus reset pulse. The USB
setup bridge uses this value for short command 01 00 00.
choice DALI_LOG_LEVEL_CHOICE
prompt "DALI log level"
+9 -4
View File
@@ -45,16 +45,21 @@ Use `menuconfig` under `DALI Component` to configure:
TX/RX stop conditions, query response timeout, double-send delay, and TX queue
arbitration waits.
- TX/RX active polarity. The native gateway default is TX active low and RX active high.
- Native bus power-down polling and legacy `FF FD` bus-abnormal raw-frame reporting intervals.
- Native bus power-down polling, first bus-fail event delay, legacy `FF FD`
bus-abnormal raw-frame repeat interval, and physical bus reset pulse duration.
- Native DALI HAL log level for the `dali_hal` ESP-IDF log tag.
- Queue sizes.
- Task stack sizes and priorities.
- Optional debug task.
The native bus monitor uses `CONFIG_DALI_BUS_POWER_CHECK_INTERVAL_MS` to resample RX while
power-down and `CONFIG_DALI_BUS_ABNORMAL_REPORT_INTERVAL_MS` to publish legacy `FF FD`
raw frames while down. The report interval defaults to 3000 ms; set it to 0 to disable the
compatibility report.
power-down, `CONFIG_DALI_BUS_FAIL_EVENT_DELAY_MS` to publish the first legacy `FF FD`
raw frame after a continuous low-bus failure, and
`CONFIG_DALI_BUS_ABNORMAL_REPORT_INTERVAL_MS` for repeat reports while the bus remains
failed. The first delay defaults to 45 ms and the repeat interval defaults to 3000 ms;
set the repeat interval to 0 to disable the compatibility report. USB setup command
`01 00 00` uses `CONFIG_DALI_BUS_RESET_PULSE_MS` to drive the bus low intentionally for
a physical reset pulse, defaulting to 10 ms.
Native timing defaults target standard 1200 bps DALI: a 416.67 us half-bit period is
generated by the default 3.636363 MHz timer. `CONFIG_DALI_CUSTOM_HALF_BIT_TIME_X100_US`
+245 -18
View File
@@ -83,10 +83,18 @@
#define CONFIG_DALI_BUS_POWER_CHECK_INTERVAL_MS 500
#endif
#ifndef CONFIG_DALI_BUS_FAIL_EVENT_DELAY_MS
#define CONFIG_DALI_BUS_FAIL_EVENT_DELAY_MS 45
#endif
#ifndef CONFIG_DALI_BUS_ABNORMAL_REPORT_INTERVAL_MS
#define CONFIG_DALI_BUS_ABNORMAL_REPORT_INTERVAL_MS 3000
#endif
#ifndef CONFIG_DALI_BUS_RESET_PULSE_MS
#define CONFIG_DALI_BUS_RESET_PULSE_MS 10
#endif
#ifndef CONFIG_DALI_FORWARD_ACTIVITY_WAIT_MS
#define CONFIG_DALI_FORWARD_ACTIVITY_WAIT_MS 20
#endif
@@ -109,6 +117,7 @@
#define DALI_BAUDRATE_MIN 400U
#define DALI_BAUDRATE_MAX 2400U
#define DALI_BUS_POWER_CHECK_INTERVAL_US ((uint64_t)CONFIG_DALI_BUS_POWER_CHECK_INTERVAL_MS * 1000ULL)
#define DALI_BUS_FAIL_EVENT_DELAY_US ((uint64_t)CONFIG_DALI_BUS_FAIL_EVENT_DELAY_MS * 1000ULL)
#define DALI_BUS_ABNORMAL_REPORT_INTERVAL_US ((uint64_t)CONFIG_DALI_BUS_ABNORMAL_REPORT_INTERVAL_MS * 1000ULL)
typedef struct {
@@ -151,7 +160,10 @@ typedef struct {
uint8_t tx_level;
uint64_t bus_level_check_time;
uint64_t bus_low_since_time;
uint64_t bus_abnormal_report_time;
uint64_t bus_abnormal_suppress_until;
bool bus_fail_reported;
Dali_msg_t tx_data;
bool bus_activity_seen;
@@ -526,6 +538,48 @@ static UBaseType_t queue_waiting(QueueHandle_t queue)
return queue ? uxQueueMessagesWaiting(queue) : 0;
}
static void IRAM_ATTR reset_rx_state_from_isr(dali_bus_ctx_t *bus)
{
if (bus == NULL) {
return;
}
bus->rx_state = RX_STATE_IDLE;
bus->rx_half_bit_counter = 0;
bus->rx_data_bit_counter = 0;
bus->rx_data.status = DALI_FRAME_UNKNOWN;
bus->rx_data.length = 0;
}
static void IRAM_ATTR reset_tx_counters_from_isr(dali_bus_ctx_t *bus)
{
if (bus == NULL) {
return;
}
bus->tx_half_bit_counter = 0;
bus->tx_data_bit_counter = 0;
}
static void reset_rx_state(dali_bus_ctx_t *bus)
{
if (bus == NULL) {
return;
}
bus->rx_state = RX_STATE_IDLE;
bus->rx_half_bit_counter = 0;
bus->rx_data_bit_counter = 0;
bus->rx_data.status = DALI_FRAME_UNKNOWN;
bus->rx_data.length = 0;
}
static void reset_tx_counters(dali_bus_ctx_t *bus)
{
if (bus == NULL) {
return;
}
bus->tx_half_bit_counter = 0;
bus->tx_data_bit_counter = 0;
}
static void log_tx_message(const char *prefix, const dali_bus_ctx_t *bus,
const Dali_msg_t *msg, uint32_t timeout_ms)
{
@@ -576,11 +630,8 @@ static void recover_tx_timeout(dali_bus_ctx_t *bus)
bus->tx_data.status = DALI_FRAME_ERROR;
bus->tx_state = TX_STATE_IDLE;
bus->rx_state = RX_STATE_IDLE;
bus->tx_half_bit_counter = 0;
bus->tx_data_bit_counter = 0;
bus->rx_half_bit_counter = 0;
bus->rx_data_bit_counter = 0;
reset_rx_state(bus);
reset_tx_counters(bus);
if (bus->bus_state == DALI_BUS_TRANSMITTING || bus->bus_state == DALI_BUS_TIME_BREAK ||
bus->bus_state == DALI_BUS_RECOVERY) {
bus->tx_last_edge_time = esp_timer_get_time();
@@ -620,22 +671,82 @@ static void IRAM_ATTR publish_bus_abnormal_from_isr(dali_bus_ctx_t *bus, BaseTyp
}
}
static void IRAM_ATTR maybe_report_bus_abnormal_from_isr(dali_bus_ctx_t *bus, uint64_t time_now,
BaseType_t *yield)
static void IRAM_ATTR update_bus_low_tracking_from_isr(dali_bus_ctx_t *bus,
uint64_t time_now,
uint8_t current_level)
{
if (bus == NULL || DALI_BUS_ABNORMAL_REPORT_INTERVAL_US == 0) {
if (bus == NULL) {
return;
}
if (!interval_elapsed_us(time_now, bus->bus_abnormal_report_time,
DALI_BUS_ABNORMAL_REPORT_INTERVAL_US)) {
if (current_level == 0) {
if (bus->bus_low_since_time == 0) {
bus->bus_low_since_time = time_now;
}
return;
}
publish_bus_abnormal_from_isr(bus, yield);
bus->bus_abnormal_report_time = time_now;
bus->bus_low_since_time = 0;
bus->bus_fail_reported = false;
bus->bus_abnormal_report_time = 0;
bus->bus_abnormal_suppress_until = 0;
}
static void IRAM_ATTR poll_power_down_bus_from_isr(dali_bus_ctx_t *bus, uint64_t time_now,
static void IRAM_ATTR maybe_report_low_bus_abnormal_from_isr(dali_bus_ctx_t *bus,
uint64_t time_now,
uint8_t current_level,
BaseType_t *yield)
{
if (bus == NULL || DALI_BUS_ABNORMAL_REPORT_INTERVAL_US == 0 || current_level != 0 ||
bus->bus_low_since_time == 0) {
return;
}
if (bus->bus_abnormal_suppress_until != 0 && time_now < bus->bus_abnormal_suppress_until) {
return;
}
if ((time_now - bus->bus_low_since_time) < DALI_BUS_FAIL_EVENT_DELAY_US) {
return;
}
if (!bus->bus_fail_reported) {
publish_bus_abnormal_from_isr(bus, yield);
bus->bus_fail_reported = true;
bus->bus_abnormal_report_time = time_now;
return;
}
if (interval_elapsed_us(time_now, bus->bus_abnormal_report_time,
DALI_BUS_ABNORMAL_REPORT_INTERVAL_US)) {
publish_bus_abnormal_from_isr(bus, yield);
bus->bus_abnormal_report_time = time_now;
}
}
static void IRAM_ATTR resample_stale_bus_level_from_isr(dali_bus_ctx_t *bus,
uint64_t time_now,
uint32_t rx_delta,
uint8_t current_level)
{
if (bus == NULL || current_level == bus->rx_level) {
return;
}
bool should_resample = bus->bus_state == DALI_BUS_POWER_DOWN ||
bus->bus_state <= DALI_BUS_ERROR ||
(bus->bus_state == DALI_BUS_READY &&
(bus->rx_state != RX_STATE_IDLE || bus->rx_level == 0) &&
rx_delta > s_timing.rx_hb_max) ||
(bus->bus_state == DALI_BUS_RECEIVING &&
bus->rx_state == RX_STATE_START &&
rx_delta > s_timing.rx_hb_max);
if (!should_resample) {
return;
}
bus->rx_level = current_level;
bus->rx_last_edge_time = time_now;
bus->bus_activity_seen = true;
}
static void IRAM_ATTR poll_power_down_bus_from_isr(dali_bus_ctx_t *bus, uint64_t time_now)
{
if (bus == NULL || bus->bus_state != DALI_BUS_POWER_DOWN) {
return;
@@ -650,8 +761,6 @@ static void IRAM_ATTR poll_power_down_bus_from_isr(dali_bus_ctx_t *bus, uint64_t
bus->rx_last_edge_time = time_now;
}
}
maybe_report_bus_abnormal_from_isr(bus, time_now, yield);
}
static inline void publish_rx_frame_from_isr(Dali_msg_t *msg, QueueHandle_t queue, BaseType_t *yield)
@@ -884,9 +993,20 @@ static bool IRAM_ATTR handle_bus_timer(dali_bus_ctx_t *bus, uint64_t time_now)
bus->tx_last_edge_time = time_now - MAX_DELTA_RELOAD_TIME/2; // half of max time
}
poll_power_down_bus_from_isr(bus, time_now, &yield);
uint8_t current_level = DALI_GET_BUS_LEVEL(bus);
update_bus_low_tracking_from_isr(bus, time_now, current_level);
resample_stale_bus_level_from_isr(bus, time_now, rx_delta, current_level);
poll_power_down_bus_from_isr(bus, time_now);
rx_delta = time_now - bus->rx_last_edge_time;
tx_delta = time_now - bus->tx_last_edge_time;
current_level = DALI_GET_BUS_LEVEL(bus);
update_bus_low_tracking_from_isr(bus, time_now, current_level);
maybe_report_low_bus_abnormal_from_isr(bus, time_now, current_level, &yield);
if (bus->bus_state == DALI_BUS_READY && bus->rx_state != RX_STATE_IDLE &&
rx_delta > s_timing.rx_hb_max) {
reset_rx_state_from_isr(bus);
}
if (bus->bus_state == DALI_BUS_TRANSMITTING && bus->tx_state == TX_STATE_STOP &&
DALI_GET_TX_LEVEL(bus) == 1 &&
@@ -901,18 +1021,21 @@ static bool IRAM_ATTR handle_bus_timer(dali_bus_ctx_t *bus, uint64_t time_now)
{ // 101.8.2.4 - startup BUS after 2.4ms
if(bus->rx_level==1 && rx_delta > s_timing.rx_stop_cond)
{
DALI_SET_BUS_HIGH(bus);
reset_rx_state_from_isr(bus);
reset_tx_counters_from_isr(bus);
bus->bus_state = DALI_BUS_READY; // bus is ready
}
}
// if bus power down - if bus is low for more then 45ms
if(bus->rx_level==0 && rx_delta > s_timing.time_bus_down)
if(current_level == 0 && bus->bus_low_since_time != 0 &&
(time_now - bus->bus_low_since_time) > s_timing.time_bus_down)
{ // power lost
bool entered_power_down = bus->bus_state != DALI_BUS_POWER_DOWN;
bus->bus_state = DALI_BUS_POWER_DOWN; // bus is power down - recovery see previous if
DALI_SET_BUS_HIGH(bus); // make sure TX is high
if (entered_power_down) {
bus->bus_level_check_time = time_now;
bus->bus_abnormal_report_time = time_now;
}
}
@@ -940,6 +1063,8 @@ static bool IRAM_ATTR handle_bus_timer(dali_bus_ctx_t *bus, uint64_t time_now)
}
else if(bus->bus_state == DALI_BUS_RECOVERY && rx_delta > s_timing.time_recovery_min)
{
reset_rx_state_from_isr(bus);
reset_tx_counters_from_isr(bus);
bus->bus_state = DALI_BUS_READY; // bus is ready
// immediately start transmitting if we have data
}
@@ -1025,6 +1150,7 @@ static bool IRAM_ATTR handle_bus_timer(dali_bus_ctx_t *bus, uint64_t time_now)
xQueueSendToBackFromISR(bus->tx_reply_queue, &bus->tx_data, &yield); // send data to queue
}
bus->tx_state = TX_STATE_IDLE; // clear state
reset_tx_counters_from_isr(bus);
}
// recover receiving
@@ -1280,7 +1406,10 @@ static esp_err_t init_bus(uint8_t bus_id, uint8_t tx_pin, uint8_t rx_pin)
bus->rx_level = DALI_GET_BUS_LEVEL(bus); // get level of RX pin
bus->tx_last_edge_time = bus->rx_last_edge_time;
bus->bus_level_check_time = bus->rx_last_edge_time;
bus->bus_low_since_time = bus->rx_level == 0 ? bus->rx_last_edge_time : 0;
bus->bus_abnormal_report_time = 0;
bus->bus_abnormal_suppress_until = 0;
bus->bus_fail_reported = false;
bus->bus_activity_seen = false;
bus->rx_last_frame_time = 0;
bus->rx_last_frame_length = 0;
@@ -1513,6 +1642,104 @@ esp_err_t dali_hal_get_bus_info(uint8_t bus_id, dali_hal_bus_info_t *info)
return ESP_OK;
}
esp_err_t dali_hal_pulse_bus_low(uint8_t bus_id, uint32_t duration_ms)
{
if (bus_id >= DALI_PHY_COUNT) {
return ESP_ERR_INVALID_ARG;
}
if (duration_ms == 0) {
duration_ms = CONFIG_DALI_BUS_RESET_PULSE_MS;
}
dali_hal_lock();
esp_err_t err = ensure_timing_ready_locked();
if (err != ESP_OK) {
dali_hal_unlock();
return err;
}
dali_bus_ctx_t *bus = &s_bus[bus_id];
if (!bus->inited) {
dali_hal_unlock();
return ESP_ERR_INVALID_STATE;
}
const uint64_t start_time = esp_timer_get_time();
const uint64_t duration_us = (uint64_t)duration_ms * 1000ULL;
const bool had_tx = bus->tx_state > TX_STATE_IDLE || queue_waiting(bus->tx_queue) > 0;
Dali_msg_t failed_tx = bus->tx_data;
failed_tx.status = DALI_FRAME_ERROR;
err = gpio_intr_disable(bus->rx_pin);
if (err != ESP_OK) {
dali_hal_unlock();
return err;
}
if (bus->tx_queue) {
xQueueReset(bus->tx_queue);
}
if (bus->tx_reply_queue) {
xQueueReset(bus->tx_reply_queue);
if (had_tx && !is_backward_tx_msg(&failed_tx)) {
xQueueSendToBack(bus->tx_reply_queue, &failed_tx, 0);
}
}
bus->force_backward_tx = false;
bus->tx_state = TX_STATE_IDLE;
bus->tx_data.status = DALI_FRAME_ERROR;
reset_rx_state(bus);
reset_tx_counters(bus);
bus->bus_activity_seen = true;
bus->bus_state = DALI_BUS_POWER_DOWN;
bus->bus_level_check_time = start_time;
bus->bus_abnormal_report_time = 0;
bus->bus_fail_reported = false;
bus->bus_abnormal_suppress_until =
start_time + duration_us + DALI_BUS_FAIL_EVENT_DELAY_US + s_timing.rx_stop_cond;
DALI_SET_BUS_LOW(bus);
bus->rx_level = DALI_GET_BUS_LEVEL(bus);
bus->rx_last_edge_time = start_time;
bus->tx_last_edge_time = start_time;
bus->bus_low_since_time = bus->rx_level == 0 ? start_time : 0;
dali_hal_unlock();
TickType_t delay_ticks = pdMS_TO_TICKS(duration_ms);
if (delay_ticks == 0) {
delay_ticks = 1;
}
vTaskDelay(delay_ticks);
dali_hal_lock();
const uint64_t end_time = esp_timer_get_time();
DALI_SET_BUS_HIGH(bus);
bus->rx_level = DALI_GET_BUS_LEVEL(bus);
bus->rx_last_edge_time = end_time;
bus->tx_last_edge_time = end_time;
bus->bus_level_check_time = end_time;
bus->bus_low_since_time = bus->rx_level == 0 ? end_time : 0;
bus->bus_abnormal_report_time = 0;
bus->bus_fail_reported = false;
if (bus->rx_level == 1) {
bus->bus_abnormal_suppress_until = 0;
bus->bus_state = DALI_BUS_READY;
} else {
bus->bus_abnormal_suppress_until =
end_time + DALI_BUS_FAIL_EVENT_DELAY_US + s_timing.rx_stop_cond;
bus->bus_state = DALI_BUS_POWER_DOWN;
}
bus->tx_state = TX_STATE_IDLE;
reset_rx_state(bus);
reset_tx_counters(bus);
gpio_intr_enable(bus->rx_pin);
dali_hal_unlock();
ESP_LOGI(TAG, "bus=%u physical reset pulse complete durationMs=%lu", bus_id,
(unsigned long)duration_ms);
return ESP_OK;
}
QueueHandle_t dali_hal_raw_receive_queue(void)
{
ensure_common_queues();
+1 -1
View File
@@ -238,10 +238,10 @@ esp_err_t dali_hal_set_baudrate(uint32_t baudrate);
uint32_t dali_hal_get_baudrate(void);
size_t dali_hal_get_inited_buses(uint8_t *ids, size_t max_ids);
esp_err_t dali_hal_get_bus_info(uint8_t bus_id, dali_hal_bus_info_t *info);
esp_err_t dali_hal_pulse_bus_low(uint8_t bus_id, uint32_t duration_ms);
QueueHandle_t dali_hal_raw_receive_queue(void);
void dali_task(void *pvParameters);
#ifdef __cplusplus
}
#endif
@@ -129,6 +129,7 @@ class DaliDomainService {
void addRawFrameSink(std::function<void(const DaliRawFrame& frame)> sink);
bool resetBus(uint8_t gateway_id) const;
bool pulseBusLow(uint8_t gateway_id, uint32_t duration_ms) const;
bool isBusIdle(uint8_t gateway_id, uint32_t quiet_ms) const;
void markHostActivity(uint8_t gateway_id) const;
void markHostCommandFrame(uint8_t gateway_id, uint8_t raw_addr, uint8_t command) const;
+15 -2
View File
@@ -305,6 +305,7 @@ std::vector<uint8_t> TransactHardwareFrame(uint8_t bus_id, const uint8_t* data,
switch (data[0]) {
case 0x00:
ESP_LOGD(TAG, "received reset for bus=%u", bus_id);
return {1};
case 0x01:
return {1};
case 0x10:
@@ -650,8 +651,11 @@ std::vector<DaliChannelInfo> DaliDomainService::channelInfo() const {
std::vector<DaliChannelInfo> info;
info.reserve(channels_.size());
for (const auto& channel : channels_) {
DaliChannelInfo item{channel->config.channel_index, channel->config.gateway_id,
channel->phy_kind, channel->config.name};
DaliChannelInfo item;
item.channel_index = channel->config.channel_index;
item.gateway_id = channel->config.gateway_id;
item.phy_kind = channel->phy_kind;
item.name = channel->config.name;
if (channel->hardware_bus.has_value()) {
item.native_bus_id = channel->hardware_bus->bus_id;
}
@@ -707,6 +711,15 @@ bool DaliDomainService::resetBus(uint8_t gateway_id) const {
return channel->comm->resetBus();
}
bool DaliDomainService::pulseBusLow(uint8_t gateway_id, uint32_t duration_ms) const {
const auto* channel = findChannelByGateway(gateway_id);
if (channel == nullptr || !channel->hardware_bus.has_value()) {
return false;
}
markBusActivity(gateway_id);
return dali_hal_pulse_bus_low(channel->hardware_bus->bus_id, duration_ms) == ESP_OK;
}
bool DaliDomainService::isBusIdle(uint8_t gateway_id, uint32_t quiet_ms) const {
TickType_t last_activity = 0;
if (bus_activity_lock_ != nullptr) {
@@ -20,6 +20,7 @@ struct GatewayUsbSetupBridgeConfig {
size_t tx_buffer_size{256};
uint32_t read_timeout_ms{20};
uint32_t write_timeout_ms{20};
uint32_t reset_pulse_ms{10};
uint32_t task_stack_size{4096};
UBaseType_t task_priority{4};
};
@@ -89,6 +89,22 @@ void GatewayUsbSetupBridge::handleBytes(const uint8_t* data, size_t len) {
}
const uint8_t gateway_id = setupGatewayId();
if (len == 3 && data[0] == 0x01 && data[1] == 0x00 && data[2] == 0x00) {
const bool ok = dali_domain_.pulseBusLow(gateway_id, config_.reset_pulse_ms);
const uint8_t response[2] = {static_cast<uint8_t>(ok ? 0x01 : 0xFD), 0x00};
const int written = usb_serial_jtag_write_bytes(response, sizeof(response),
pdMS_TO_TICKS(config_.write_timeout_ms));
if (written < 0 || static_cast<size_t>(written) != sizeof(response)) {
ESP_LOGW(kTag, "failed to write USB bus reset response channel=%u ok=%u",
config_.channel_index, ok ? 1 : 0);
}
if (!ok) {
ESP_LOGW(kTag, "failed to pulse DALI bus low for USB reset channel=%u gateway=%u",
config_.channel_index, gateway_id);
}
return;
}
if (data[0] == 0x12) {
const auto response = dali_domain_.transactBridgeFrame(gateway_id, data, len);
if (!response.empty()) {