rt_inline int _serial_dma_tx(struct rt_serial_device *serial, const rt_uint8_t *data, int length) { rt_base_t level; rt_err_t result; struct rt_serial_tx_dma *tx_dma; tx_dma = (struct rt_serial_tx_dma*)(serial->serial_tx); result = rt_data_queue_push(&(tx_dma->data_queue), data, length, RT_WAITING_FOREVER); if (result == RT_EOK) { level = rt_hw_interrupt_disable(); if (tx_dma->activated != RT_TRUE) { tx_dma->activated = RT_TRUE; rt_hw_interrupt_enable(level); /* make a DMA transfer */ serial->ops->dma_transmit(serial, data, length, RT_SERIAL_DMA_TX); } else { rt_hw_interrupt_enable(level); } return length; } else { rt_set_errno(result); return 0; } }
static rt_size_t rt_serial_write(struct rt_device *dev, rt_off_t pos, const void *buffer, rt_size_t size) { rt_uint8_t *ptr; rt_size_t write_nbytes = 0; struct rt_serial_device *serial; RT_ASSERT(dev != RT_NULL); serial = (struct rt_serial_device *)dev; ptr = (rt_uint8_t*)buffer; if (dev->flag & RT_DEVICE_FLAG_INT_TX) { /* warning: data will be discarded if buffer is full */ while (size) { if (serial_ringbuffer_putchar(serial->int_tx, *ptr) != -1) { ptr ++; size --; } else break; } } else if (dev->flag & RT_DEVICE_FLAG_DMA_TX) { const void *data_ptr = RT_NULL; rt_size_t data_size = 0; rt_base_t level; rt_err_t result; RT_ASSERT(0 == (dev->flag & RT_DEVICE_FLAG_STREAM)); result = rt_data_queue_push(&(serial->tx_dq), buffer, size, 20); if (result == RT_EOK) { level = rt_hw_interrupt_disable(); if (serial->dma_flag == RT_FALSE) { serial->dma_flag = RT_TRUE; rt_hw_interrupt_enable(level); if (RT_EOK == rt_data_queue_pop(&(serial->tx_dq), &data_ptr, &data_size, 0)) { serial->ops->dma_transmit(serial, data_ptr, data_size); } } else rt_hw_interrupt_enable(level); return size; } else { rt_set_errno(result); return 0; } } else { /* polling mode */ while (size) { /* * to be polite with serial console add a line feed * to the carriage return character */ if (*ptr == '\n' && (dev->flag & RT_DEVICE_FLAG_STREAM)) { serial->ops->putc(serial, '\r'); } serial->ops->putc(serial, *ptr); ++ ptr; -- size; } } write_nbytes = (rt_uint32_t)ptr - (rt_uint32_t)buffer; if (write_nbytes == 0) { rt_set_errno(-RT_EFULL); } return write_nbytes; }