SPI Control Issues with EVB1000 & external STM32F407

Hello all,

I’ve been moving my RTLS application to an external STM32F4xx development board & driving the EVB1000 with the external SPI header. Some of my problems I think are to do with the issues discussed in https://groups.google.com/forum/#!topic/decawave_group/7qcBDInP9K8.

Occasionally the DW1000 seems to enter a mode where the MISO pin outputs a very low signal voltage (shown in the attached screen-grab of a id request). I’ve not been able to determine how it gets into this mode (it often shows this as soon as it powers on, but it can transition from working state to non-working). I notice it most often when loading new code via gdb debugger.

Has anyone else seen anything like this? I have a feeling its something electrical rather than a fault with the transceiver.

I’m also having trouble getting TX with timeouts working. When sending a TX message with approx 8ms timeout, the timeout irq triggers immediately after the message is sent. The message is received by other radios, but any subsequent response isn’t received. Still debugging this.

For those also doing this, some of the other stuff I’ve figured out:
The RSTN line isn’t (to my knowledge) routed to the SPI header. S3 switches the rst line off the microprocessor, but doesn’t route it to the header. I was able to access it by soldering a wire to the via connected to the unpopulated R44.
SS1 is routed to the SPICSn pin on the DW1000 (after bridging R43). SS2 and SS3 don’t seem to be connected to anything important.

Scope colour key

CKL: yellow
MOSI: green
MISO: purple
DW1000 IRQ: pink (offset)

Hi Ryan,

I’m trying to use the same hardware as you but I’m not able to communicate with the device, it doesn’t even initialize. could you share part of the code where you set it?

