Emandhal / MCP251XFD

MCP2517FD, MCP2518FD and MCP251863 driver
MIT License
30 stars 6 forks source link

RAM Writing function error #5

Closed BombaMat closed 2 years ago

BombaMat commented 2 years ago

Hello again,

I'm continuing the developpement on STM32 and I'm having an issue concerning RAM writing. The Test SPI connection of eERRORRESULT Init_MCP251XFD(MCP251XFD *pComp, const MCP251XFD_Config *pConf) always return me error code.

I am able to communicate with the MCP controller but I don't get the correct results

Here is an extract of the communication during this process. Is the process normal ? : image

Best Regards,

Emandhal commented 2 years ago

Hi,

Can you show me your interfaces functions (init and transfer) please? Which platform and MCU are you using?

Best regards,

BombaMat commented 2 years ago

I'm using the STM32 platform with a STM32F411VE.

The initialization is made by the STM32 HAL Library so I did not use your function. I will double check that everything is ok on this side but I am able to manually use the HAL SPI commands to exchange data with the MCP.

Here is my communication function :

//=============================================================================
// MCP251XFD SPI transfer data for the STM32
//=============================================================================
eERRORRESULT MCP251XFD_InterfaceTransfer_STM32(void *pIntDev, uint8_t chipSelect, uint8_t *txData, uint8_t *rxData, size_t size)
{
    initialise_monitor_handles();
    if (pIntDev == NULL)
        return ERR__SPI_PARAMETER_ERROR;
    if (txData == NULL)
        return ERR__SPI_PARAMETER_ERROR;

    HAL_StatusTypeDef SPI_Status;
    GPIO_TypeDef* CS_GPIO_Port;
    SPI_HandleTypeDef hspi;
    uint16_t CS_Pin;
    switch (chipSelect)
    {
        case CS_mkBUS1:
            // mkBUS1 : BUS SPI2
            hspi = hspi2;
            CS_GPIO_Port = mkBUS1_CS_GPIO_Port;
            CS_Pin = mkBUS1_CS_Pin;
            break;
        case CS_mkBUS2:
            // mkBUS2 : BUS SPI2
            hspi = hspi2;
            CS_GPIO_Port = mkBUS2_CS_GPIO_Port;
            CS_Pin = mkBUS2_CS_Pin;
            break;
        case CS_mkBUS3:
            // mkBUS3 : BUS SPI1
            hspi = hspi1;
            CS_GPIO_Port = mkBUS3_CS_GPIO_Port;
            CS_Pin = mkBUS3_CS_Pin;
            break;
        case CS_mkBUS4:
            // mkBUS4 : BUS SPI1
            hspi = hspi1;
            CS_GPIO_Port = mkBUS4_CS_GPIO_Port;
            CS_Pin = mkBUS4_CS_Pin;
            break;
    }

    __disable_irq();

    printf("lib tx : ");
    for (int i = 0; i < size ; i++)
    {
        printf("%#X ", txData[i]);
    }
    printf("\n");

    //--- Transmit data ---
    HAL_GPIO_WritePin(CS_GPIO_Port, CS_Pin, GPIO_PIN_RESET);
    SPI_Status = HAL_SPI_Transmit(&hspi, txData, size, SPI_TIMEOUT);

     //--- Receive data ---
    if (rxData != NULL)
    {
        SPI_Status = HAL_SPI_Receive(&hspi, rxData, size, SPI_TIMEOUT);
        HAL_GPIO_WritePin(CS_GPIO_Port, CS_Pin, GPIO_PIN_SET);

        //--- Check for errors ---
        if (SPI_Status == HAL_ERROR)
            return ERR__SPI_COMM_ERROR;
        else if (SPI_Status == HAL_TIMEOUT)
            return ERR__SPI_TIMEOUT;

        printf("lib rx : ");
        for (int y = 0; y < size ; y++)
        {
            printf("%#X ", rxData[y]);
        }
        printf("\n");
    }
    else
    {
        HAL_GPIO_WritePin(CS_GPIO_Port, CS_Pin, GPIO_PIN_SET);
    }

 __enable_irq();
 return ERR_OK;
}

