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(); } } }
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; }
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); }
/** * 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; }
void SerialBase::abort_read(void) { serial_rx_abort_asynch(&_serial); }
/** 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; }
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; }