0

I'm trying to communicate betwenn two NucleoF303K8 boards via SPI. One board is Master and is controlled by UART. It can send via SPI 3 kinds of messages:

  1. {0x01 0x00 0x00 0x00} that means 'read value'

  2. {0x81 0x00 0x00 0x00} that means 'set value = 0'

  3. {0x81 0x01 0x00 0x00} that means 'set value = 1'

The other board is Slave. It sets (and gets) LED pin value depending on command.

Slave algorythm is as follows:

  1. when NSS_Pin becomes low, EXTI_Callback is called, and starts recievemnt of 1 byte

  2. After First byte is recieved, I guess if it is readout command or writein

  3. if it is readback I use SPI_DMA to transmit value if it writein I use SPI DMA to receive value

  4. when NSS_Pin gets to high level again, slave processes message if it was writeIn or just waits for another command if it was readout

Here is the code:

extern DMA_HandleTypeDef hdma_spi1_tx;
extern DMA_HandleTypeDef hdma_spi1_rx;
extern SPI_HandleTypeDef hspi1;


uint8_t txb[16] = {0x01,0xAA,0xBB};
uint8_t rxb[16] = {};
uint8_t code = 0;
uint8_t op = 0; // 0: idle, 1: readout, 2: writein

void readOut(){
    op = 1;
    HAL_SPI_Transmit_DMA(&hspi1, txb,3);
}
void receiveWriteIn(){
    op = 2;
    HAL_SPI_Receive_DMA(&hspi1, rxb, 3);
}
void processWriteIn(){
    HAL_GPIO_WritePin(LD3_GPIO_Port, LD3_Pin, (GPIO_PinState)rxb[0]);
}

void SystemLoad(){
    HAL_GPIO_WritePin(LD3_GPIO_Port,LD3_Pin,GPIO_PIN_SET);
    while(1){
    }
}

void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin){
    HAL_SPI_DMAStop(&hspi1);
    if(GPIO_Pin == NSS_Pin){
        if(HAL_GPIO_ReadPin(NSS_GPIO_Port, NSS_Pin) == GPIO_PIN_RESET){
            op = 0;
            HAL_SPI_Receive_DMA(&hspi1,&code,1);
        }else{
            if(op == 2){
                processWriteIn();
            }
            op = 0;
            code = 0;
        }
    }
}

inline void mainCbk(SPI_HandleTypeDef *hspi){
    HAL_SPI_DMAStop(hspi);
    if(hspi == &hspi1){
        if(op == 0){
            if(code & 0x80){
                receiveWriteIn();
            }else{
                readOut();
            }
        }
    }
}

void HAL_SPI_TxCpltCallback(SPI_HandleTypeDef *hspi){
    mainCbk(hspi);
}
void HAL_SPI_TxRxCpltCallback(SPI_HandleTypeDef *hspi){
    mainCbk(hspi);
}
void HAL_SPI_RxCpltCallback(SPI_HandleTypeDef *hspi){
    mainCbk(hspi);
}

Slave settings in CubeMX are:

  1. 1 GPIO output (LED) and one EXTI

  2. SPI1 with DMARX (Priority high) and DMATX(priority Very High) and NVIC enabled for both DMA channels and SPI1 global interrupt

  3. NVIC priority, Debug, SysTick, etc. with highest priority (0), EXTI and SPI1 global interrupt with lower priority (1)

  4. HCLK is 64 MHz, PCLK1 is 32 MHz, PCLK2 is 64 MHz

  5. SPI speed from Master device is 250 KBit/s

For some reason I have two main problems:

  1. writeIn data migrates in rxbuffer cyclicaly. That 0x01 in 'set value = 1' appears in rxb[0] then in rxb[1], rxb[2] and from beggining on each SPI message.

  2. readout data, that slaves transmitts also acts strange: on first 2 messages I recieve on master device (and see with logic analyzer on the line) proper values:

{0x00 0x01 0xAA 0xBB}

but then something changes andit becomes

{0xBB 0x01 0xAA 0xBB} or

{0xBB 0x00 0x01 0xBB} or

{0xBB 0x81 0xAA 0xBB} and if I after readout try to writein it becomes like

{0xBB 0xBB 0xBB 0xBB}

though rxb that is in HAL_SPI_Receive_DMA(&hspi1, rxb, 3); is filled with 0

I've looked into SPI1.DR register, but it is 0, so I don't know what to think. I've tried to DMAStop on message TX and RX callbacks, also I've tried SPI_Abort.

I've mixed priority levels in different ways:

  1. all equal

  2. EXTI > SPI > DMARX > DMATX (and TX > RX)

  3. DMATX > DMARX > EXTI = SPI

  4. DMATX > DMARX > EXTI > SPI

  5. DMATX > DMARX > SPI > EXTI

Also I've tried to use HAL_SPI_Transmit_IT, but had the same result even if DMA was disabled at all.

Theoretically it have to work correct as SPI buffer is filled before the next byte si going to be transmitted, but it seems to act very strange.

What is the proper way to configure my device? Or maybe MCU cannot be controlled in such a way, as it has to use software core, to process messages, and there is proper way of doing this?

lazba
  • 129
  • 9

0 Answers0