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; }
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); }
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; }
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); }
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; }
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; }
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; }
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); }
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; }
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; }
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); }
void nrf24l01p_stop(nrf24l01p_t *dev) { hwtimer_spin(DELAY_CS_TOGGLE_TICKS); gpio_clear(dev->ce); }