And for conveniance here is the definition of HAL library functions : image

Let me know if you need more information.

UPDATE : It seems that the test RAM try to write 0xAA55AA55 into memory, but the buffer send 0x55AA55AA. It seems that this append during the creation of the transmit buffer.

UPDATE 2: The function MCP251XFD_uint32t_Conv convert the data from LSB first to MSB first, which causes the inversion when sending data.

Emandhal commented 2 years ago

Hi,

If the ST functions are well written, you can do this:

//=============================================================================
// MCP251XFD SPI transfer data for the STM32
//=============================================================================
eERRORRESULT MCP251XFD_InterfaceTransfer_STM32(void *pIntDev, uint8_t chipSelect, uint8_t *txData, uint8_t *rxData, size_t size)
{
    initialise_monitor_handles();
    if (pIntDev == NULL)
        return ERR__SPI_PARAMETER_ERROR;
    if (txData == NULL)
        return ERR__SPI_PARAMETER_ERROR;

    HAL_StatusTypeDef SPI_Status;
    GPIO_TypeDef* CS_GPIO_Port;
    SPI_HandleTypeDef hspi;
    uint16_t CS_Pin;
    switch (chipSelect)
    {
        case CS_mkBUS1:
            // mkBUS1 : BUS SPI2
            hspi = hspi2;
            CS_GPIO_Port = mkBUS1_CS_GPIO_Port;
            CS_Pin = mkBUS1_CS_Pin;
            break;
        case CS_mkBUS2:
            // mkBUS2 : BUS SPI2
            hspi = hspi2;
            CS_GPIO_Port = mkBUS2_CS_GPIO_Port;
            CS_Pin = mkBUS2_CS_Pin;
            break;
        case CS_mkBUS3:
            // mkBUS3 : BUS SPI1
            hspi = hspi1;
            CS_GPIO_Port = mkBUS3_CS_GPIO_Port;
            CS_Pin = mkBUS3_CS_Pin;
            break;
        case CS_mkBUS4:
            // mkBUS4 : BUS SPI1
            hspi = hspi1;
            CS_GPIO_Port = mkBUS4_CS_GPIO_Port;
            CS_Pin = mkBUS4_CS_Pin;
            break;
    }

    __disable_irq();

    printf("lib tx : ");
    for (int i = 0; i < size ; i++)
    {
        printf("%#X ", txData[i]);
    }
    printf("\n");

  SPI_Status = HAL_SPI_TransmitReceive(&hspi, txData, rxData, size, SPI_TIMEOUT);

  //--- Check for errors ---
  if (SPI_Status == HAL_ERROR)
    return ERR__SPI_COMM_ERROR;
  else if (SPI_Status == HAL_TIMEOUT)
    return ERR__SPI_TIMEOUT;

  HAL_GPIO_WritePin(CS_GPIO_Port, CS_Pin, GPIO_PIN_SET);

  __enable_irq();
  return ERR_OK;
}

else do this:

