Пример #1
0
int vtimer_sleep(timex_t time)
{
    /**
     * Use spin lock for short periods.
     * Assumes that hardware timer ticks are shorter than a second.
     */
    if (time.seconds == 0) {
        unsigned long ticks = HWTIMER_TICKS(time.microseconds);
        if (ticks <= HWTIMER_SPIN_BARRIER) {
            hwtimer_spin(ticks);
            return 0;
        }
    }

    int ret;
    vtimer_t t;
    mutex_t mutex = MUTEX_INIT;
    mutex_lock(&mutex);

    t.action = vtimer_callback_unlock;
    t.arg = &mutex;
    t.absolute = time;

    ret = vtimer_set(&t);
    mutex_lock(&mutex);
    return ret;
}
Пример #2
0
int nrf24l01p_set_address_width(nrf24l01p_t *dev, nrf24l01p_aw_t aw)
{
    char aw_setup;
    nrf24l01p_read_reg(dev, REG_SETUP_AW, &aw_setup);

    hwtimer_spin(DELAY_AFTER_FUNC_TICKS);

    switch (aw) {
        case NRF24L01P_AW_3BYTE:
            aw_setup &= ~(3);
            aw_setup |= 1;
            break;

        case NRF24L01P_AW_4BYTE:
            aw_setup &= ~(3);
            aw_setup |= 2;
            break;

        case NRF24L01P_AW_5BYTE:
            aw_setup &= ~(3);
            aw_setup |= 3;
            break;

        default:
            return -1;
    }

    return nrf24l01p_write_reg(dev, REG_SETUP_AW, aw_setup);
}
Пример #3
0
int nrf24l01p_read_payload(nrf24l01p_t *dev, char *answer, unsigned int size)
{
    int status;

    /* Acquire exclusive access to the bus. */
    spi_acquire(dev->spi);
    gpio_clear(dev->cs);
    hwtimer_spin(DELAY_CS_TOGGLE_TICKS);
    status = spi_transfer_regs(dev->spi, CMD_R_RX_PAYLOAD, 0, answer, size);
    hwtimer_spin(DELAY_CS_TOGGLE_TICKS);
    gpio_set(dev->cs);
    hwtimer_spin(DELAY_AFTER_FUNC_TICKS);
    /* Release the bus for other threads. */
    spi_release(dev->spi);

    return status;
}
Пример #4
0
void nrf24l01p_transmit(nrf24l01p_t *dev)
{
    gpio_set(dev->ce);
    hwtimer_wait(DELAY_CE_HIGH_US); /* at least 10 us high */
    gpio_clear(dev->ce);

    hwtimer_spin(DELAY_CHANGE_TXRX_US);
}
Пример #5
0
int nrf24l01p_set_tx_address(nrf24l01p_t *dev, char *saddr, unsigned int length)
{
    int status;

    /* Acquire exclusive access to the bus. */
    spi_acquire(dev->spi);
    gpio_clear(dev->cs);
    hwtimer_spin(DELAY_CS_TOGGLE_TICKS);
    status = spi_transfer_regs(dev->spi, (CMD_W_REGISTER | (REGISTER_MASK & REG_TX_ADDR)), saddr, NULL, length); /* address width is 5 byte */
    hwtimer_spin(DELAY_CS_TOGGLE_TICKS);
    gpio_set(dev->cs);
    /* Release the bus for other threads. */
    spi_release(dev->spi);

    hwtimer_spin(DELAY_AFTER_FUNC_TICKS);

    return status;
}
Пример #6
0
int nrf24l01p_read_reg(nrf24l01p_t *dev, char reg, char *answer)
{
    int status;

    /* Acquire exclusive access to the bus. */
    spi_acquire(dev->spi);
    gpio_clear(dev->cs);
    hwtimer_spin(DELAY_CS_TOGGLE_TICKS);
    status = spi_transfer_reg(dev->spi, (CMD_R_REGISTER | (REGISTER_MASK & reg)), CMD_NOP, answer);
    hwtimer_spin(DELAY_CS_TOGGLE_TICKS);
    gpio_set(dev->cs);
    /* Release the bus for other threads. */
    spi_release(dev->spi);

    hwtimer_spin(DELAY_AFTER_FUNC_TICKS);

    return status;
}
Пример #7
0
int nrf24l01p_preload(nrf24l01p_t *dev, char *data, unsigned int size)
{
    int status;

    size = (size <= 32) ? size : 32;

    /* Acquire exclusive access to the bus. */
    spi_acquire(dev->spi);
    gpio_clear(dev->cs);
    hwtimer_spin(DELAY_CS_TOGGLE_TICKS);
    status = spi_transfer_regs(dev->spi, CMD_W_TX_PAYLOAD, data, NULL, size);
    hwtimer_spin(DELAY_CS_TOGGLE_TICKS);
    gpio_set(dev->cs);
    /* Release the bus for other threads. */
    spi_release(dev->spi);

    hwtimer_spin(DELAY_AFTER_FUNC_TICKS);

    return status;
}
Пример #8
0
void hwtimer_wait(unsigned long ticks)
{
    DEBUG("hwtimer_wait ticks=%lu\n", ticks);

    mutex_t mutex;

    if (ticks <= 6 || inISR()) {
        hwtimer_spin(ticks);
        return;
    }
    mutex_init(&mutex);
    mutex_lock(&mutex);
    /* -2 is to adjust the real value */
    int res = hwtimer_set(ticks - 2, hwtimer_releasemutex, &mutex);
    if (res == -1) {
        mutex_unlock(&mutex);
        hwtimer_spin(ticks);
        return;
    }

    /* try to lock mutex again will cause the thread to go into
     * STATUS_MUTEX_BLOCKED until hwtimer fires the releasemutex */
    mutex_lock(&mutex);
}
Пример #9
0
static int nvram_spi_write(nvram_t *dev, uint8_t *src, uint32_t dst, size_t len)
{
    nvram_spi_params_t *spi_dev = (nvram_spi_params_t *) dev->extra;
    int status;
    union {
        uint32_t u32;
        char c[4];
    } addr;
    /* Address is expected by the device as big-endian, i.e. network byte order,
     * we utilize the network byte order macros here. */
    addr.u32 = HTONL(dst);
    /* Acquire exclusive bus access */
    spi_acquire(spi_dev->spi);
    /* Assert CS */
    gpio_clear(spi_dev->cs);
    /* Enable writes */
    status = spi_transfer_byte(spi_dev->spi, NVRAM_SPI_CMD_WREN, NULL);
    if (status < 0)
    {
        return status;
    }
    /* Release CS */
    gpio_set(spi_dev->cs);
    hwtimer_spin(NVRAM_SPI_CS_TOGGLE_TICKS);
    /* Re-assert CS */
    gpio_clear(spi_dev->cs);
    /* Write command and address */
    status = spi_transfer_regs(spi_dev->spi, NVRAM_SPI_CMD_WRITE,
                      &addr.c[sizeof(addr.c) - spi_dev->address_count], NULL,
                      spi_dev->address_count);
    if (status < 0)
    {
        return status;
    }
    /* Keep holding CS and write data */
    status = spi_transfer_bytes(spi_dev->spi, (char *)src, NULL, len);
    if (status < 0)
    {
        return status;
    }
    /* Release CS */
    gpio_set(spi_dev->cs);
    /* Release exclusive bus access */
    spi_release(spi_dev->spi);
    return status;
}
Пример #10
0
static int nvram_spi_write_9bit_addr(nvram_t *dev, uint8_t *src, uint32_t dst, size_t len)
{
    nvram_spi_params_t *spi_dev = (nvram_spi_params_t *) dev->extra;
    int status;
    uint8_t cmd;
    uint8_t addr;
    cmd = NVRAM_SPI_CMD_WRITE;
    /* The upper address bit is mixed into the command byte on certain devices,
     * probably just to save a byte in the SPI transfer protocol. */
    if (dst > 0xff) {
        cmd |= 0x08;
    }
    /* LSB of address */
    addr = (dst & 0xff);
    spi_acquire(spi_dev->spi);
    gpio_clear(spi_dev->cs);
    /* Enable writes */
    status = spi_transfer_byte(spi_dev->spi, NVRAM_SPI_CMD_WREN, NULL);
    if (status < 0)
    {
        return status;
    }
    gpio_set(spi_dev->cs);
    hwtimer_spin(NVRAM_SPI_CS_TOGGLE_TICKS);
    gpio_clear(spi_dev->cs);
    /* Write command and address */
    status = spi_transfer_reg(spi_dev->spi, cmd, addr, NULL);
    if (status < 0)
    {
        return status;
    }
    /* Keep holding CS and write data */
    status = spi_transfer_bytes(spi_dev->spi, (char *)src, NULL, len);
    if (status < 0)
    {
        return status;
    }
    gpio_set(spi_dev->cs);
    spi_release(spi_dev->spi);
    /* status contains the number of bytes actually written to the SPI bus. */
    return status;
}
Пример #11
0
int nrf24l01p_init(nrf24l01p_t *dev, spi_t spi, gpio_t ce, gpio_t cs, gpio_t irq)
{
    int status;
    char INITIAL_TX_ADDRESS[] =  {0xe7, 0xe7, 0xe7, 0xe7, 0xe7,};
    char INITIAL_RX_ADDRESS[] =  {0xe7, 0xe7, 0xe7, 0xe7, 0xe7,};

    dev->spi = spi;
    dev->ce = ce;
    dev->cs = cs;
    dev->irq = irq;
    dev->listener = KERNEL_PID_UNDEF;

    /* Init CE pin */
    gpio_init_out(dev->ce, GPIO_NOPULL);

    /* Init CS pin */
    gpio_init_out(dev->cs, GPIO_NOPULL);
    gpio_set(dev->cs);

    /* Init IRQ pin */
    gpio_init_int(dev->irq, GPIO_PULLUP, GPIO_FALLING, nrf24l01p_rx_cb, dev);


    /* Init SPI */
    spi_poweron(dev->spi);
    spi_acquire(dev->spi);
    status = spi_init_master(dev->spi, SPI_CONF_FIRST_RISING, SPI_SPEED_400KHZ);
    spi_release(dev->spi);

    if (status < 0) {
        return status;
    }

    hwtimer_spin(DELAY_AFTER_FUNC_TICKS);

    /* Flush TX FIFIO */
    status = nrf24l01p_flush_tx_fifo(dev);

    if (status < 0) {
        return status;
    }

    /* Flush RX FIFIO */
    status = nrf24l01p_flush_tx_fifo(dev);

    if (status < 0) {
        return status;
    }

    /* Setup adress width */
    status = nrf24l01p_set_address_width(dev, NRF24L01P_AW_5BYTE);

    if (status < 0) {
        return status;
    }

    /* Setup payload width */
    status = nrf24l01p_set_payload_width(dev, NRF24L01P_PIPE0, NRF24L01P_MAX_DATA_LENGTH);

    if (status < 0) {
        return status;
    }

    /* Set RF channel */
    status = nrf24l01p_set_channel(dev, INITIAL_RF_CHANNEL);

    if (status < 0) {
        return status;
    }

    /* Set RF power */
    status = nrf24l01p_set_power(dev, 0);

    if (status < 0) {
        return status;
    }

    /* Set RF datarate */
    status = nrf24l01p_set_datarate(dev, NRF24L01P_DR_250KBS);

    if (status < 0) {
        return status;
    }

    /* Set TX Address */
    status = nrf24l01p_set_tx_address(dev, INITIAL_TX_ADDRESS, INITIAL_ADDRESS_WIDTH);

    if (status < 0) {
        return status;
    }

    /* Set RX Adress */
    status = nrf24l01p_set_rx_address(dev, NRF24L01P_PIPE0, INITIAL_RX_ADDRESS, INITIAL_ADDRESS_WIDTH);

    if (status < 0) {
        return status;
    }

    /* Reset auto ack for all pipes */
    status = nrf24l01p_disable_all_auto_ack(dev);

    if (status < 0) {
        return status;
    }

    /* Setup Auto ACK and retransmission */
    status = nrf24l01p_setup_auto_ack(dev, NRF24L01P_PIPE0, NRF24L01P_RETR_750US, 15);

    if (status < 0) {
        return status;
    }

    /* Setup CRC */
    status = nrf24l01p_enable_crc(dev, NRF24L01P_CRC_2BYTE);

    if (status < 0) {
        return status;
    }

    /* Reset all interrupt flags */
    status = nrf24l01p_reset_all_interrupts(dev);

    if (status < 0) {
        return status;
    }

    return nrf24l01p_on(dev);
}
Пример #12
0
void nrf24l01p_stop(nrf24l01p_t *dev)
{
    hwtimer_spin(DELAY_CS_TOGGLE_TICKS);
    gpio_clear(dev->ce);
}