CYW43907 UART Framing Error problem while implementing DMX512

Tip / Sign in to post questions, reply, level up, and achieve exciting badges. Know more

cross mob
krystofslavik
Level 1
Level 1
5 replies posted 10 sign-ins 5 sign-ins

Hello,

I would like to implement a DMX512 receiver using the CYW43907. DMX512 protocol  is basically identical to a normal UART 8N2 at 250 kbaud. The only important difference is that there is a BREAK pulse (signal goes low for at least 88 microseconds) between 512B data frames.  This BREAK pulse must be detected in order to find the first byte of the data frame. From what I gathered this is normally achieved by using Framing Error interrupt which should trigger if there is no Stop bit detected.

The GCI UART interface in the CYW43907 has Framing Error interrupt which can be enabled by setting the GCI_INT_ST_MASK_SECI_FRAMING_ERROR flag. The issue that I have is that the interrupt fires all the time even for bytes that are received correctly. I have also tried to connect a regular UART transmitter (USB to UART converter) but the Framing Error interrupt still triggers even though the data is received correctly.

Modifications in platform_uart.c:

static void uart_gci_enable_interrupts( void )
{
#ifndef BCM4390X_UART_GCI_POLL_MODE
    /* Enable GCI UART interrupt in ChipCommon interrupt mask */
    uart_chipcommon_interrupt_mask(0x0, UART_GCI_CC_INT_STATUS_MASK);

// MODIFICATION STARTS HERE
    GCI_INT_MASK_REG = GCI_INT_ST_MASK_SECI_RX_FIFO_ALMOST_FULL | GCI_INT_ST_MASK_SECI_RX_IDLE_TIMER_INT | GCI_INT_ST_MASK_SECI_FRAMING_ERROR;
// MODIFICATION ENDS HERE
#endif /* !BCM4390X_UART_GCI_POLL_MODE */
}

static void uart_gci_irq( platform_uart_driver_t* driver )
{
    uint32_t int_status;
    uint32_t int_mask;

    int_mask = GCI_INT_MASK_REG;
    int_status = GCI_INT_STATUS_REG;

    /* Turn off GCI UART interrupts */
    platform_uart_disable_interrupts(driver->interface->port);

    if ( ((int_status & GCI_INT_ST_MASK_SECI_RX_FIFO_ALMOST_FULL) && (int_mask & GCI_INT_ST_MASK_SECI_RX_FIFO_ALMOST_FULL)) ||
         ((int_status & GCI_INT_ST_MASK_SECI_RX_IDLE_TIMER_INT) && (int_mask & GCI_INT_ST_MASK_SECI_RX_IDLE_TIMER_INT)) )
    {
        /* Drain the GCI UART RX FIFO */
        while ( (GCI_INT_STATUS_REG & GCI_INT_ST_MASK_SECI_RX_FIFO_NOT_EMPTY) )
        {
            if ( uart_seci_process_irq(driver, uart_gci_base) != WICED_TRUE )
            {
                /* GCI UART interrupts remain turned off */
                return;
            }
        }
    }
// MODIFICATION STARTS HERE
    if ((int_status & GCI_INT_ST_MASK_SECI_FRAMING_ERROR) && (int_mask & GCI_INT_ST_MASK_SECI_FRAMING_ERROR))
    {
        framing_error_cnt++;
    }
// MODIFICATION ENDS HERE

    /* Turn on GCI UART interrupts */
    platform_uart_enable_interrupts(driver->interface->port);
}

I have also tried to use the FAST UART interface. It does not have the FE interrupt but Framing Error bit can be read from the LSR register and it seems that it is always set.

Is there any low level documentation of the UART interfaces? Do you have experience with the UART interrupts and flags? Is there a better way to implement DMX512 receiver on the CYW43907?

Many thanks!

 

0 Likes
5 Replies
YashM
Moderator
Moderator
Moderator
First question asked 250 sign-ins 100 replies posted

Hi,

Sorry, we don't have any such documents.

Regarding the Framing error concept - I will discuss this internally and get back to you shortly.

Thanks and Regards

0 Likes
krystofslavik
Level 1
Level 1
5 replies posted 10 sign-ins 5 sign-ins

Hi,

any updates?

Thanks.

0 Likes

Hi,

Can you provide how have you configured the UART for this protocol? In short, how has been the configuration done? As per the protocol, there should be two stop bits in a data frame. Have you configured that?

