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
|
#define CONFIG_GATEWAY_USB_SETUP_READ_TIMEOUT_MS 20
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef CONFIG_DALI_BUS_RESET_PULSE_MS
|
||||||
|
#define CONFIG_DALI_BUS_RESET_PULSE_MS 10
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifndef CONFIG_GATEWAY_485_CONTROL_BAUDRATE
|
#ifndef CONFIG_GATEWAY_485_CONTROL_BAUDRATE
|
||||||
#define CONFIG_GATEWAY_485_CONTROL_BAUDRATE 9600
|
#define CONFIG_GATEWAY_485_CONTROL_BAUDRATE 9600
|
||||||
#endif
|
#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.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.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.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_usb_setup_bridge = std::make_unique<gateway::GatewayUsbSetupBridge>(*s_controller,
|
||||||
*s_dali_domain,
|
*s_dali_domain,
|
||||||
usb_config);
|
usb_config);
|
||||||
|
|||||||
@@ -2919,7 +2919,7 @@ CONFIG_DALI_CUSTOM_HALF_BIT_TIME_X100_US=0
|
|||||||
CONFIG_DALI_TX_STOP_CONDITION_US=0
|
CONFIG_DALI_TX_STOP_CONDITION_US=0
|
||||||
CONFIG_DALI_RX_STOP_CONDITION_US=0
|
CONFIG_DALI_RX_STOP_CONDITION_US=0
|
||||||
CONFIG_DALI_QUERY_RESPONSE_TIMEOUT_MS=30
|
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_ACTIVITY_WAIT_MS=20
|
||||||
CONFIG_DALI_FORWARD_AFTER_BACKWARD_WAIT_MS=10
|
CONFIG_DALI_FORWARD_AFTER_BACKWARD_WAIT_MS=10
|
||||||
CONFIG_DALI_FORWARD_MAX_WAIT_MS=50
|
CONFIG_DALI_FORWARD_MAX_WAIT_MS=50
|
||||||
|
|||||||
@@ -1861,7 +1861,7 @@ CONFIG_SPIRAM_USE_MALLOC=y
|
|||||||
CONFIG_SPIRAM_MEMTEST=y
|
CONFIG_SPIRAM_MEMTEST=y
|
||||||
CONFIG_SPIRAM_MALLOC_ALWAYSINTERNAL=16384
|
CONFIG_SPIRAM_MALLOC_ALWAYSINTERNAL=16384
|
||||||
CONFIG_SPIRAM_TRY_ALLOCATE_WIFI_LWIP=y
|
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_BSS_SEG_EXTERNAL_MEMORY is not set
|
||||||
# CONFIG_SPIRAM_ALLOW_NOINIT_SEG_EXTERNAL_MEMORY is not set
|
# CONFIG_SPIRAM_ALLOW_NOINIT_SEG_EXTERNAL_MEMORY is not set
|
||||||
# end of SPI RAM config
|
# end of SPI RAM config
|
||||||
@@ -2480,9 +2480,9 @@ CONFIG_LWIP_HOOK_IP6_INPUT_DEFAULT=y
|
|||||||
#
|
#
|
||||||
# mbedTLS
|
# 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_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_CUSTOM_MEM_ALLOC is not set
|
||||||
CONFIG_MBEDTLS_ASYMMETRIC_CONTENT_LEN=y
|
CONFIG_MBEDTLS_ASYMMETRIC_CONTENT_LEN=y
|
||||||
CONFIG_MBEDTLS_SSL_IN_CONTENT_LEN=16384
|
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_ENCRYPTION is not set
|
||||||
# CONFIG_NVS_ASSERT_ERROR_CHECK is not set
|
# CONFIG_NVS_ASSERT_ERROR_CHECK is not set
|
||||||
# CONFIG_NVS_LEGACY_DUP_KEYS_COMPATIBILITY 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
|
# 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
|
power-down. This lets the HAL recover when the bus was already powered
|
||||||
before gateway startup and no RX edge is generated.
|
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
|
config DALI_BUS_ABNORMAL_REPORT_INTERVAL_MS
|
||||||
int "Legacy bus abnormal report interval ms"
|
int "Legacy bus abnormal report interval ms"
|
||||||
range 0 60000
|
range 0 60000
|
||||||
default 3000
|
default 3000
|
||||||
help
|
help
|
||||||
Interval for publishing the legacy two-byte FF FD bus-abnormal raw frame
|
Repeat interval for publishing the legacy two-byte FF FD bus-abnormal raw
|
||||||
while the native DALI bus is power-down. Set to 0 to disable the report.
|
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
|
choice DALI_LOG_LEVEL_CHOICE
|
||||||
prompt "DALI log level"
|
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
|
TX/RX stop conditions, query response timeout, double-send delay, and TX queue
|
||||||
arbitration waits.
|
arbitration waits.
|
||||||
- TX/RX active polarity. The native gateway default is TX active low and RX active high.
|
- 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.
|
- Native DALI HAL log level for the `dali_hal` ESP-IDF log tag.
|
||||||
- Queue sizes.
|
- Queue sizes.
|
||||||
- Task stack sizes and priorities.
|
- Task stack sizes and priorities.
|
||||||
- Optional debug task.
|
- Optional debug task.
|
||||||
|
|
||||||
The native bus monitor uses `CONFIG_DALI_BUS_POWER_CHECK_INTERVAL_MS` to resample RX while
|
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`
|
power-down, `CONFIG_DALI_BUS_FAIL_EVENT_DELAY_MS` to publish the first legacy `FF FD`
|
||||||
raw frames while down. The report interval defaults to 3000 ms; set it to 0 to disable the
|
raw frame after a continuous low-bus failure, and
|
||||||
compatibility report.
|
`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
|
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`
|
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
|
#define CONFIG_DALI_BUS_POWER_CHECK_INTERVAL_MS 500
|
||||||
#endif
|
#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
|
#ifndef CONFIG_DALI_BUS_ABNORMAL_REPORT_INTERVAL_MS
|
||||||
#define CONFIG_DALI_BUS_ABNORMAL_REPORT_INTERVAL_MS 3000
|
#define CONFIG_DALI_BUS_ABNORMAL_REPORT_INTERVAL_MS 3000
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef CONFIG_DALI_BUS_RESET_PULSE_MS
|
||||||
|
#define CONFIG_DALI_BUS_RESET_PULSE_MS 10
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifndef CONFIG_DALI_FORWARD_ACTIVITY_WAIT_MS
|
#ifndef CONFIG_DALI_FORWARD_ACTIVITY_WAIT_MS
|
||||||
#define CONFIG_DALI_FORWARD_ACTIVITY_WAIT_MS 20
|
#define CONFIG_DALI_FORWARD_ACTIVITY_WAIT_MS 20
|
||||||
#endif
|
#endif
|
||||||
@@ -109,6 +117,7 @@
|
|||||||
#define DALI_BAUDRATE_MIN 400U
|
#define DALI_BAUDRATE_MIN 400U
|
||||||
#define DALI_BAUDRATE_MAX 2400U
|
#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_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)
|
#define DALI_BUS_ABNORMAL_REPORT_INTERVAL_US ((uint64_t)CONFIG_DALI_BUS_ABNORMAL_REPORT_INTERVAL_MS * 1000ULL)
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
@@ -151,7 +160,10 @@ typedef struct {
|
|||||||
uint8_t tx_level;
|
uint8_t tx_level;
|
||||||
|
|
||||||
uint64_t bus_level_check_time;
|
uint64_t bus_level_check_time;
|
||||||
|
uint64_t bus_low_since_time;
|
||||||
uint64_t bus_abnormal_report_time;
|
uint64_t bus_abnormal_report_time;
|
||||||
|
uint64_t bus_abnormal_suppress_until;
|
||||||
|
bool bus_fail_reported;
|
||||||
|
|
||||||
Dali_msg_t tx_data;
|
Dali_msg_t tx_data;
|
||||||
bool bus_activity_seen;
|
bool bus_activity_seen;
|
||||||
@@ -526,6 +538,48 @@ static UBaseType_t queue_waiting(QueueHandle_t queue)
|
|||||||
return queue ? uxQueueMessagesWaiting(queue) : 0;
|
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,
|
static void log_tx_message(const char *prefix, const dali_bus_ctx_t *bus,
|
||||||
const Dali_msg_t *msg, uint32_t timeout_ms)
|
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_data.status = DALI_FRAME_ERROR;
|
||||||
bus->tx_state = TX_STATE_IDLE;
|
bus->tx_state = TX_STATE_IDLE;
|
||||||
bus->rx_state = RX_STATE_IDLE;
|
reset_rx_state(bus);
|
||||||
bus->tx_half_bit_counter = 0;
|
reset_tx_counters(bus);
|
||||||
bus->tx_data_bit_counter = 0;
|
|
||||||
bus->rx_half_bit_counter = 0;
|
|
||||||
bus->rx_data_bit_counter = 0;
|
|
||||||
if (bus->bus_state == DALI_BUS_TRANSMITTING || bus->bus_state == DALI_BUS_TIME_BREAK ||
|
if (bus->bus_state == DALI_BUS_TRANSMITTING || bus->bus_state == DALI_BUS_TIME_BREAK ||
|
||||||
bus->bus_state == DALI_BUS_RECOVERY) {
|
bus->bus_state == DALI_BUS_RECOVERY) {
|
||||||
bus->tx_last_edge_time = esp_timer_get_time();
|
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,
|
static void IRAM_ATTR update_bus_low_tracking_from_isr(dali_bus_ctx_t *bus,
|
||||||
BaseType_t *yield)
|
uint64_t time_now,
|
||||||
|
uint8_t current_level)
|
||||||
{
|
{
|
||||||
if (bus == NULL || DALI_BUS_ABNORMAL_REPORT_INTERVAL_US == 0) {
|
if (bus == NULL) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!interval_elapsed_us(time_now, bus->bus_abnormal_report_time,
|
if (current_level == 0) {
|
||||||
DALI_BUS_ABNORMAL_REPORT_INTERVAL_US)) {
|
if (bus->bus_low_since_time == 0) {
|
||||||
|
bus->bus_low_since_time = time_now;
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
publish_bus_abnormal_from_isr(bus, yield);
|
bus->bus_low_since_time = 0;
|
||||||
bus->bus_abnormal_report_time = time_now;
|
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)
|
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) {
|
if (bus == NULL || bus->bus_state != DALI_BUS_POWER_DOWN) {
|
||||||
return;
|
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;
|
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)
|
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
|
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;
|
rx_delta = time_now - bus->rx_last_edge_time;
|
||||||
tx_delta = time_now - bus->tx_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 &&
|
if (bus->bus_state == DALI_BUS_TRANSMITTING && bus->tx_state == TX_STATE_STOP &&
|
||||||
DALI_GET_TX_LEVEL(bus) == 1 &&
|
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
|
{ // 101.8.2.4 - startup BUS after 2.4ms
|
||||||
if(bus->rx_level==1 && rx_delta > s_timing.rx_stop_cond)
|
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
|
bus->bus_state = DALI_BUS_READY; // bus is ready
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// if bus power down - if bus is low for more then 45ms
|
// 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
|
{ // power lost
|
||||||
bool entered_power_down = bus->bus_state != DALI_BUS_POWER_DOWN;
|
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
|
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
|
DALI_SET_BUS_HIGH(bus); // make sure TX is high
|
||||||
if (entered_power_down) {
|
if (entered_power_down) {
|
||||||
bus->bus_level_check_time = time_now;
|
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)
|
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
|
bus->bus_state = DALI_BUS_READY; // bus is ready
|
||||||
// immediately start transmitting if we have data
|
// 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
|
xQueueSendToBackFromISR(bus->tx_reply_queue, &bus->tx_data, &yield); // send data to queue
|
||||||
}
|
}
|
||||||
bus->tx_state = TX_STATE_IDLE; // clear state
|
bus->tx_state = TX_STATE_IDLE; // clear state
|
||||||
|
reset_tx_counters_from_isr(bus);
|
||||||
}
|
}
|
||||||
|
|
||||||
// recover receiving
|
// 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->rx_level = DALI_GET_BUS_LEVEL(bus); // get level of RX pin
|
||||||
bus->tx_last_edge_time = bus->rx_last_edge_time;
|
bus->tx_last_edge_time = bus->rx_last_edge_time;
|
||||||
bus->bus_level_check_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_report_time = 0;
|
||||||
|
bus->bus_abnormal_suppress_until = 0;
|
||||||
|
bus->bus_fail_reported = false;
|
||||||
bus->bus_activity_seen = false;
|
bus->bus_activity_seen = false;
|
||||||
bus->rx_last_frame_time = 0;
|
bus->rx_last_frame_time = 0;
|
||||||
bus->rx_last_frame_length = 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;
|
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)
|
QueueHandle_t dali_hal_raw_receive_queue(void)
|
||||||
{
|
{
|
||||||
ensure_common_queues();
|
ensure_common_queues();
|
||||||
|
|||||||
@@ -238,10 +238,10 @@ esp_err_t dali_hal_set_baudrate(uint32_t baudrate);
|
|||||||
uint32_t dali_hal_get_baudrate(void);
|
uint32_t dali_hal_get_baudrate(void);
|
||||||
size_t dali_hal_get_inited_buses(uint8_t *ids, size_t max_ids);
|
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_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);
|
QueueHandle_t dali_hal_raw_receive_queue(void);
|
||||||
void dali_task(void *pvParameters);
|
void dali_task(void *pvParameters);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
@@ -129,6 +129,7 @@ class DaliDomainService {
|
|||||||
void addRawFrameSink(std::function<void(const DaliRawFrame& frame)> sink);
|
void addRawFrameSink(std::function<void(const DaliRawFrame& frame)> sink);
|
||||||
|
|
||||||
bool resetBus(uint8_t gateway_id) const;
|
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;
|
bool isBusIdle(uint8_t gateway_id, uint32_t quiet_ms) const;
|
||||||
void markHostActivity(uint8_t gateway_id) const;
|
void markHostActivity(uint8_t gateway_id) const;
|
||||||
void markHostCommandFrame(uint8_t gateway_id, uint8_t raw_addr, uint8_t command) 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]) {
|
switch (data[0]) {
|
||||||
case 0x00:
|
case 0x00:
|
||||||
ESP_LOGD(TAG, "received reset for bus=%u", bus_id);
|
ESP_LOGD(TAG, "received reset for bus=%u", bus_id);
|
||||||
|
return {1};
|
||||||
case 0x01:
|
case 0x01:
|
||||||
return {1};
|
return {1};
|
||||||
case 0x10:
|
case 0x10:
|
||||||
@@ -650,8 +651,11 @@ std::vector<DaliChannelInfo> DaliDomainService::channelInfo() const {
|
|||||||
std::vector<DaliChannelInfo> info;
|
std::vector<DaliChannelInfo> info;
|
||||||
info.reserve(channels_.size());
|
info.reserve(channels_.size());
|
||||||
for (const auto& channel : channels_) {
|
for (const auto& channel : channels_) {
|
||||||
DaliChannelInfo item{channel->config.channel_index, channel->config.gateway_id,
|
DaliChannelInfo item;
|
||||||
channel->phy_kind, channel->config.name};
|
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()) {
|
if (channel->hardware_bus.has_value()) {
|
||||||
item.native_bus_id = channel->hardware_bus->bus_id;
|
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();
|
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 {
|
bool DaliDomainService::isBusIdle(uint8_t gateway_id, uint32_t quiet_ms) const {
|
||||||
TickType_t last_activity = 0;
|
TickType_t last_activity = 0;
|
||||||
if (bus_activity_lock_ != nullptr) {
|
if (bus_activity_lock_ != nullptr) {
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ struct GatewayUsbSetupBridgeConfig {
|
|||||||
size_t tx_buffer_size{256};
|
size_t tx_buffer_size{256};
|
||||||
uint32_t read_timeout_ms{20};
|
uint32_t read_timeout_ms{20};
|
||||||
uint32_t write_timeout_ms{20};
|
uint32_t write_timeout_ms{20};
|
||||||
|
uint32_t reset_pulse_ms{10};
|
||||||
uint32_t task_stack_size{4096};
|
uint32_t task_stack_size{4096};
|
||||||
UBaseType_t task_priority{4};
|
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();
|
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) {
|
if (data[0] == 0x12) {
|
||||||
const auto response = dali_domain_.transactBridgeFrame(gateway_id, data, len);
|
const auto response = dali_domain_.transactBridgeFrame(gateway_id, data, len);
|
||||||
if (!response.empty()) {
|
if (!response.empty()) {
|
||||||
|
|||||||
Reference in New Issue
Block a user