Esempio n. 1
0
static void uart_err_irq(IRQn_Type irq_num, uint32_t index) {
    serial_t *obj = uart_data[index].receiving_obj;
    int was_masked, err_read;
    
    if (obj) {
        serial_irq_err_set(obj, 0);
        if (uart_data[index].wanted_rx_events & (SERIAL_EVENT_RX_PARITY_ERROR | SERIAL_EVENT_RX_FRAMING_ERROR)) {
            uart_data[index].event = SERIAL_EVENT_RX_PARITY_ERROR | SERIAL_EVENT_RX_FRAMING_ERROR;
            if (obj->serial.uart->SCFSR & 1 << 2) {
                uart_data[index].event = SERIAL_EVENT_RX_PARITY_ERROR;
            } else if (obj->serial.uart->SCFSR & 1 << 3) {
                uart_data[index].event = SERIAL_EVENT_RX_FRAMING_ERROR;
            }
            ((void (*)())uart_data[index].async_rx_callback)();
        }
        serial_rx_abort_asynch(obj);
        
        was_masked = __disable_irq();
        if (obj->serial.uart->SCFSR & 0x93) {
            err_read = obj->serial.uart->SCFSR;
            obj->serial.uart->SCFSR = (err_read & ~0x93);
        }
        if (obj->serial.uart->SCLSR & 1) {
            obj->serial.uart->SCLSR = 0;
        }
        if (!was_masked) {
            __enable_irq();
        }
    }
}
Esempio n. 2
0
int serial_rx_irq_handler_asynch(serial_t *obj)
{
    /* Sanity check arguments */
    MBED_ASSERT(obj);
    uint32_t ul_status, ulmask;

    /* Read USART Status. */
    ul_status = usart_get_status(_USART(obj));
    ulmask = usart_get_interrupt_mask(_USART(obj));
    ul_status &= ulmask;

    if (ul_status & US_CSR_OVRE) { /* Overrun Error */
        usart_disable_interrupt(_USART(obj), US_IDR_OVRE);
        serial_rx_abort_asynch(obj);
        return SERIAL_EVENT_RX_OVERFLOW;
    }
    if (ul_status & US_CSR_FRAME) { /* Framing Error */
        usart_disable_interrupt(_USART(obj), US_IDR_FRAME);
        serial_rx_abort_asynch(obj);
        return SERIAL_EVENT_RX_FRAMING_ERROR;
    }
    if (ul_status & US_CSR_PARE) { /* Parity Error */
        usart_disable_interrupt(_USART(obj), US_IDR_PARE);
        serial_rx_abort_asynch(obj);
        return SERIAL_EVENT_RX_PARITY_ERROR;
    }
    if ((ul_status & (US_IER_RXBUFF | US_IER_CMP)) ==  (US_IER_RXBUFF | US_IER_CMP)) { /* Character match in last character in transfer*/
        usart_disable_interrupt(_USART(obj), US_IDR_CMP);
        serial_rx_abort_asynch(obj);
        return SERIAL_EVENT_RX_COMPLETE|SERIAL_EVENT_RX_CHARACTER_MATCH;
    }
    if (ul_status & US_IER_CMP) { /* Character match */
        usart_disable_interrupt(_USART(obj), US_IDR_CMP);
        if (pSERIAL_S(obj)->events == SERIAL_EVENT_RX_CHARACTER_MATCH) { /*if character match is the only event abort transfer */
            serial_rx_abort_asynch(obj);
        }
        return SERIAL_EVENT_RX_CHARACTER_MATCH;
    }
    if (ul_status & US_IER_RXBUFF) { /* Reception Complete */
        serial_rx_abort_asynch(obj);
        return SERIAL_EVENT_RX_COMPLETE;
    }
    return 0;
}
Esempio n. 3
0
static void uart_rx_irq(IRQn_Type irq_num, uint32_t index) {
    __IO uint16_t *dmy_rd_scscr;
    __IO uint16_t *dmy_rd_scfsr;
    serial_t *obj;
    int c;
    
    dmy_rd_scscr = SCSCR_MATCH[index];
    *dmy_rd_scscr &= 0x00B3;                    // Clear RIE,REIE and Write to bit15~8,2 is always 0
    dmy_rd_scfsr = SCFSR_MATCH[index];
    *dmy_rd_scfsr = (*dmy_rd_scfsr & ~0x0003);  // Clear RDF,DR
    
    obj = uart_data[index].receiving_obj;
    if (obj) {
        if (obj->serial.uart->SCLSR & 1) {
            if (uart_data[index].wanted_rx_events & SERIAL_EVENT_RX_OVERRUN_ERROR) {
                serial_rx_abort_asynch(obj);
                uart_data[index].event = SERIAL_EVENT_RX_OVERRUN_ERROR;
                ((void (*)())uart_data[index].async_rx_callback)();
            }
            return;
        }
        c = serial_getc(obj);
        if (c != -1) {
            ((uint8_t *)obj->rx_buff.buffer)[obj->rx_buff.pos] = c;
            ++obj->rx_buff.pos;
            if (c == obj->char_match && ! obj->char_found) {
                obj->char_found = 1;
                if (obj->rx_buff.pos == obj->rx_buff.length) {
                    if (uart_data[index].wanted_rx_events & SERIAL_EVENT_RX_COMPLETE) {
                        uart_data[index].event = SERIAL_EVENT_RX_COMPLETE;
                    }
                }
                if (uart_data[index].wanted_rx_events & SERIAL_EVENT_RX_CHARACTER_MATCH) {
                    uart_data[index].event |= SERIAL_EVENT_RX_CHARACTER_MATCH;
                }
                if (uart_data[index].event) {
                    uart_data[index].receiving_obj = NULL;
                    ((void (*)())uart_data[index].async_rx_callback)();
                }
            } else if (obj->rx_buff.pos == obj->rx_buff.length) {
                uart_data[index].receiving_obj = NULL;
                if (uart_data[index].wanted_rx_events & SERIAL_EVENT_RX_COMPLETE) {
                    uart_data[index].event = SERIAL_EVENT_RX_COMPLETE;
                    ((void (*)())uart_data[index].async_rx_callback)();
                }
            }
        } else {
            serial_rx_abort_asynch(obj);
            if (uart_data[index].wanted_rx_events & (SERIAL_EVENT_RX_PARITY_ERROR | SERIAL_EVENT_RX_FRAMING_ERROR)) {
                uart_data[index].event = SERIAL_EVENT_RX_PARITY_ERROR | SERIAL_EVENT_RX_FRAMING_ERROR;
                if (obj->serial.uart->SCFSR & 1 << 2) {
                    uart_data[index].event = SERIAL_EVENT_RX_PARITY_ERROR;
                } else if (obj->serial.uart->SCFSR & 1 << 3) {
                    uart_data[index].event = SERIAL_EVENT_RX_FRAMING_ERROR;
                }
                ((void (*)())uart_data[index].async_rx_callback)();
            }
            return;
        }
    }
    
    irq_handler(uart_data[index].serial_irq_id, RxIrq);
}
Esempio n. 4
0
/**
 * The asynchronous TX and RX handler.
 *
 * @param obj The serial object
 * @return Returns event flags if a TX/RX transfer termination condition was met or 0 otherwise
 */
