Пример #1
0
static int32_t PIOS_COM_SendBufferNonBlockingInternal(struct pios_com_dev *com_dev, const uint8_t *buffer, uint16_t len)
{
    PIOS_Assert(com_dev);
    PIOS_Assert(com_dev->has_tx);
    if (com_dev->driver->available && !com_dev->driver->available(com_dev->lower_id)) {
        /*
         * Underlying device is down/unconnected.
         * Dump our fifo contents and act like an infinite data sink.
         * Failure to do this results in stale data in the fifo as well as
         * possibly having the caller block trying to send to a device that's
         * no longer accepting data.
         */
        fifoBuf_clearData(&com_dev->tx);
        return len;
    }

    if (len > fifoBuf_getFree(&com_dev->tx)) {
        /* Buffer cannot accept all requested bytes (retry) */
        return -2;
    }

    uint16_t bytes_into_fifo = fifoBuf_putData(&com_dev->tx, buffer, len);

    if (bytes_into_fifo > 0) {
        /* More data has been put in the tx buffer, make sure the tx is started */
        if (com_dev->driver->tx_start) {
            com_dev->driver->tx_start(com_dev->lower_id,
                                      fifoBuf_getUsed(&com_dev->tx));
        }
    }
    return bytes_into_fifo;
}
Пример #2
0
data_type fifoBuf_putData(t_fifo_buffer *buf, const void *data, data_type len)
{       // add data to the buffer

    data_type wr = buf->wr;
    data_type buf_size = buf->buf_size;
    uint8_t *buff = buf->buf_ptr;

    data_type num_bytes = fifoBuf_getFree(buf);
    if (num_bytes > len)
        num_bytes = len;

    if (num_bytes < 1)
        return 0;               // return number of bytes copied

    uint8_t *p = (uint8_t *)data;
    data_type i = 0;

    while (num_bytes > 0)
    {
        data_type j = buf_size - wr;
        if (j > num_bytes)
            j = num_bytes;
        memcpy(buff + wr, p + i, j);
        i += j;
        num_bytes -= j;
        wr += j;
        if (wr >= buf_size)
            wr = 0;
    }

    buf->wr = wr;

    return i;                   // return number of bytes copied
}
Пример #3
0
/**
* puts more than one byte onto the transmit buffer (used for atomic sends)
* \param[in] USART USART name
* \param[in] *buffer pointer to buffer to be sent
* \param[in] len number of bytes to be sent
* \return 0 if no error
* \return -1 if buffer full or cannot get all requested bytes (retry)
*/
static int32_t PIOS_USART_TxBufferPutMoreNonBlocking(uint32_t usart_id, const uint8_t *buffer, uint16_t len)
{
	struct pios_usart_dev * usart_dev = (struct pios_usart_dev *)usart_id;

	bool valid = PIOS_USART_validate(usart_dev);
	PIOS_Assert(valid)

	if (len >= fifoBuf_getFree(&usart_dev->tx)) {
		/* Buffer cannot accept all requested bytes (retry) */
		return -1;
	}

	/* Copy bytes to be transmitted into transmit buffer */
	/* This operation should be atomic! */
	PIOS_IRQ_Disable();

	uint16_t used = fifoBuf_getUsed(&usart_dev->tx);
	fifoBuf_putData(&usart_dev->tx,buffer,len);
	
	if (used == 0) {
		/* enable sending when buffer was previously empty */
		USART_ITConfig(usart_dev->cfg->regs, USART_IT_TXE, ENABLE);
	}

	PIOS_IRQ_Enable();

	/* No error */
	return 0;
}
Пример #4
0
/**
* Sends a package over given port
* \param[in] port COM port
* \param[in] buffer character buffer
* \param[in] len buffer length
* \return -1 if port not available
* \return -2 if non-blocking mode activated: buffer is full
*            caller should retry until buffer is free again
* \return 0 on success
*/
int32_t PIOS_COM_SendBufferNonBlocking(uint32_t com_id, const uint8_t *buffer, uint16_t len)
{
	struct pios_com_dev * com_dev = PIOS_COM_find_dev(com_id);

	if (!PIOS_COM_validate(com_dev)) {
		/* Undefined COM port for this board (see pios_board.c) */
		return -1;
	}

	PIOS_Assert(com_dev->has_tx);

	if (len >= fifoBuf_getFree(&com_dev->tx)) {
		/* Buffer cannot accept all requested bytes (retry) */
		return -2;
	}

	PIOS_IRQ_Disable();
	uint16_t bytes_into_fifo = fifoBuf_putData(&com_dev->tx, buffer, len);
	PIOS_IRQ_Enable();

	if (bytes_into_fifo > 0) {
		/* More data has been put in the tx buffer, make sure the tx is started */
		if (com_dev->driver->tx_start) {
			com_dev->driver->tx_start(com_dev->lower_id,
						  fifoBuf_getUsed(&com_dev->tx));
		}
	}

	return (bytes_into_fifo);
}
Пример #5
0
/**
 * Initialises COM layer
 * \param[out] handle
 * \param[in] driver
 * \param[in] id
 * \return < 0 if initialisation failed
 */