Regarding the irq, if you want to use them from the external connector you need to fit a 0R resistor where R43 is (between J6 external connector and S2 control switch. Maybe you don’t get the signal at all and so the timeout triggers.

Hope this will help.

Thank you.

Fabrizio

Are there any schematics of EVB kit available? It is really hard to help you solve the problem without seeing the design. If not, ask Leo Theunissen maybe he will provide them and you will have clear response to the hardware problems (or at least help us to give you one).

Regarding the software problems, are you using Decawave API or you write your own code? What does it mean you dont get any response? What should you get back? Message or ACK? Are you using frame filtering? If message is seen by other radioS how can they know which one should respond?

Regards,
Bartosz

What sort of initalisation problem are you getting Fabrizio? Have you confirmed your SPI comms are working by reading the 0x0 register? I won’t be able to share my code files (I don’t want to take the time scrubbing any IP it may contain), but I can copy in snippets that would be helpful.

At the base I am using the dwt_* api functions from the /decadriver folder in the demo application for the STM32F105. Porting the api was relatively easy, I had to implement 4 functions:
#include <deca_device_api.h>
decaIrqStatus_t decamutexon(void); // outputs a valid input to decamutexoff & disables interrupts for the dw1000 irq
void decamutexoff(decaIrqStatus_t s); // resets interrupt status of dw1000 irq
#include <port.h>
int writetospi_serial(uint16_t headerLength, const uint8_t *headerBuffer, uint32_t bodylength, const uint8_t *bodyBuffer); // writes header & body out to the spi bus
int readfromspi_serial(uint16_t headerLength, const uint8_t *headerBuffer, uint32_t readlength, uint8_t *readBuffer ); // reads readlength from spi bus

I’m using the new HAL library from STM & had a lot of trouble getting SPI configured correctly. In the end I’m driving the CS in software (their hardware CS feature’s documentation is the definition of arcane) but it works quite well.
uint8_t Spi::write(const uint8_t* headerBuffer, uint16_t headerLength, const uint8_t* bodyBuffer, uint16_t bodyLength)
{
cs.reset();

auto ret = SPI_Transmit(handle, headerBuffer, headerLength);
if (ret == HAL_OK)    // don't transmit body if header failed?
{
    ret = SPI_Transmit(handle, bodyBuffer, bodyLength);
}

cs.set();

return ret;

}

uint8_t Spi::read(const uint8_t* headerBuffer, uint16_t headerLength, uint8_t* readBuffer, uint16_t readLength)
{
cs.reset();

auto ret = SPI_Transmit(handle, headerBuffer, headerLength);
if (ret == HAL_OK)    // don't attempt to recieve if the header fails
{
    ret = HAL_SPI_Receive(&handle, readBuffer, readLength, SPI_TIMEOUT);
}

cs.set();

return ret;

}

As for the DW1000 IRQ. I was always getting that signal in correctly (soldered over the R43 point). See the reply to Bartosz for more info…

Bartosz,

My apologies for the vagueness of the description. I’ve had a day of debugging & have some new information. I think I’ve actually solved it while I was preparing some data for this post!

I’m using the decadriver api libraries from the decaranging application, but everything else is a custom application layer (replaces instance and everything above that in the decaranging sample app). I was originally running this code on the STM32F105 on the EVB100, so all the application code is tested working, its mostly the hardware and the changes I’ve made while porting the application that are suspect.

A major problems i discovered was the RSTn switch still active on the EVB1000, so both my F4 and the on-board F105 were able to reset the transceiver… I haven’t seen the MISO level issue sense I switched the RSTn line off, so that may have been the cause.

While debugging yesterday I discovered the application was failing to send a delayed transmit message, returning an error which indicates it was unable to send the delayed message in the correct time. This morning I discovered the application worked when my debugger wasn’t attached. My theory at the moment is the semihosting debug statements I put in while porting the application slowed the execution time enough to miss the delayed transmit window. The semihosting statements weren’t too often (essentially printed at the successful reception of any message, and outside the interrupt routines), but I’m not exactly sure how they work or how much time they eat up.

-Ryan Estep

Thank you for your help Ryan.

The error is probably in their api for using the spi. I was using theirs and didn’t write mine. I’ve found out just yesterday that there is no signal sent so no excange of communication.
I’ll try to fix this. Thank you.

Fabrizio

Be careful in how you setup the SPI and GPIO pins. Their documentation leave a lot to be desired. My MISO level problem turned out to be a hardware fault caused by my mis-configuration of the MISO GPIO pin alternate function.

I discovered yesterday by scoping the DW1000 VDDIOA pin that the voltage was drooping when the MISO line was pulled high (meaning the MISO line was loaded). I had configured the MISO line as a push-pull alternate output when because the STM32F4xx can’t configure the line as an alternate function input (as in the decaranging example code). Even when I realised my mistake and changed the pin to open drain alternate function set high, the gpio pin still loaded the line after a short period of run-time. Thankfully I was able to switch to an alternate MISO pin, and it has been working constantly for the last hour or so.

-Ryan Estep

Here is my spi initialization code. It’s pretty standard, always used this and had never problems.

void SPI2Init(uint16_t scalingfactor)
{
GPIO_InitTypeDef dw1000_gpio_spi_init;
SPI_InitTypeDef dw1000_spi_init;
/* GPIOA clock enable */

SPI_I2S_DeInit(DW1000_SPI);

RCC_AHB1PeriphClockCmd(DW1000_SPI_GPIO_RCC, ENABLE);

dw1000_gpio_spi_init.GPIO_Pin =  DW1000_SPI_Clock_Pin | DW1000_SPI_MISO_Pin | DW1000_SPI_MOSI_Pin;
dw1000_gpio_spi_init.GPIO_Mode = GPIO_Mode_AF;
dw1000_gpio_spi_init.GPIO_OType = GPIO_OType_PP;
dw1000_gpio_spi_init.GPIO_PuPd = GPIO_PuPd_NOPULL;
dw1000_gpio_spi_init.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(DW1000_SPI_Port, &dw1000_gpio_spi_init);

//GPIO_PinAFConfig(GPIOB, GPIO_PinSource12);
GPIO_PinAFConfig(DW1000_SPI_Port, DW1000_PinSource_CLK, DW1000_GPIO_AF);
GPIO_PinAFConfig(DW1000_SPI_Port, DW1000_PinSource_MISO, DW1000_GPIO_AF);
GPIO_PinAFConfig(DW1000_SPI_Port, DW1000_PinSource_MOS1, DW1000_GPIO_AF);

RCC_APB1PeriphClockCmd(DW1000_SPI_RCC, ENABLE);

dw1000_spi_init.SPI_BaudRatePrescaler = scalingfactor;
dw1000_spi_init.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
dw1000_spi_init.SPI_CPHA =  SPI_CPHA_1Edge; //SPI_CPHA_2Edge;
dw1000_spi_init.SPI_CPOL = SPI_CPOL_Low;
dw1000_spi_init.SPI_FirstBit = SPI_FirstBit_MSB;
dw1000_spi_init.SPI_NSS = SPI_NSS_Soft;
dw1000_spi_init.SPI_Mode = SPI_Mode_Master;
dw1000_spi_init.SPI_DataSize = SPI_DataSize_8b;
dw1000_spi_init.SPI_CRCPolynomial = 7;

InitializeDW1000ChipSel();

SPI_Init(DW1000_SPI, &dw1000_spi_init);
//SPI_SSOutputCmd(DW1000_SPI, DISABLE);
SPI_Cmd(DW1000_SPI, ENABLE);


//SPI_ConfigFastRate(SPI_BaudRatePrescaler_32);

//InitializeMotionChipSel();

}

SPI communication happens but the device sends me 0x1010101 instead of the classic 0xDECA0130.
after that I try to run the decaranging application (adapted for my microcontroller) but it goes into the hardfault handler.
from the assembly it tries to branch (blx) in a empty register (so the hardfault).

any suggestions?

Thanks,

Fabrizio

My initialization for STM32F411:
void SPI_Init(void){
GPIO_InitTypeDef GPIO_InitStruct;
__GPIOA_CLK_ENABLE();
__SPI1_CLK_ENABLE();

///Konfiguracja portów na SPI(MOSI,SCK,MISO)
GPIO_InitStruct.Alternate=GPIO_AF5_SPI1;
GPIO_InitStruct.Pin = SPI_PIN_MOSI | SPI_PIN_SCK;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;
HAL_GPIO_Init(SPI_PORT, &GPIO_InitStruct);

GPIO_InitStruct.Pin = SPI_PIN_MISO;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_PULLDOWN;
GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;
HAL_GPIO_Init(SPI_PORT, &GPIO_InitStruct);

///Konfiguracja portów na SPI (NSS)

GPIO_InitStruct.Pin = SPI_PIN_NSS_DW ;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;
HAL_GPIO_Init(SPI_PORT, &GPIO_InitStruct);

NSS_DW_High; //#define NSS_DW_High SPI_PORT->BSRRL =SPI_PIN_NSS_DW

SPI1 -> CR1 |= SPI_CR1_MSTR |SPI_CR1_SSM | SPI_CR1_SSI|SPI_CR1_BR_1 |SPI_CR1_BR_2|SPI_CR1_CPHA; //BR on 790kHz
SPI_SetBaudrate(SPI_NUM,SPI_BAUDRATEPRESCALER_256);
SPI1 -> CR1 |= SPI_CR1_SPE; //enable SPI

}
First of all, check the Device ID in a closed loop. There is no sense in testing ranging application while your SPI is not working. How do you check that you get 0x0101010? By readind DR register or checking it by logic analyzer on the PCB? First, check whether the proper signals arrive to DW1000 chip, then go further :slight_smile:

Any improvements ? :slight_smile:

Hi Bartosz,

SPI works, also checked with a logic analyzer, and the device sends me that address. i know that because i read it from the register where i save it.
i didn’t go through it yet, is today work.
what i would like to undestand is if it is actually correct that i receive that address instead of the classic one…

Hi,

At the end I made the code working, it was just a connection problem!!! i feel very silly!

I am also facing this type of error previously on my iOS. The main issue is iTunes error 9. Anyone have any proper solution?