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:
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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"
|
||||
|
||||
@@ -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`
|
||||
|
||||
@@ -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,
|
||||
BaseType_t *yield)
|
||||
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();
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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};
|
||||
};
|
||||
@@ -45,4 +46,4 @@ class GatewayUsbSetupBridge {
|
||||
bool started_{false};
|
||||
};
|
||||
|
||||
} // namespace gateway
|
||||
} // namespace gateway
|
||||
|
||||
@@ -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()) {
|
||||
@@ -131,4 +147,4 @@ uint8_t GatewayUsbSetupBridge::setupGatewayId() const {
|
||||
return config_.channel_index;
|
||||
}
|
||||
|
||||
} // namespace gateway
|
||||
} // namespace gateway
|
||||
|
||||
Reference in New Issue
Block a user