int serial_irq_handler_asynch(serial_t *obj)
{
    struct serial_s *obj_s = SERIAL_S(obj);
    UART_HandleTypeDef *huart = &uart_handlers[obj_s->index];
    
    volatile int return_event = 0;
    uint8_t *buf = (uint8_t*)(obj->rx_buff.buffer);
    uint8_t i = 0;
    
    // TX PART:
    if (__HAL_UART_GET_FLAG(huart, UART_FLAG_TC) != RESET) {
        if (__HAL_UART_GET_IT_SOURCE(huart, UART_IT_TC) != RESET) {
            // Return event SERIAL_EVENT_TX_COMPLETE if requested
            if ((obj_s->events & SERIAL_EVENT_TX_COMPLETE ) != 0) {
                return_event |= (SERIAL_EVENT_TX_COMPLETE & obj_s->events);
            }
        }
    }
    
    // Handle error events
    if (__HAL_UART_GET_FLAG(huart, UART_FLAG_PE) != RESET) {
        if (__HAL_UART_GET_IT_SOURCE(huart, USART_IT_ERR) != RESET) {
            return_event |= (SERIAL_EVENT_RX_PARITY_ERROR & obj_s->events);
        }
    }
    
    if (__HAL_UART_GET_FLAG(huart, UART_FLAG_FE) != RESET) {
        if (__HAL_UART_GET_IT_SOURCE(huart, USART_IT_ERR) != RESET) {
            return_event |= (SERIAL_EVENT_RX_FRAMING_ERROR & obj_s->events);
        }
    }
    
    if (__HAL_UART_GET_FLAG(huart, UART_FLAG_ORE) != RESET) {
        if (__HAL_UART_GET_IT_SOURCE(huart, USART_IT_ERR) != RESET) {
            return_event |= (SERIAL_EVENT_RX_OVERRUN_ERROR & obj_s->events);
        }
    }
    
    HAL_UART_IRQHandler(huart);
    
    // Abort if an error occurs
    if (return_event & SERIAL_EVENT_RX_PARITY_ERROR ||
            return_event & SERIAL_EVENT_RX_FRAMING_ERROR ||
            return_event & SERIAL_EVENT_RX_OVERRUN_ERROR) {
        return return_event;
    }
    
    //RX PART
    if (huart->RxXferSize != 0) {
        obj->rx_buff.pos = huart->RxXferSize - huart->RxXferCount;
    }
    if ((huart->RxXferCount == 0) && (obj->rx_buff.pos >= (obj->rx_buff.length - 1))) {
        return_event |= (SERIAL_EVENT_RX_COMPLETE & obj_s->events);
    }
    
    // Check if char_match is present
    if (obj_s->events & SERIAL_EVENT_RX_CHARACTER_MATCH) {
        if (buf != NULL) {
            for (i = 0; i < obj->rx_buff.pos; i++) {
                if (buf[i] == obj->char_match) {
                    obj->rx_buff.pos = i;
                    return_event |= (SERIAL_EVENT_RX_CHARACTER_MATCH & obj_s->events);
                    serial_rx_abort_asynch(obj);
                    break;
                }
            }
        }
    }
    
    return return_event;  
}
Esempio n. 5
0
void SerialBase::abort_read(void)
{
    serial_rx_abort_asynch(&_serial);
}
Esempio n. 6
0
/** The asynchronous TX and RX handler.
 *
 * @param obj The serial object
 * @return Returns event flags if an RX transfer termination condition was met; otherwise returns 0
 */