//=============================================================================
// MCP251XFD SPI transfer data for the STM32
//=============================================================================
eERRORRESULT MCP251XFD_InterfaceTransfer_STM32(void *pIntDev, uint8_t chipSelect, uint8_t *txData, uint8_t *rxData, size_t size)
{
    initialise_monitor_handles();
    if (pIntDev == NULL)
        return ERR__SPI_PARAMETER_ERROR;
    if (txData == NULL)
        return ERR__SPI_PARAMETER_ERROR;

    HAL_StatusTypeDef SPI_Status;
    GPIO_TypeDef* CS_GPIO_Port;
    SPI_HandleTypeDef hspi;
    uint16_t CS_Pin;
    switch (chipSelect)
    {
        case CS_mkBUS1:
            // mkBUS1 : BUS SPI2
            hspi = hspi2;
            CS_GPIO_Port = mkBUS1_CS_GPIO_Port;
            CS_Pin = mkBUS1_CS_Pin;
            break;
        case CS_mkBUS2:
            // mkBUS2 : BUS SPI2
            hspi = hspi2;
            CS_GPIO_Port = mkBUS2_CS_GPIO_Port;
            CS_Pin = mkBUS2_CS_Pin;
            break;
        case CS_mkBUS3:
            // mkBUS3 : BUS SPI1
            hspi = hspi1;
            CS_GPIO_Port = mkBUS3_CS_GPIO_Port;
            CS_Pin = mkBUS3_CS_Pin;
            break;
        case CS_mkBUS4:
            // mkBUS4 : BUS SPI1
            hspi = hspi1;
            CS_GPIO_Port = mkBUS4_CS_GPIO_Port;
            CS_Pin = mkBUS4_CS_Pin;
            break;
    }

    __disable_irq();

    printf("lib tx : ");
    for (int i = 0; i < size ; i++)
    {
        printf("%#X ", txData[i]);
    }
    printf("\n");

  if (rxData != NULL)
    SPI_Status = HAL_SPI_TransmitReceive(&hspi, txData, rxData, size, SPI_TIMEOUT);
  else SPI_Status = HAL_SPI_Transmit(&hspi, txData, size, SPI_TIMEOUT);

  //--- Check for errors ---
  if (SPI_Status == HAL_ERROR)
    return ERR__SPI_COMM_ERROR;
  else if (SPI_Status == HAL_TIMEOUT)
    return ERR__SPI_TIMEOUT;

  HAL_GPIO_WritePin(CS_GPIO_Port, CS_Pin, GPIO_PIN_SET);

  __enable_irq();
  return ERR_OK;
}

This is because the driver works like the SPI bus. If only tx buffer (rx buffer == NULL), send only the tx buffer. In case of rx buffer not NULL, it's a transfer not only a receive and works like this:

1) Send a byte of the tx buffer 2) Read the rx buffer of the SPI peripheral and write it in the rxbuffer 3) Move tx and rx buffers pointers and decrease size by 1 4) Return to 1) until size == 0

Hope this helps

Emandhal commented 2 years ago

For the 0xAA55AA55 that becomes 55 AA 55 AA it's because the MCP251XFD works in little-endian in the communication only for the data. The driver formats the data so that the MCP2517FD or MCP2518FD can understand. The interface function SHALL transmit and receive data in the save order as in parameter.

BombaMat commented 2 years ago

Thanks for your help, it was a misunderstanding of the driver function on my side. I am now able to init and configure the MCP.

Now I have a new issue, concerning the FIFO configuration. It seems that what is happening at the end of MCP251XFD_ConfigureFIFO is affecting my HAL SPI type def.

Here is the problematic part :

  if (confFIFO->RAMInfos != NULL)
  {
    confFIFO->RAMInfos->ByteInObject    = Size;                                                             // Set size of 1 object in the FIFO
    confFIFO->RAMInfos->ByteInFIFO      = (Size * ((uint8_t)confFIFO->Size + 1));                           // Total size of the FIFO in RAM is 1 element size x Element Count
    confFIFO->RAMInfos->RAMStartAddress = 0;                                                                // Can't know the start address of the FIFO info here
  }

When the program execute confFIFO->RAMInfos->ByteInObject = Size;, the adresse of hspi2 pointer (pointer to the SPI config registers) is modified. It seems like they are overlapping but I can't understand why.

Emandhal commented 2 years ago

There is no direct link. What is the confFIFO structure that you put in parameter of the function?

BombaMat commented 2 years ago

I have found the source of the problem. I was using your code example (page 13 of your lib guide) for FIFO configuration and the .RAMInfos attribution have a small error. It start with adress &Ext1_FIFOs_RAMInfos[1] instead of &Ext1_FIFOs_RAMInfos[0]. The last FIFO .RAMInfos was then out of bounds, that's why the overlapping happenned.

Emandhal commented 2 years ago

I agree, it is an error. I will correct this later Thank you

roboretag commented 2 years ago

BombaMat, i have a question. I am trie to conect my stm32f446re with the controler can mcp2518fd and i see that you are doing a code. Can you send your project? i cant how to conect . i am programing in c