From e4ae8e23fc3192ab877add5b73ec721b7345b1a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Hru=C5=A1ka?= Date: Sun, 8 Apr 2018 21:23:24 +0200 Subject: [PATCH] working nordic comm, tested. May need cleaning --- comm/iface_nordic.c | 20 +++--- comm/interfaces.c | 9 +++ comm/interfaces.h | 2 + comm/messages.c | 3 +- comm/nrf.c | 144 +++++++++++++++++++++++++++----------------- comm/nrf.h | 8 +-- gex.mk | 2 +- 7 files changed, 118 insertions(+), 70 deletions(-) diff --git a/comm/iface_nordic.c b/comm/iface_nordic.c index 1c152e1..4b16c14 100644 --- a/comm/iface_nordic.c +++ b/comm/iface_nordic.c @@ -9,10 +9,11 @@ #include "nrf.h" #include "unit_base.h" #include "system_settings.h" +#include "utils/hexdump.h" extern osSemaphoreId semVcomTxReadyHandle; -#define RX_PIPE_NUM 1 +#define RX_PIPE_NUM 0 void iface_nordic_claim_resources(void) { @@ -45,16 +46,18 @@ 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] ---"); uint8_t pipenum; uint8_t count = NRF_ReceivePacket(rx_buffer, &pipenum); if (count > 0) { - dbg("NRF RX %d bytes", (int)count); + 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) @@ -75,10 +78,11 @@ bool iface_nordic_init(void) LL_SPI_Disable(NRF_SPI); { - LL_SPI_SetBaudRatePrescaler(NRF_SPI, LL_SPI_BAUDRATEPRESCALER_DIV8); + 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_2EDGE); + 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); @@ -128,7 +132,8 @@ void iface_nordic_deinit(void) hw_deinit_pin_rsc(NRF_R_IRQ); } -#define MAX_RETRY 8 +// FIXME +#define MAX_RETRY 5 void iface_nordic_transmit(const uint8_t *buff, uint32_t len) { @@ -137,11 +142,12 @@ void iface_nordic_transmit(const uint8_t *buff, uint32_t len) 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 += 5; // longer delay next time + delay *= 2; // longer delay next time } else { break; } @@ -156,7 +162,7 @@ void iface_nordic_transmit(const uint8_t *buff, uint32_t len) } if (suc) { - dbg("+ NRF Tx OK!"); + dbg_nrf("+ NRF Tx OK!"); } else { dbg("- NRF sending failed"); } diff --git a/comm/interfaces.c b/comm/interfaces.c index 595beec..0ab281c 100644 --- a/comm/interfaces.c +++ b/comm/interfaces.c @@ -16,6 +16,15 @@ #include "iface_usb.h" #include "iface_nordic.h" +const char * COMPORT_NAMES[] = { + "NONE", + "USB", + "UART", + "NRF", + "LORA", +}; + + enum ComportSelection gActiveComport = COMPORT_USB; // start with USB so the handlers work correctly initially static uint32_t last_switch_time = 0; // started with USB diff --git a/comm/interfaces.h b/comm/interfaces.h index 5d65766..fe56abe 100644 --- a/comm/interfaces.h +++ b/comm/interfaces.h @@ -15,6 +15,8 @@ enum ComportSelection { COMPORT_LORA = 4, }; +extern const char * COMPORT_NAMES[]; + /** * The currently active communication port */ diff --git a/comm/messages.c b/comm/messages.c index 77c399d..170d8b9 100644 --- a/comm/messages.c +++ b/comm/messages.c @@ -11,6 +11,7 @@ #include "framework/system_settings.h" #include "utils/malloc_safe.h" #include "platform/status_led.h" +#include "interfaces.h" static TinyFrame tf_; TinyFrame *comm = &tf_; @@ -23,7 +24,7 @@ TinyFrame *comm = &tf_; static TF_Result lst_ping(TinyFrame *tf, TF_Msg *msg) { com_respond_snprintf(msg->frame_id, MSG_SUCCESS, - "GEX v%s on %s", GEX_VERSION, GEX_PLATFORM); + "GEX v%s on %s (%s)", GEX_VERSION, GEX_PLATFORM, COMPORT_NAMES[gActiveComport]); return TF_STAY; } diff --git a/comm/nrf.c b/comm/nrf.c index 985538d..97da551 100644 --- a/comm/nrf.c +++ b/comm/nrf.c @@ -53,13 +53,17 @@ do { \ #define _delay_us(n) __asm_loop((n)*8) static inline void CE(bool level) { + __asm_loop(1); if (level) LL_GPIO_SetOutputPin(NRF_CE_GPIO_Port, NRF_CE_Pin); else LL_GPIO_ResetOutputPin(NRF_CE_GPIO_Port, NRF_CE_Pin); + __asm_loop(1); } static inline void NSS(bool level) { + __asm_loop(1); if (level) LL_GPIO_SetOutputPin(NRF_NSS_GPIO_Port, NRF_NSS_Pin); else LL_GPIO_ResetOutputPin(NRF_NSS_GPIO_Port, NRF_NSS_Pin); + __asm_loop(1); } static uint8_t spi(uint8_t tx) { @@ -136,9 +140,6 @@ static uint8_t spi(uint8_t tx) { RD_CONFIG_EN_CRC | \ RD_CONFIG_CRCO) -#define CEHIGH CE(1) -#define CELOW CE(0) - static inline uint8_t CS(uint8_t hl) { if (hl == 1) { @@ -166,7 +167,21 @@ static uint8_t NRF_WriteRegister(uint8_t reg, uint8_t value) status = spi(CMD_WRITE_REG | reg); spi(value); } - dbg("Wr[0x%02x] := 0x%02x", (int)reg, (int) value); + dbg_nrf("Wr[0x%02x] := 0x%02x", (int)reg, (int) value); + + + uint8_t reg_val = 0; + CHIPSELECT { + spi(CMD_READ_REG | reg); + reg_val = spi(0); + } + dbg_nrf(" verify 0x%02x", (int)reg_val); + if (reg_val != value) + dbg_nrf(" !!!"); + else + dbg_nrf(" OK"); + + return status; } @@ -177,7 +192,7 @@ static uint8_t NRF_ReadRegister(uint8_t reg) spi(CMD_READ_REG | reg); reg_val = spi(0); } - dbg("Rd[0x%02x] = 0x%02x", (int)reg, (int) reg_val); + dbg_nrf("Rd[0x%02x] = 0x%02x", (int)reg, (int) reg_val); return reg_val; } @@ -218,12 +233,17 @@ void NRF_SetBaseAddress(const uint8_t *Bytes4) { memcpy(nrf_base_address, Bytes4, 4); nrf_base_address[4] = 0; + + // write it to the two full-width address registers + NRF_WriteBuffer(RG_RX_ADDR_P0, nrf_base_address, 5); + nrf_base_address[4] = 1;// to be different + NRF_WriteBuffer(RG_RX_ADDR_P1, nrf_base_address, 5); } void NRF_SetRxAddress(uint8_t pipenum, uint8_t AddrByte) { if (pipenum > 5) { - dbg("!! bad pipe %d", pipenum); + dbg_nrf("!! bad pipe %d", pipenum); return; } @@ -231,13 +251,13 @@ void NRF_SetRxAddress(uint8_t pipenum, uint8_t AddrByte) nrf_pipe_addr[pipenum] = AddrByte; - dbg("Set Rx addr (pipe %d) = 0x%02x", (int)pipenum, AddrByte); + dbg_nrf("Set Rx addr (pipe %d) = 0x%02x", (int)pipenum, AddrByte); if (pipenum == 0) { - dbg("W ADDR_PA0: %02X-%02X-%02X-%02X-%02X", nrf_base_address[0], nrf_base_address[1], nrf_base_address[2], nrf_base_address[3], nrf_base_address[4]); + dbg_nrf("W ADDR_PA0: %02X-%02X-%02X-%02X-%02X", nrf_base_address[0], nrf_base_address[1], nrf_base_address[2], nrf_base_address[3], nrf_base_address[4]); NRF_WriteBuffer(RG_RX_ADDR_P0, nrf_base_address, 5); } else if (pipenum == 1) { - dbg("W ADDR_PA1: %02X-%02X-%02X-%02X-%02X", nrf_base_address[0], nrf_base_address[1], nrf_base_address[2], nrf_base_address[3], nrf_base_address[4]); + dbg_nrf("W ADDR_PA1: %02X-%02X-%02X-%02X-%02X", nrf_base_address[0], nrf_base_address[1], nrf_base_address[2], nrf_base_address[3], nrf_base_address[4]); NRF_WriteBuffer(RG_RX_ADDR_P1, nrf_base_address, 5); } else { @@ -275,6 +295,7 @@ uint8_t NRF_Addr2PipeNum(uint8_t addr) void NRF_EnablePipe(uint8_t pipenum) { + dbg_nrf("Enable pipe num %d", (int)pipenum); uint8_t enabled = NRF_ReadRegister(RG_EN_RXADDR); enabled |= 1 << pipenum; NRF_WriteRegister(RG_EN_RXADDR, enabled); @@ -295,34 +316,39 @@ static void NRF_SetTxAddress(uint8_t SendTo) { nrf_base_address[4] = SendTo; - dbg("W Tx_ADDR + Rx0: %02X-%02X-%02X-%02X-%02X", nrf_base_address[0], nrf_base_address[1], nrf_base_address[2], nrf_base_address[3], nrf_base_address[4]); + dbg_nrf("W Tx_ADDR + Rx0: %02X-%02X-%02X-%02X-%02X", + nrf_base_address[0], nrf_base_address[1], nrf_base_address[2], nrf_base_address[3], nrf_base_address[4]); + NRF_WriteBuffer(RG_TX_ADDR, nrf_base_address, 5); NRF_WriteBuffer(RG_RX_ADDR_P0, nrf_base_address, 5); // the ACK will come to pipe 0 } void NRF_PowerDown(void) { - dbg("PDn"); - CELOW; + dbg_nrf("PDn"); + CE(0); NRF_WriteRegister(RG_CONFIG, ModeBits); } void NRF_ModeTX(void) { - dbg("Tx Mode"); + dbg_nrf("Tx Mode"); - CELOW; + CE(0); uint8_t m = NRF_ReadRegister(RG_CONFIG); NRF_WriteRegister(RG_CONFIG, ModeBits | RD_CONFIG_PWR_UP); - if ((m & RD_CONFIG_PWR_UP) == 0) LL_mDelay(5); + if ((m & RD_CONFIG_PWR_UP) == 0) { + // switching on + LL_mDelay(5); + } } void NRF_ModeRX(void) { - dbg("Rx Mode"); + dbg_nrf("Rx Mode"); NRF_WriteRegister(RG_CONFIG, ModeBits | RD_CONFIG_PWR_UP | RD_CONFIG_PRIM_RX); NRF_SetRxAddress(0, nrf_pipe_addr[0]); // set the P0 address - it was changed during Rx for ACK reception - CEHIGH; + CE(1); //if ((m&2)==0) LL_mDelay()(5); You don't need to wait. Just nothing will come for 5ms or more } @@ -360,7 +386,9 @@ uint8_t NRF_ReceivePacket(uint8_t *Packet, uint8_t *PipeNum) uint8_t pw = 0, status; if (!NRF_IsRxPacket()) return 0; - CELOW; + const uint8_t orig_conf = NRF_ReadRegister(RG_CONFIG); + CE(0); // quit Rx mode - go idle + CHIPSELECT { status = spi(CMD_RD_RX_PL_WIDTH); pw = spi(0); @@ -370,19 +398,25 @@ uint8_t NRF_ReceivePacket(uint8_t *Packet, uint8_t *PipeNum) CHIPSELECT { spi(CMD_FLUSH_RX); } - NRF_WriteRegister(RG_STATUS, RD_STATUS_RX_DR); - return 0; + pw = 0; + } else { + // Read the reception pipe number + *PipeNum = ((status & RD_STATUS_RX_PNO) >> 1); + CHIPSELECT { + spi(CMD_RD_RX_PLD); + for (uint8_t i = 0; i < pw; i++) Packet[i] = spi(0); + } } + NRF_WriteRegister(RG_STATUS, RD_STATUS_RX_DR); // Clear the RX_DR interrupt - // Read the reception pipe number - *PipeNum = (status & RD_STATUS_RX_PNO) >> 1; - - CHIPSELECT { - spi(CMD_RD_RX_PLD); - for (uint8_t i = 0; i < pw; i++) Packet[i] = spi(0); + if ((orig_conf & RD_CONFIG_PWR_UP) == 0) { + dbg_nrf("going back PwrDn"); + NRF_PowerDown(); + } + else if ((orig_conf & RD_CONFIG_PRIM_RX) == RD_CONFIG_PRIM_RX) { + dbg_nrf("going back PwrUp+Rx"); + NRF_ModeRX(); } - NRF_WriteRegister(RG_STATUS, RD_STATUS_RX_DR); // Clear the RX_DR interrupt - CEHIGH; return pw; } @@ -395,14 +429,16 @@ bool NRF_IsRxPacket(void) bool NRF_SendPacket(uint8_t PipeNum, const uint8_t *Packet, uint8_t Length) { if (!nrf_pipe_enabled[PipeNum]) { - dbg("!! Pipe %d not enabled", PipeNum); + dbg_nrf("!! Pipe %d not enabled", PipeNum); return 0; } + dbg_nrf("Will tx to addr %02x", nrf_pipe_addr[PipeNum]); + const uint8_t orig_conf = NRF_ReadRegister(RG_CONFIG); - CELOW; + CE(0); NRF_ModeTX(); // Make sure in TX mode - NRF_SetTxAddress(nrf_pipe_addr[PipeNum]); + NRF_SetTxAddress(nrf_pipe_addr[PipeNum]); // this sets the Tx addr and also pipe 0 addr for ACK CHIPSELECT { spi(CMD_FLUSH_TX); @@ -413,58 +449,56 @@ bool NRF_SendPacket(uint8_t PipeNum, const uint8_t *Packet, uint8_t Length) for (uint8_t i = 0; i < Length; i++) spi(Packet[i]); }; - CEHIGH; - _delay_us(15); // At least 10 us - CELOW; + // CE pulse + CE(1); + _delay_us(20); // At least 10 us + CE(0); uint8_t st = 0; while ((st & (RD_STATUS_MAX_RT|RD_STATUS_TX_DS)) == 0) { st = NRF_ReadStatus(); // Packet acked or timed out } - dbg("Send status: MAX_RT %d, SENT %d", (st&RD_STATUS_MAX_RT) != 0, (st&RD_STATUS_TX_DS) != 0); + dbg_nrf("Send status: 0x%02x - MAX_RT %d, SENT %d", (int)st, + (st&RD_STATUS_MAX_RT) != 0, (st&RD_STATUS_TX_DS) != 0); NRF_WriteRegister(RG_STATUS, st & (RD_STATUS_MAX_RT|RD_STATUS_TX_DS)); // Clear the bit if ((orig_conf & RD_CONFIG_PWR_UP) == 0) { - dbg("going back PwrDn"); + dbg_nrf("going back PwrDn"); NRF_PowerDown(); } else if ((orig_conf & RD_CONFIG_PRIM_RX) == RD_CONFIG_PRIM_RX) { - dbg("going back PwrUp+Rx"); + dbg_nrf("going back PwrUp+Rx"); NRF_ModeRX(); } return 0 != (st & RD_STATUS_TX_DS); // success } -void NRF_Reset(void) +void NRF_Init(uint8_t pSpeed) { + // Set the required output pins NSS(1); - CELOW; - NRF_PowerDown(); + CE(0); - NRF_WriteRegister(RG_EN_RXADDR, 0); // disable all pipes + LL_mDelay(200); for (int i = 0; i < 6; i++) { nrf_pipe_addr[i] = 0; nrf_pipe_enabled[i] = 0; } -} -void NRF_Init(uint8_t pSpeed) -{ - // Set the required output pins - NSS(1); - CELOW; - - LL_mDelay(200); + // clear flags etc + NRF_PowerDown(); + CHIPSELECT { spi(CMD_FLUSH_RX); } + CHIPSELECT { spi(CMD_FLUSH_TX); } + NRF_WriteRegister(RG_STATUS, 0x70); NRF_WriteRegister(RG_CONFIG, ModeBits); NRF_WriteRegister(RG_SETUP_AW, 0b11); // 5 byte addresses - // default -// NRF_EnablePipe(0); + NRF_WriteRegister(RG_EN_RXADDR, 0x01); // disable all, enable pipe 0 - this is required for shockburst, despite not being specified in the DS NRF_WriteRegister(RG_SETUP_RETR, 0x18); // 8 retries NRF_WriteRegister(RG_RF_CH, 2); // channel 2 NO HIGHER THAN 83 in USA! @@ -474,9 +508,7 @@ void NRF_Init(uint8_t pSpeed) NRF_WriteRegister(RG_DYNPD, 0b111111); // Dynamic packet length NRF_WriteRegister(RG_FEATURE, 0b100); // Enable dynamic payload, and no payload in the ack. - for (int i = 0; i < 6; i++) { - NRF_WriteRegister(RG_RX_PW_P0+i, 32); // Receive 32 byte packets - XXX this is probably not needed with dynamic length - } - - //NRFModePowerDown(); // Already in power down mode, dummy +// for (int i = 0; i < 6; i++) { +// NRF_WriteRegister(RG_RX_PW_P0+i, 32); // Receive 32 byte packets - XXX this is probably not needed with dynamic length +// } } diff --git a/comm/nrf.h b/comm/nrf.h index a2e1dc2..e671d71 100644 --- a/comm/nrf.h +++ b/comm/nrf.h @@ -23,6 +23,9 @@ #include "resources.h" #include "nrf_pins.h" +#define dbg_nrf(...) do{}while(0) +//#define dbg_nrf(...) dbg(##__VA_ARGS__) + // Initialize SPI and the Nordic /** @@ -103,11 +106,6 @@ uint8_t NRF_PipeNum2Addr(uint8_t pipe_num); */ uint8_t NRF_Addr2PipeNum(uint8_t addr); -/** - * Reset as much as possible (incl. removing pipes) - */ -void NRF_Reset(void); - /** * Send a packet (takes care of mode switching etc) * diff --git a/gex.mk b/gex.mk index 5921c08..8fbd5e4 100644 --- a/gex.mk +++ b/gex.mk @@ -95,7 +95,7 @@ GEX_CDEFS = $(GEX_CDEFS_BASE) \ -DDEBUG_VFS=0 \ -DDEBUG_FLASH_WRITE=0 \ -DVERBOSE_HARDFAULT=1 \ - -DUSE_STACK_MONITOR=1 \ + -DUSE_STACK_MONITOR=0 \ -DUSE_DEBUG_UART=1 \ -DDEBUG_MALLOC=0 \ -DDEBUG_RSC=0