Skip to main content
SSmit.0
Associate III
October 30, 2018
Question

HAL_SPI_Transmit uint16_t size limit

  • October 30, 2018
  • 13 replies
  • 5094 views

Hello,

I would like to send a uint32_t size array via HAL_SPI_Transmit / HAL_SPI_Transmit_DMA but both are limited to 16 bit size.

I have tried casting as

HAL_SPI_Transmit(&hspi1,Array,(uint16_t)65537),10000)

but this doesn't work.

I have also tried editing the SPI driver and changing TxXferSize and TxXferCount to uint32_t but this only seems to get rid of the compiler warning and still overflows somewhere, i.e only 1 byte from the array is sent.

Please could anyone advise what else I need to change?

Thanks

    This topic has been closed for replies.

    13 replies

    waclawek.jan
    Super User
    October 30, 2018

    Your approach.

    The libraries have their limitations. You either accept them and maybe work around them (e.g. by repeated call of those functions), or write your own.

    There's also an underlying hardware issue: the DMA's NDTR (counting) register is 16-bit long.

    JW

    PS. As somebody whose nick starts with "pic18f" you really shouldn't be shocked by a 16-bit limitation... ;)

    David Littell
    Senior II
    October 30, 2018

    ...and exactly what did you think the result of "(uint16_t)65537" would be?

    Sigh.

    David Littell
    Senior II
    October 30, 2018

    ...and exactly what did you think the result of "(uint16_t)65537" would be?

    Sigh.

    GSome
    Visitor II
    October 30, 2018

    HAL_SPI_Transmit requires a pointer to the array

    change HAL_SPI_Transmit(&hspi1,Array,(uint16_t)65537),10000)

    to HAL_SPI_Transmit(&hspi1,(uint16_t*)Array, 65537 * 2 ,10000)

    *2 require as it will then send the 32 bit number as 2 16 bit numbers;

    The receiving end would then need to be able to handle it this way.

    Tesla DeLorean
    Guru
    October 30, 2018

    "HAL_SPI_Transmit requires a pointer to the array

    change HAL_SPI_Transmit(&hspi1,Array,(uint16_t)65537),10000)

    to HAL_SPI_Transmit(&hspi1,(uint16_t*)Array, 65537 * 2 ,10000)

    *2 require as it will then send the 32 bit number as 2 16 bit numbers;

    The receiving end would then need to be able to handle it this way."

    Pretty sure that's not going to work in the way you describe.

    You'd need to tell the SPI to use 16-bit transactions, the DMA count is in transfer units, not bytes, but is still bounded by 16-bit limits for the number space.

    Tips, Buy me a coffee, or three.. PayPal Venmo (See Profile) Up vote any posts that you find helpful, it shows what's working..
    SSmit.0
    SSmit.0Author
    Associate III
    October 31, 2018

    Thank for the replies, yes despite my username I am very new to micro controller programming thus sticking to HAL.

    So I was thinking the simplest way would be to truncate the array at 65535 and send it in two HAL_SPI_Transmit pieces.

    I.e HAL_SPI_Transmit(send first 65535 number of bytes), then HAL_SPI_Transmit(send remainder of array offset by 65535). Is it possible to do this?

    Thanks

    GSome
    Visitor II
    October 31, 2018

    My answer "change HAL_SPI_Transmit(&hspi1,Array,(uint16_t)65537),10000)

    to HAL_SPI_Transmit(&hspi1,(uint16_t*)Array, 65537 * 2 ,10000)"

    makes two assumptions

    1. ARRAY is defined as uint32_t ARRAY[65537];
    2. SPI mode is set to 16 bit as this is the maximum in HAL

    I made a n error in that (uint16_t*)Array should be (uint16_t*)&Array

    The (uint16_t*) cast tells the SPI_Transmit ARRAY is 16 bits not 32 bit.

    "HAL_SPI_Transmit(&hspi1,(uint16_t*)&Array, 65537 * 2 ,10000)"

    I do this with my ADC to PC transfer where I set up a 32 bit buffer to receive ADC Data

    and transmit as 8 bit bytes

    I know this works.

       uint32_t startBuffer[1];

       startBuffer[0] = 0x53530a0d; // SS\r\n

    HAL_UART_Transmit_DMA(&huart6,(uint8_t *)&startBuffer, 4 ); // transmit 4 bytes

    I see no reason this would not work the same in SPI

    Tesla DeLorean
    Guru
    October 31, 2018

    65537 * 2 still doesn't fit in a uint16_t width variable. The largest value there is 65535, and you're more than twice that.

    Tips, Buy me a coffee, or three.. PayPal Venmo (See Profile) Up vote any posts that you find helpful, it shows what's working..
    SSmit.0
    SSmit.0Author
    Associate III
    October 31, 2018

    Hi Geosom & Clive,

    To clarify my Array is: uint16_t Array [76800], (I posted it as 8 bit for simplification).

    My suggested approach was

    HAL_SPI_Transmit(&hspi1,(uint16_t*)Array, 65535 ,10000)

    HAL_SPI_Transmit(&hspi1,(uint16_t*)Array, **LAST 11264** ,10000) -- I'm not sure how to implement this or if it's possible?

    Thanks

    SSmit.0
    SSmit.0Author
    Associate III
    November 3, 2018

    Someone?

    Tesla DeLorean
    Guru
    November 3, 2018

    You'd need to break the transfer in to multiple pieces, advancing the Array pointer to account for the data already committed.

    I think HAL_SPI_Transmit() will block until complete. The STM32 is capable of interrupting on the DMA TC event.

    Is SPI in 8-bit or 16-bit mode, the size is in units not bytes

    If 16-bit SPI

    HAL_SPI_Transmit(&hspi1,(uint16_t*)&Array[0], 38400,10000);

    HAL_SPI_Transmit(&hspi1,(uint16_t*)&Array[38400], 38400 ,10000);

    one could do it as an iterative loop

    If 8-bit SPI, from a 16-bit array

    int i;

    for(i=0; i<4; i++)

    HAL_SPI_Transmit(&hspi1,(uint16_t*)&Array[i * (38400/2)], 38400,10000); // 38400 bytes, 19200 words

    Tips, Buy me a coffee, or three.. PayPal Venmo (See Profile) Up vote any posts that you find helpful, it shows what's working..
    waclawek.jan
    Super User
    November 3, 2018

    If DMA transfers 16-bit halfwords and SPI is set to 16-bit too, then

    uin16_t Array[76800]

    HAL_SPI_Transmit(&hspi1,(uint16_t)Array, 65535 ,10000);

    HAL_SPI_Transmit(&hspi1,(uint16_t)&Array[65535], 76800-65535 ,10000);

    JW