Если ваш вопрос не влез ни в одну из вышеперечисленных тем, вам сюда.
Ответить

CH32V103 пропуск точек останова

Сб июн 17, 2023 17:13:29

Всем привет!

Пытаюсь сделать прошивку для приема и обработки DMX посылок, а также обработку RDM-команд.
Адаптировал библиотеку под CH32V, пытаюсь отловить баги с помощью wch-linke.
Замечаю, что некоторые точки останова отладчик пропускает, что бы я ни делал: перекомпиляция проекта, перезаливка, установка/снятие наживую, перезапуск mounriver studio - ничего из этого не помогало. И есть подозрение, что CH32V пропускает некоторые из команд.

Прошу помощи

Код под спойлером
Спойлерmain.c
Код:
...
void dmx_rdm_usart_enable_tx_interrupts() {
    USART2->STATR = 0x00C0;
    USART_ITConfig(DMX_RDM_USART_USED, USART_IT_TC, ENABLE);
}

// Вот эту функцию вызывает и точка останова работает
void dmx_rdm_usart_disable_tx_interrupts() {
    USART2->STATR = 0x00C0;
    USART_ITConfig(DMX_RDM_USART_USED, USART_IT_TC, DISABLE);
}

void dmx_rdm_usart_enable_rx_interrupts() {
    USART2->STATR = 0x00C0;
    USART_ITConfig(DMX_RDM_USART_USED, USART_IT_RXNE | USART_IT_FE, ENABLE);    // <-- А вот здесь точка останова не работает
}

void dmx_rdm_usart_disable_rx_interrupts() {
    USART2->STATR = 0x00C0;
    USART_ITConfig(DMX_RDM_USART_USED, USART_IT_RXNE | USART_IT_FE, DISABLE);
}

...
    set_disable_usart_tx_interrupts_cb(dmx_rdm_usart_disable_tx_interrupts);
    set_disable_usart_rx_interrupts_cb(dmx_rdm_usart_disable_rx_interrupts);
    set_enable_usart_tx_interrupts_cb(dmx_rdm_usart_enable_tx_interrupts);
    set_enable_usart_rx_interrupts_cb(dmx_rdm_usart_enable_rx_interrupts);
    set_enable_usart_cb(DMX2PWM_RS485_Enable);
    set_disable_usart_cb(DMX2PWM_RS485_Disable);
    set_save_dmx_start_address_cb((void *)dmx_rdm_save_device_label);
    set_save_device_label_cb((void *)dmx_rdm_save_dmx_start_address);

    DMX2PWM_RS485_Interrupts_Init();

    dmx_rdm_init(&rdmInit, processCommand, NULL, DMX_RDM_USART_USED, DMX_RDM_DIRECTION_GPIO_PORT, DMX_RDM_DIRECTION_GPIO_PIN, 0, 1);
...


Функции, вызываемые при dmx_rdm_init
Код:
void set_dmx_rdm_mode(uint8_t is_rdm, uint16_t usart_rx_tx_mode) {
    // In RDM mode set SERIAL_8E1 mode with 45500 baud
    if (is_rdm == true) {
        USART_SetBaudRate(_USARTx, BREAKSPEED);
        USART_SetCommunicationProperties(_USARTx, USART_Mode_Tx, USART_WordLength_8b, USART_StopBits_1, USART_HardwareFlowControl_None, USART_Parity_Even);
    }
    // Otherwise set in into SERIAL_8N2 mode with 250000 baud
    else {
        USART_SetBaudRate(_USARTx, DMXSPEED);
        USART_SetCommunicationProperties(_USARTx, USART_Mode_Tx, USART_WordLength_8b, USART_StopBits_2, USART_HardwareFlowControl_None, USART_Parity_No);
    }
}

void set_usart_tx(uint8_t is_rdm) {
    if (disable_usart) disable_usart();
    if (disable_usart_rx_interrupts) disable_usart_rx_interrupts();
    if (enable_usart_tx_interrupts) enable_usart_tx_interrupts();
    set_dmx_rdm_mode(is_rdm, USART_Mode_Tx);
    if (enable_usart) enable_usart();
}

void set_usart_rx(uint8_t is_rdm) {
    if (disable_usart) disable_usart();
    if (disable_usart_tx_interrupts) disable_usart_tx_interrupts();
    if (enable_usart_rx_interrupts) enable_usart_rx_interrupts();
    set_dmx_rdm_mode(is_rdm, USART_Mode_Rx);
    if (enable_usart) enable_usart();
}


Соответственно, во время приема не вызывается (по крайней мере, не отрабатывает точка останова) в обработчике прерывания
Код:

#if defined(DMX_USART1)
void USART1_IRQHandler(void) __attribute__((interrupt("WCH-Interrupt-fast")));
#elif defined(DMX_USART2)
void USART2_IRQHandler(void) __attribute__((interrupt("WCH-Interrupt-fast")));
#elif defined(DMX_USART3)
void USART3_IRQHandler(void) __attribute__((interrupt("WCH-Interrupt-fast")));
#endif
...
#ifdef DMX_USART1
void USART1_IRQHandler(void)
#elif defined(DMX_USART2)
void USART2_IRQHandler(void)
#elif defined(DMX_USART3)
void USART3_IRQHandler(void)
#endif
{
    if(USART_GetITStatus(DMX_RDM_USART_USED, USART_IT_RXNE | USART_IT_FE) != RESET)
    {
        dmx_rdm_on_usart_rx_interrupt();
        symbols++;
    }

    if (USART_GetITStatus(DMX_RDM_USART_USED, USART_IT_TC) != RESET) {
        dmx_rdm_on_usart_tx_interrupt();
    }
}
...