int32_t PIOS_COM_Init(uint32_t *com_id, const struct pios_com_driver *driver, uint32_t lower_id, uint8_t *rx_buffer, uint16_t rx_buffer_len, uint8_t *tx_buffer, uint16_t tx_buffer_len)
{
    PIOS_Assert(com_id);
    PIOS_Assert(driver);

    bool has_rx = (rx_buffer && rx_buffer_len > 0);
    bool has_tx = (tx_buffer && tx_buffer_len > 0);
    PIOS_Assert(has_rx || has_tx);
    PIOS_Assert(driver->bind_tx_cb || !has_tx);
    PIOS_Assert(driver->bind_rx_cb || !has_rx);

    struct pios_com_dev *com_dev;

    com_dev = (struct pios_com_dev *)PIOS_COM_alloc();
    if (!com_dev) {
        goto out_fail;
    }

    com_dev->driver   = driver;
    com_dev->lower_id = lower_id;

    com_dev->has_rx   = has_rx;
    com_dev->has_tx   = has_tx;

    if (has_rx) {
        fifoBuf_init(&com_dev->rx, rx_buffer, rx_buffer_len);
#if defined(PIOS_INCLUDE_FREERTOS)
        vSemaphoreCreateBinary(com_dev->rx_sem);
#endif /* PIOS_INCLUDE_FREERTOS */
        (com_dev->driver->bind_rx_cb)(lower_id, PIOS_COM_RxInCallback, (uint32_t)com_dev);
        if (com_dev->driver->rx_start) {
            /* Start the receiver */
            (com_dev->driver->rx_start)(com_dev->lower_id,
                                        fifoBuf_getFree(&com_dev->rx));
        }
    }

    if (has_tx) {
        fifoBuf_init(&com_dev->tx, tx_buffer, tx_buffer_len);
#if defined(PIOS_INCLUDE_FREERTOS)
        vSemaphoreCreateBinary(com_dev->tx_sem);
#endif /* PIOS_INCLUDE_FREERTOS */
        (com_dev->driver->bind_tx_cb)(lower_id, PIOS_COM_TxOutCallback, (uint32_t)com_dev);
    }
#if defined(PIOS_INCLUDE_FREERTOS)
    com_dev->sendbuffer_sem = xSemaphoreCreateMutex();
#endif /* PIOS_INCLUDE_FREERTOS */

    *com_id = (uint32_t)com_dev;
    return 0;

out_fail:
    return -1;
}
Пример #6
0
/**
 * Send the buffer over UART
 * return -2 if non-blocking mode activated: buffer is full
 *            caller should retry until buffer is free again
 * return number of bytes transmitted on success
 */
int8_t Serial_SendBufferNonBlocking(const uint8_t *buffer,
                                    uint16_t len)
{
    if (len > fifoBuf_getFree(&tx_buffer))
    {
        /* Buffer cannot accept all requested bytes (retry) */
        return -2;
    }
    cli();
    uint8_t bytes_into_fifo = fifoBuf_putData(&tx_buffer, buffer, len);
    sei();
    if (bytes_into_fifo > 0)
    {
        /* More data has been put in the tx buffer, make sure the tx is started */
        UCSR0B |= _BV(UDRIE0);
    }
    return (bytes_into_fifo);
}
Пример #7
0
data_type fifoBuf_putByte(t_fifo_buffer *buf, const uint8_t b)
{       // add a data byte to the buffer

    data_type wr = buf->wr;
    data_type buf_size = buf->buf_size;
    uint8_t *buff = buf->buf_ptr;

    data_type num_bytes = fifoBuf_getFree(buf);
    if (num_bytes < 1)
        return 0;

    buff[wr] = b;
    if (++wr >= buf_size)
        wr = 0;

    buf->wr = wr;

    return 1;                   // return number of bytes copied
}
Пример #8
0
/**
* puts a byte onto the receive buffer
* \param[in] USART USART name
* \param[in] b byte which should be put into Rx buffer
* \return 0 if no error
* \return -1 if buffer full (retry)
*/
static int32_t PIOS_USART_RxBufferPut(uint32_t usart_id, uint8_t b)
{
	struct pios_usart_dev * usart_dev = (struct pios_usart_dev *)usart_id;

	bool valid = PIOS_USART_validate(usart_dev);
	PIOS_Assert(valid)

	if (fifoBuf_getFree(&usart_dev->rx) < 1) {
		/* Buffer full (retry) */
		return -1;
	}

	/* Copy received byte into receive buffer */
	/* This operation should be atomic! */
	fifoBuf_putByte(&usart_dev->rx, b);

	/* No error */
	return 0;
}
Пример #9
0
/**
 * Transfer bytes from port buffers into another buffer
 * \param[in] port COM port
 * \returns Byte from buffer
 */