int serial_irq_handler_asynch(serial_t *obj)
{
    struct serial_s *p_obj = GET_SERIAL_S(obj);
    volatile uint8_t i = 0;
    volatile int return_val = 0;
    uint8_t *p_buf = (uint8_t *)(obj->rx_buff.buffer);

    if (usart_interrupt_flag_get(p_obj->uart, USART_INT_FLAG_PERR) != RESET) {
        /* clear PERR error flag by reading USART DATA register */
        USART_DATA(p_obj->uart);

        return_val |= (SERIAL_EVENT_RX_PARITY_ERROR & p_obj->events);
        p_obj->error_code |= USART_ERROR_CODE_PERR;
    }

    if (usart_interrupt_flag_get(p_obj->uart, USART_INT_FLAG_ERR_FERR) != RESET) {
        /* clear FERR error flag by reading USART DATA register */
        USART_DATA(p_obj->uart);

        return_val |= (SERIAL_EVENT_RX_FRAMING_ERROR & p_obj->events);
        p_obj->error_code |= USART_ERROR_CODE_FERR;
    }

    if (usart_interrupt_flag_get(p_obj->uart, USART_INT_FLAG_ERR_ORERR) != RESET) {
        /* clear ORERR error flag by reading USART DATA register */
        USART_DATA(p_obj->uart);

        return_val |= (SERIAL_EVENT_RX_OVERRUN_ERROR & p_obj->events);
        p_obj->error_code |= USART_ERROR_CODE_ORERR;
    }

    if (return_val & (SERIAL_EVENT_RX_PARITY_ERROR | SERIAL_EVENT_RX_FRAMING_ERROR |
                      SERIAL_EVENT_RX_OVERRUN_ERROR)) {
        return return_val;
    }

    if (usart_interrupt_flag_get(p_obj->uart, USART_INT_FLAG_TC) != RESET) {
        if ((p_obj->events & SERIAL_EVENT_TX_COMPLETE) != 0) {
            return_val |= (SERIAL_EVENT_TX_COMPLETE & p_obj->events);
        }
    }

    usart_irq_handler(p_obj);

    if (p_obj->rx_size != 0) {
        obj->rx_buff.pos = p_obj->rx_size - p_obj->rx_count;
    }

    if ((p_obj->rx_count == 0) && (obj->rx_buff.pos >= (obj->rx_buff.length - 1))) {
        return_val |= (SERIAL_EVENT_RX_COMPLETE & p_obj->events);
    }

    if (p_obj->events & SERIAL_EVENT_RX_CHARACTER_MATCH) {
        if (p_buf != NULL) {
            for (i = 0; i < obj->rx_buff.pos; i++) {
                if (p_buf[i] == obj->char_match) {
                    obj->rx_buff.pos = i;
                    return_val |= (SERIAL_EVENT_RX_CHARACTER_MATCH & p_obj->events);
                    serial_rx_abort_asynch(obj);
                    break;
                }
            }
        }
    }

    return return_val;
}
Esempio n. 7
0
int serial_rx_irq_handler_asynch(serial_t *obj)
{
    /* Sanity check arguments */
    MBED_ASSERT(obj);
    int event = 0;
    /* This interrupt handler is called from USART irq */
    uint8_t *buf = (uint8_t*)obj->rx_buff.buffer;
    uint8_t error_code = 0;
    uint16_t received_data = 0;

    error_code = (uint8_t)(_USART(obj).STATUS.reg & SERCOM_USART_STATUS_MASK);
    /* Check if an error has occurred during the receiving */
    if (error_code) {
        /* Check which error occurred */
        if (error_code & SERCOM_USART_STATUS_FERR) {
            /* Store the error code and clear flag by writing 1 to it */
            _USART(obj).STATUS.reg |= SERCOM_USART_STATUS_FERR;
            serial_rx_abort_asynch(obj);
            return SERIAL_EVENT_RX_FRAMING_ERROR;
        } else if (error_code & SERCOM_USART_STATUS_BUFOVF) {
            /* Store the error code and clear flag by writing 1 to it */
            _USART(obj).STATUS.reg |= SERCOM_USART_STATUS_BUFOVF;
            serial_rx_abort_asynch(obj);
            return SERIAL_EVENT_RX_OVERFLOW;
        } else if (error_code & SERCOM_USART_STATUS_PERR) {
            /* Store the error code and clear flag by writing 1 to it */
            _USART(obj).STATUS.reg |= SERCOM_USART_STATUS_PERR;
            serial_rx_abort_asynch(obj);
            return SERIAL_EVENT_RX_PARITY_ERROR;
        }
    }

    /* Read current packet from DATA register,
    * increment buffer pointer and decrement buffer length */
    received_data = (_USART(obj).DATA.reg & SERCOM_USART_DATA_MASK);

    /* Read value will be at least 8-bits long */
    buf[obj->rx_buff.pos] = received_data;
    /* Increment 8-bit pointer */
    obj->rx_buff.pos++;

    /* Check if the last character have been received */
    if(--(obj->rx_buff.length) == 0) {
        event |= SERIAL_EVENT_RX_COMPLETE;
        if((buf[obj->rx_buff.pos - 1] == obj->char_match) && (obj->serial.events & SERIAL_EVENT_RX_CHARACTER_MATCH)) {
            event |= SERIAL_EVENT_RX_CHARACTER_MATCH;
        }
        _USART(obj).INTFLAG.reg = SERCOM_USART_INTFLAG_RXC;
        serial_rx_abort_asynch(obj);
        return event & obj->serial.events;
    }

    /* Check for character match event */
    if((buf[obj->rx_buff.pos - 1] == obj->char_match) && (obj->serial.events & SERIAL_EVENT_RX_CHARACTER_MATCH)) {
        event |= SERIAL_EVENT_RX_CHARACTER_MATCH;
    }

    /* Return to the call back if character match occured */
    if(event != 0) {
        serial_rx_abort_asynch(obj);
        return event & obj->serial.events;
    }
    return 0;
}