2020-03-20 11:57 PM
Hello,
A simple question make me confused. For example, this code with return 40 value for a 10-member array.
#include <stdio.h>
int buffer[10];
int main()
{
printf("Hello World %d \n\r",sizeof(buffer));
return 0;
}
For settings my DMA for specific value of an array I need to clarify the size of my sending array. For example, if I have a 150-member array( buffer[150] ) and I need to send 100 bytes of it how can I define "DMA_InitStructure.DMA_BufferSize " ?
This question arises when I see "DMA_InitStructure.DMA_BufferSize =sizeof(Buffer) - 1;".
I don't know where did -1 come? if the size of buffer is (150*4) bytes, we should set "DMA_InitStructure.DMA_BufferSize =sizeof(Buffer) - 1*4;"
2020-03-21 12:59 AM
The sizeof operator is a built-in operator in C which returns the size of the operand in bytes.
https://www.gnu.org/software/gnu-c-manual/gnu-c-manual.html#The-sizeof-Operator
If the size of one element is more than one byte, you should of course divide the array size with the element size to get the number of elements. Like in the gcc documentation above,
#define ARRAYSIZE(x) (sizeof x/sizeof x[0])
> if I have a 150-member array( buffer[150] ) and I need to send 100 bytes of it
You can of course send any part of the array, there is no rule requiring the use of all array elements each time. Just ensure that it never goes outside of the array.
> how can I define "DMA_InitStructure.DMA_BufferSize "
See the documentation of the library that defines "DMA_InitStructure.DMA_BufferSize". It might require the number of bytes, or the number of words, it is up to the library implementation.
The DMA peripheral requires the number of data units to be set in the NDTR register, as defined by the MSIZE/PSIZE bit fields of the channel control register, i.e. the size in bytes / 2 for halfword (16 bit) transfers, size/4 for word (32 bit) sized transfers. See the DMA chapter of the reference manual.
> "DMA_InitStructure.DMA_BufferSize =sizeof(Buffer) - 1;". I don't know where did -1 come?
Neither do I. The author wanted to exclude the last byte for whatever reason.
> if the size of buffer is (150*4) bytes, we should set "DMA_InitStructure.DMA_BufferSize =sizeof(Buffer) - 1*4;"
You are the only person in the world who can know how many bytes you want to send. The rest of the world including me can only guess.
2020-03-21 03:11 AM
+1 to everything berendi said above except this minor thing:
> The DMA peripheral requires the number of data units to be set in the NDTR register, as defined by the MSIZE/PSIZE bit fields of the channel control register
The OP did not tell us which STM32 model is he using. When MSIZE==PSIZE, the behaviour is the same, but in the other case the exact behaviour on the memory side differs, depending on whether it's a single-port DMA (as in 'F0, 'F1, 'F3 and 'Lx) or dual-port DMA ('F2/'F4/'F7) - and the latter's behaviour depends on whether FIFO is on or off.
JW
2020-03-21 03:35 AM
The -1 would be for a byte array, holding a string, where you don't want the trailing NUL to be sent over the wire.
Where strlen(str) == sizeof(str) - 1
2020-03-23 01:01 AM
Thanks all for your comments and your usual help in this forum.
Here is my DMA settings.(STM32F10x)
DMA_InitTypeDef DMA_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel4_IRQn;;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
DMA_DeInit(DMA1_Channel4);
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&USART1->DR;
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)MSG;
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;
DMA_InitStructure.DMA_BufferSize =(uint8_t)sizeof(MSG);
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
DMA_InitStructure.DMA_Mode =DMA_Mode_Circular ;///DMA_Mode_Normal ; //
DMA_InitStructure.DMA_Priority = DMA_Priority_High;
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
DMA_Init(DMA1_Channel4, &DMA_InitStructure);
DMA_ITConfig(DMA1_Channel4, DMA_IT_TC, ENABLE);
USART_DMACmd(USART1, USART_DMAReq_Tx, ENABLE);
DMA_Cmd(DMA1_Channel4, ENABLE);
And the MSG array consists of 15 elements (unsigned char MSG[15];). I filled up all elements manually as you can see:
....
MSG[7]=Sensor1;
MSG[8]=Sensor2;
MSG[9]= Sensor3;
MSG[10]= Sensor4;
MSG[12]= MSG[11];
MSG[13]='\r';
MSG[14]='\n';
However in receiver I just get data up to MSG[12] and I miss 13,14 elements. I changed this line to
DMA_InitStructure.DMA_BufferSize =(uint8_t)sizeof(MSG)+2;
And now it works fine. What is my mistake?