uint16_t PIOS_COM_ReceiveBuffer(uint32_t com_id, uint8_t *buf, uint16_t buf_len, uint32_t timeout_ms)
{
    PIOS_Assert(buf);
    PIOS_Assert(buf_len);
    uint16_t bytes_from_fifo;

    struct pios_com_dev *com_dev = (struct pios_com_dev *)com_id;

    if (!PIOS_COM_validate(com_dev)) {
        /* Undefined COM port for this board (see pios_board.c) */
        PIOS_Assert(0);
    }
    PIOS_Assert(com_dev->has_rx);

check_again:
    bytes_from_fifo = fifoBuf_getData(&com_dev->rx, buf, buf_len);

    if (bytes_from_fifo == 0) {
        /* No more bytes in receive buffer */
        /* Make sure the receiver is running while we wait */
        if (com_dev->driver->rx_start) {
            /* Notify the lower layer that there is now room in the rx buffer */
            (com_dev->driver->rx_start)(com_dev->lower_id,
                                        fifoBuf_getFree(&com_dev->rx));
        }
        if (timeout_ms > 0) {
#if defined(PIOS_INCLUDE_FREERTOS)
            if (xSemaphoreTake(com_dev->rx_sem, timeout_ms / portTICK_RATE_MS) == pdTRUE) {
                /* Make sure we don't come back here again */
                timeout_ms = 0;
                goto check_again;
            }
#else
            PIOS_DELAY_WaitmS(1);
            timeout_ms--;
            goto check_again;
#endif
        }
    }

    /* Return received byte */
    return bytes_from_fifo;
}
Пример #10
0
static uint16_t PIOS_COM_RxInCallback(uint32_t context, uint8_t * buf, uint16_t buf_len, uint16_t * headroom, bool * need_yield)
{
	struct pios_com_dev * com_dev = (struct pios_com_dev *)context;

	bool valid = PIOS_COM_validate(com_dev);
	PIOS_Assert(valid);
	PIOS_Assert(com_dev->has_rx);

	uint16_t bytes_into_fifo = fifoBuf_putData(&com_dev->rx, buf, buf_len);

	if (bytes_into_fifo > 0) {
		/* Data has been added to the buffer */
		PIOS_COM_UnblockRx(com_dev, need_yield);
	}

	if (headroom) {
		*headroom = fifoBuf_getFree(&com_dev->rx);
	}

	return (bytes_into_fifo);
}
Пример #11
0
bool PIOS_BMA180_IRQHandler(void)
{
	bma180_irqs++;
	
	const static uint8_t pios_bma180_req_buf[7] = {BMA_X_LSB_ADDR | 0x80,0,0,0,0,0};
	uint8_t pios_bma180_dmabuf[8];

	// If we can't get the bus then just move on for efficiency
	bool woken = false;
	if(PIOS_BMA180_ClaimBusISR(&woken) != 0) {
		return woken; // Something else is using bus, miss this data
	}
		
	PIOS_SPI_TransferBlock(dev->spi_id,pios_bma180_req_buf,(uint8_t *) pios_bma180_dmabuf, 
							   sizeof(pios_bma180_dmabuf), NULL);

	// TODO: Make this conversion depend on configuration scale
	struct pios_bma180_data data;
	
	// Don't release bus till data has copied
	PIOS_BMA180_ReleaseBus(&woken);
	
	// Must not return before releasing bus
	if(fifoBuf_getFree(&dev->fifo) < sizeof(data))
		return woken;
	
	// Bottom two bits indicate new data and are constant zeros.  Don't right 
	// shift because it drops sign bit
	data.x = ((pios_bma180_dmabuf[2] << 8) | pios_bma180_dmabuf[1]);
	data.y = ((pios_bma180_dmabuf[4] << 8) | pios_bma180_dmabuf[3]);
	data.z = ((pios_bma180_dmabuf[6] << 8) | pios_bma180_dmabuf[5]);
	data.x /= 4;
	data.y /= 4;
	data.z /= 4;
	data.temperature = pios_bma180_dmabuf[7];
	
	fifoBuf_putData(&dev->fifo, (uint8_t *) &data, sizeof(data));
	
	return woken;
}