Thanks

Aditi

0 Likes

Hi Aditi,

for the DMX512 I have configured the UART as follows:

    wiced_uart_config_t uart_config =
    {
        .baud_rate    = 250000,
        .data_width   = DATA_WIDTH_8BIT,
        .parity       = NO_PARITY,
        .stop_bits    = STOP_BITS_2,
        .flow_control = FLOW_CONTROL_DISABLED,
    };

 

Also, I have some new info that might help resolve the issue. Once the Framing Error interrupt fires for the first time it is then triggered repeatedly even when there is no activity on the RX line. Perhaps the interrupt flag is not beging cleared? I am definitely not clearing it. Is there a way to do it?

These are the steps to reproduce the issue (interrupt firing repeatedly) using a normal USB UART converter, DMX512 not involved here. I am mismatching the baud rates here on purpose in order to produce the Framing Error. Every time there is a Framing Error I toggle the WICED_GPIO_12 that is connected to an oscilloscope.

  1. Fresh install of Wiced Studio 6.6
  2. Modify snip.uart (code snippet below), configure UART as 250000 baud
  3. Modify platform_uart.c (code snippet below)
  4. Connect USB UART converter to the GCI UART, configure as 115200 baud
  5. Connect oscilloscope probes to UART RX and WICED_GPIO_12
  6. Send character 'f' via UART

Blue = UART RX, Yellow = Framing Error interruptBlue = UART RX, Yellow = Framing Error interrupt

uart.c:

#include "wiced.h"

#define RX_BUFFER_SIZE    64
#define TEST_STR          "\r\nType something! Keystrokes are echoed to the terminal ...\r\n> "

wiced_uart_config_t uart_config =
{
    .baud_rate    = 250000,//115200,
    .data_width   = DATA_WIDTH_8BIT,
    .parity       = NO_PARITY,
    .stop_bits    = STOP_BITS_1,
    .flow_control = FLOW_CONTROL_DISABLED,
};

wiced_ring_buffer_t rx_buffer;
DEFINE_RING_BUFFER_DATA( uint8_t, rx_data, RX_BUFFER_SIZE)

void application_start( )
{
    char c;
    uint32_t expected_data_size = 1;

    wiced_result_t res = wiced_gpio_init(WICED_GPIO_12, OUTPUT_PUSH_PULL);
    wiced_gpio_output_low(WICED_GPIO_12);

    /* Initialise ring buffer */
    ring_buffer_init(&rx_buffer, rx_data, RX_BUFFER_SIZE );

    /* Initialise UART. A ring buffer is used to hold received characters */
    wiced_uart_init( WICED_UART_3, &uart_config, &rx_buffer );

    /* Send a test string to the terminal */
    wiced_uart_transmit_bytes( WICED_UART_3, TEST_STR, sizeof( TEST_STR ) - 1 );

    /* Wait for user input. If received, echo it back to the terminal */
    while ( wiced_uart_receive_bytes( WICED_UART_3, &c, &expected_data_size, WICED_NEVER_TIMEOUT ) == WICED_SUCCESS )
    {
        wiced_uart_transmit_bytes( WICED_UART_3, &c, 1 );
        expected_data_size = 1;
    }
}

 

platform_uart.c

/* INSIDE uart_gci_enable_interrupts */
CHIPCOMMON_SECI_STATUS_MASK_REG = GCI_INT_ST_MASK_SECI_RX_FIFO_ALMOST_FULL | GCI_INT_ST_MASK_SECI_RX_IDLE_TIMER_INT | GCI_INT_ST_MASK_SECI_FRAMING_ERROR;

/* INSIDE uart_gci_irq */
    if ((int_status & GCI_INT_ST_MASK_SECI_FRAMING_ERROR) && (int_mask & GCI_INT_ST_MASK_SECI_FRAMING_ERROR))
    {
        static int state = 0;
        if (!state) wiced_gpio_output_high(WICED_GPIO_12);
        else wiced_gpio_output_low(WICED_GPIO_12);
        state = !state;
    }

 

0 Likes
krystofslavik
Level 1
Level 1
5 replies posted 10 sign-ins 5 sign-ins

Hi,

are there any updates regarding this issue? Does the Framing Error interrupt flag have to be cleared somehow?

Thanks,

Krystof

0 Likes