You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
175 lines
5.1 KiB
175 lines
5.1 KiB
//
|
|
// Created by MightyPork on 2018/04/06.
|
|
//
|
|
|
|
#include "iface_nordic.h"
|
|
#include "nrf_pins.h"
|
|
#include "resources.h"
|
|
#include "hw_utils.h"
|
|
#include "nrf.h"
|
|
#include "unit_base.h"
|
|
#include "system_settings.h"
|
|
#include "utils/hexdump.h"
|
|
|
|
extern osSemaphoreId semVcomTxReadyHandle;
|
|
|
|
#define RX_PIPE_NUM 0
|
|
|
|
void iface_nordic_claim_resources(void)
|
|
{
|
|
assert_param(E_SUCCESS == rsc_claim(&UNIT_SYSTEM, NRF_R_SPI));
|
|
assert_param(E_SUCCESS == rsc_claim(&UNIT_SYSTEM, NRF_R_CE));
|
|
assert_param(E_SUCCESS == rsc_claim(&UNIT_SYSTEM, NRF_R_NSS));
|
|
assert_param(E_SUCCESS == rsc_claim(&UNIT_SYSTEM, NRF_R_IRQ));
|
|
assert_param(E_SUCCESS == rsc_claim(&UNIT_SYSTEM, NRF_R_MISO));
|
|
assert_param(E_SUCCESS == rsc_claim(&UNIT_SYSTEM, NRF_R_MOSI));
|
|
assert_param(E_SUCCESS == rsc_claim(&UNIT_SYSTEM, NRF_R_SCK));
|
|
|
|
assert_param(E_SUCCESS == rsc_claim(&UNIT_SYSTEM, R_EXTI0+NRF_EXTI_LINENUM));
|
|
}
|
|
|
|
void iface_nordic_free_resources(void)
|
|
{
|
|
rsc_free(&UNIT_SYSTEM, NRF_R_SPI);
|
|
rsc_free(&UNIT_SYSTEM, NRF_R_CE);
|
|
rsc_free(&UNIT_SYSTEM, NRF_R_NSS);
|
|
rsc_free(&UNIT_SYSTEM, NRF_R_IRQ);
|
|
rsc_free(&UNIT_SYSTEM, NRF_R_MISO);
|
|
rsc_free(&UNIT_SYSTEM, NRF_R_MOSI);
|
|
rsc_free(&UNIT_SYSTEM, NRF_R_SCK);
|
|
|
|
rsc_free(&UNIT_SYSTEM, R_EXTI0+NRF_EXTI_LINENUM);
|
|
}
|
|
|
|
static uint8_t rx_buffer[32];
|
|
|
|
static void NrfIrqHandler(void *arg)
|
|
{
|
|
LL_EXTI_ClearFlag_0_31(LL_EXTI_LINES[NRF_EXTI_LINENUM]);
|
|
dbg_nrf("[EXTI] ---");
|
|
|
|
while (NRF_IsRxPacket()) {
|
|
uint8_t pipenum;
|
|
uint8_t count = NRF_ReceivePacket(rx_buffer, &pipenum);
|
|
if (count > 0) {
|
|
dbg_nrf("NRF RX %d bytes", (int) count);
|
|
rxQuePostMsg(rx_buffer, count);
|
|
}
|
|
else {
|
|
dbg("IRQ but no Rx");
|
|
}
|
|
}
|
|
|
|
dbg_nrf("--- end [EXTI]");
|
|
}
|
|
|
|
bool iface_nordic_init(void)
|
|
{
|
|
dbg("Setting up Nordic...");
|
|
|
|
hw_periph_clock_enable(NRF_SPI);
|
|
|
|
// SPI pins
|
|
assert_param(E_SUCCESS == hw_configure_gpiorsc_af(NRF_R_SCK, NRF_SPI_AF));
|
|
assert_param(E_SUCCESS == hw_configure_gpiorsc_af(NRF_R_MOSI, NRF_SPI_AF));
|
|
assert_param(E_SUCCESS == hw_configure_gpiorsc_af(NRF_R_MISO, NRF_SPI_AF));
|
|
|
|
// Manual pins
|
|
LL_GPIO_SetPinMode(NRF_NSS_GPIO_Port, NRF_NSS_Pin, LL_GPIO_MODE_OUTPUT);
|
|
LL_GPIO_SetPinMode(NRF_CE_GPIO_Port, NRF_CE_Pin, LL_GPIO_MODE_OUTPUT);
|
|
LL_GPIO_SetPinMode(NRF_IRQ_GPIO_Port, NRF_IRQ_Pin, LL_GPIO_MODE_INPUT);
|
|
|
|
LL_SPI_Disable(NRF_SPI);
|
|
{
|
|
LL_SPI_SetBaudRatePrescaler(NRF_SPI, LL_SPI_BAUDRATEPRESCALER_DIV32);
|
|
//LL_SPI_BAUDRATEPRESCALER_DIV8
|
|
|
|
LL_SPI_SetClockPolarity(NRF_SPI, LL_SPI_POLARITY_LOW);
|
|
LL_SPI_SetClockPhase(NRF_SPI, LL_SPI_PHASE_1EDGE);
|
|
LL_SPI_SetTransferDirection(NRF_SPI, LL_SPI_FULL_DUPLEX);
|
|
LL_SPI_SetTransferBitOrder(NRF_SPI, LL_SPI_MSB_FIRST);
|
|
|
|
LL_SPI_SetNSSMode(NRF_SPI, LL_SPI_NSS_SOFT);
|
|
LL_SPI_SetDataWidth(NRF_SPI, LL_SPI_DATAWIDTH_8BIT);
|
|
LL_SPI_SetRxFIFOThreshold(NRF_SPI, LL_SPI_RX_FIFO_TH_QUARTER); // trigger RXNE on 1 byte
|
|
|
|
LL_SPI_SetMode(NRF_SPI, LL_SPI_MODE_MASTER);
|
|
}
|
|
LL_SPI_Enable(NRF_SPI);
|
|
|
|
|
|
dbg("configure nrf module");
|
|
|
|
// Now configure the radio
|
|
NRF_Init(NRF_SPEED_2M); // TODO configurable speed
|
|
NRF_SetChannel(SystemSettings.nrf_channel);
|
|
NRF_SetBaseAddress(SystemSettings.nrf_network);
|
|
NRF_SetRxAddress(RX_PIPE_NUM, SystemSettings.nrf_address);
|
|
NRF_EnablePipe(RX_PIPE_NUM);
|
|
NRF_ModeRX();
|
|
|
|
dbg("enable exti");
|
|
// EXTI
|
|
LL_EXTI_EnableIT_0_31(LL_EXTI_LINES[NRF_EXTI_LINENUM]);
|
|
LL_EXTI_EnableFallingTrig_0_31(LL_EXTI_LINES[NRF_EXTI_LINENUM]);
|
|
LL_SYSCFG_SetEXTISource(NRF_SYSCFG_EXTI_PORT, LL_SYSCFG_EXTI_LINES[NRF_EXTI_LINENUM]);
|
|
irqd_attach(EXTIS[NRF_EXTI_LINENUM], NrfIrqHandler, NULL);
|
|
// TODO increase priority in NVIC?
|
|
|
|
dbg("nrf setup done");
|
|
return true;
|
|
}
|
|
|
|
void iface_nordic_deinit(void)
|
|
{
|
|
LL_EXTI_DisableIT_0_31(LL_EXTI_LINES[NRF_EXTI_LINENUM]);
|
|
LL_EXTI_DisableFallingTrig_0_31(LL_EXTI_LINES[NRF_EXTI_LINENUM]);
|
|
irqd_detach(EXTIS[NRF_EXTI_LINENUM], NrfIrqHandler);
|
|
hw_periph_clock_disable(NRF_SPI);
|
|
|
|
hw_deinit_pin_rsc(NRF_R_SCK);
|
|
hw_deinit_pin_rsc(NRF_R_MOSI);
|
|
hw_deinit_pin_rsc(NRF_R_MISO);
|
|
hw_deinit_pin_rsc(NRF_R_NSS);
|
|
hw_deinit_pin_rsc(NRF_R_CE);
|
|
hw_deinit_pin_rsc(NRF_R_IRQ);
|
|
}
|
|
|
|
// FIXME
|
|
#define MAX_RETRY 5
|
|
|
|
void iface_nordic_transmit(const uint8_t *buff, uint32_t len)
|
|
{
|
|
bool suc = false;
|
|
while (len > 0) {
|
|
uint8_t chunk = (uint8_t) MIN(32, len);
|
|
|
|
uint16_t delay = 1;
|
|
//hexDump("Tx chunk", buff, chunk);
|
|
for (int i = 0; i < MAX_RETRY; i++) {
|
|
suc = NRF_SendPacket(RX_PIPE_NUM, buff, chunk); // use the pipe to retrieve the address
|
|
if (!suc) {
|
|
vTaskDelay(delay);
|
|
delay *= 2; // longer delay next time
|
|
} else {
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (!suc) {
|
|
break;
|
|
}
|
|
|
|
buff += chunk;
|
|
len -= chunk;
|
|
}
|
|
|
|
if (suc) {
|
|
dbg_nrf("+ NRF Tx OK!");
|
|
} else {
|
|
dbg("- NRF sending failed");
|
|
}
|
|
|
|
// give when it's done
|
|
xSemaphoreGive(semVcomTxReadyHandle); // similar to how it's done in USB - this is called in the Tx Done handler
|
|
}
|
|
|