Добавлено after 11 minutes 40 seconds:
Заметил такое явление, что в MounRiver есть глюк, когда точка останова становится "фальшивой", то есть, если до начала отладки выставлять точку останова, то она показывается как бы сдвоенной, и если "убрать", то остается одиночная точка, как будто она выставлена, но в процессе отладки там нет галочки, и точка не отрабатывает

Re: CH32V103 пропуск точек останова

Сб июн 17, 2023 20:11:15

странно. обычно, среды вопят, если бряк не может быть обработан (выкинут оптимизатором, например)
я бы проверил выключением оптимизатора и собственно отработки прерывания (светодиодиком моргнуть на порту)
а так-то у них Эклипсе, эта MounRiver ... не в восторге я от нее
И вроде, ИАР поддерживает RISC-V WCH?

Re: CH32V103 пропуск точек останова

Сб июн 17, 2023 20:38:43

я бы проверил выключением оптимизатора и собственно отработки прерывания (светодиодиком моргнуть на порту)

Оптимизация O0, попробую моргнуть светиком на моменте обработки прерывания

IAR не видел, чтобы поддерживалась, Keil скорее всего только для армов

Добавлено after 3 minutes 44 seconds:
Отработал 4 точки останова:
Спойлер
Код:
void dmx_rdm_usart_enable_tx_interrupts() {
    USART2->STATR = 0x00C0;
    USART_ITConfig(DMX_RDM_USART_USED, USART_IT_TC, ENABLE); // <-
}

void dmx_rdm_usart_disable_tx_interrupts() {
    USART2->STATR = 0x00C0;
    USART_ITConfig(DMX_RDM_USART_USED, USART_IT_TC, DISABLE); // <-
}

void dmx_rdm_usart_enable_rx_interrupts() {
    USART2->STATR = 0x00C0;
    USART_ITConfig(DMX_RDM_USART_USED, USART_IT_RXNE | USART_IT_FE, ENABLE); // <-
}

void dmx_rdm_usart_disable_rx_interrupts() {
    USART2->STATR = 0x00C0;
    USART_ITConfig(DMX_RDM_USART_USED, USART_IT_RXNE | USART_IT_FE, DISABLE); // <-
}


После
Сообщение от GDB:
Код:
Error: unable to step rtos hart

Re: CH32V103 пропуск точек останова

Сб июн 17, 2023 21:12:38

тут описан некий механизм, может поможет https://zhuanlan.zhihu.com/p/138322951

Re: CH32V103 пропуск точек останова

Сб июн 17, 2023 22:01:04

Сделал вывод на пин события прерывания

И тут такая странность:
1) Когда только залил прошивку и перезагрузил, светодиод не моргает даже на приходящие данные
2) Когда начинаю отладку, то светодиод моргает (не HardFault), отладчик проходит по точкам останова
3) Когда завершаю отладку командой Terminate, контроллер сваливается в HardFault, моргает светик быстро, но видимо на глаз
Код обработчика HardFault:
Код:
void HardFault_Handler(void)
{
    while(1)
    {
        GPIO_WriteBit(GPIOC, GPIO_Pin_13, 1);
        delay_ms(20);
//        Delay_Ms(100);
        GPIO_WriteBit(GPIOC, GPIO_Pin_13, 0);
        delay_ms(20);
//        Delay_Ms(100);
    }
}

Re: CH32V103 пропуск точек останова и прерывания для DMX/RDM

Вс июн 18, 2023 18:47:03

Так, с hardfault разобрался
Поменял скрипт линковки:
Код:
MEMORY
{
     APP (rx) : ORIGIN = 0x00000000, LENGTH = 0x0FF00
     CREDENTIALS (rx) : ORIGIN = 0x0000FF00, LENGTH = 0x00080
     DATA (rwx) : ORIGIN = 0x0000FF80, LENGTH = 0x00080
   RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 20K
}


Теперь есть такая проблема: если сделать такой вызов:
Код:
USART_ITConfig(DMX_RDM_USART_USED, USART_IT_TC | USART_IT_RXNE | USART_IT_ERR, ENABLE);

то прерывания не приходят, даже если слать DMX посылку
А если делаю так:
Код:
DMX_RDM_USART_USED->CTLR1 |= (1<<6); // USART TCIE Transmit completed interrupt
DMX_RDM_USART_USED->CTLR1 |= (1<<5); // USART RXNEIE Receive non empty interrupt
DMX_RDM_USART_USED->CTLR3 |= (1<<0); // USART EIE Error enable interrupt

то контроллер зависает в обработчике прерывания, что выдается миганием светодиода

Вот думаю, что делаю не так
Ответить