0:09
hello and welcome to controller Tech
0:12
this is the fifth video in the SDM 32
0:15
wat series and today we will continue
0:18
receiving the data but we will use the
0:20
idle line to do so we covered how to
0:23
receive data using the dma in the
0:25
previous video although the data
0:27
reception worked very well but we needed
0:30
to know the size of the data to be
0:32
advance the idle line can handle the
0:35
issue of unknown data very well idle
0:39
line is detected by the U peripheral
0:41
when the RX line remains idle for some
0:44
time the line can be idle when the
0:47
sender has stopped sending the data or
0:49
when the sender is sending a large data
0:51
in smaller chunks and there is an
0:54
unusual delay between two successive
0:56
chunks this idle time depends on the
0:59
board rate configuration of the device
1:02
and will be automatically handled by the
1:04
peripheral for highboard rates this idle
1:08
time is low as compared to that for the
1:11
rates when the peripheral detects this
1:13
idle line it can trigger the interrupt
1:16
or exit the Blocking Mode depending on
1:19
how we are receiving the data in today's
1:22
tutorial we will utilize this IDL line
1:25
feature of the stdm 32 to receive the
1:30
the advantage it is over the dma method
1:33
we used in the previous video is this
1:35
time we won't need to send the size of
1:37
the data we will extract the size from
1:42
itself I will continue with the previous
1:46
project here I have deleted all the code
1:51
video now let's open the cube
1:54
MX here we will keep the uart dma as we
1:58
will use it in today's video
2:01
let's change the mode to
2:03
normal make sure the interrupt is also
2:06
enabled the basic configuration for the
2:09
uart is still the same click save to
2:14
project we will first start with the
2:17
simple reception using the idle
2:19
Line This method could be used when you
2:22
want to transfer small data between two
2:24
devices but the receiver does not know
2:27
the size of the incoming data let's
2:30
create a buffer of 30 bytes to store the
2:32
received data the index variable will
2:36
keep track of how many data bytes have
2:39
received here we have three different
2:41
functions to receive data using the idle
2:45
line note that these functions start
2:48
with uart ex and not just
2:51
uart the receive to idle is used in The
2:54
Blocking Mode then we have the interrupt
2:56
mode and the dma mode we will not use
3:00
the Blocking Mode as it is not that
3:03
useful let's use the interrupt mode to
3:06
receive the data the parameters are the
3:09
uart instance the buffer to store the
3:12
data and the size of the buffer this
3:15
size variable is the maximum size of the
3:18
data you are expecting so better set it
3:20
the same as the buffer
3:22
size the interrupt will trigger in two
3:26
scenarios first when the data received
3:29
is left Les than 30 bytes and the sender
3:32
has stopped sending the data for some
3:34
time and second when the sender has sent
3:37
30 bytes data whether it is sending more
3:40
data or not it does not matter here I
3:43
will demonstrate both scenarios so you
3:46
will understand them better when the
3:48
idle line interrupt is triggered the RX
3:51
event call back is called the size
3:54
variable of this call back represents
3:57
how many bytes were received when the
3:59
call back is called inside the call back
4:02
we will simply extract this size and
4:05
save it in the index variable the
4:08
interrupt is disabled after the call
4:10
back is called so we will again call the
4:12
interrupt function so that the MCU can
4:15
continue receiving the data let's build
4:18
and debug the project now I will use the
4:22
same serial monitor on the computer as
4:31
I have added the RX data and the index
4:40
expression let's run the debugger now I
4:44
am going to send five bytes first you
4:47
can see the index variable has the value
4:50
five and the RX data has the data we
4:53
sent since we are dealing with a small
4:56
amount of data you can process this data
5:00
itself now let's send 8 bytes of data
5:04
here the index variable has been updated
5:07
and the RX data now has the new data in
5:10
it basically the idle line interrupt is
5:13
called whenever the sender stops sending
5:15
the data and the size parameter of the
5:18
call back stores the number of bytes
5:21
received since we are receiving a
5:23
maximum of 30 bytes this can work well
5:26
if we send data less than or equal to 30
5:30
let's try sending more than 30
5:33
bytes here I am going to send 36 bytes
5:36
of data note that the index variable is
5:41
six this is because the first interrupt
5:44
was called when it received 30
5:47
bytes the data was stored in the RX data
5:50
buffer and the receive function was
5:52
called again the remaining six bytes
5:55
were stored in the second call and hence
5:58
the index variable is
6:00
six the new data overlapped the first
6:03
six bytes of the previously stored data
6:06
we can write a much better code to
6:08
handle such situations but I would
6:10
advise not to do that what I am trying
6:13
to say here is that we should not
6:15
receive a large amount of data in the
6:17
interrupt mode as we have the dma for it
6:21
and for the small data we can define a
6:23
buffer large enough to store the entire
6:27
overlapped so use using the receive to
6:30
idle in the interrupt mode is a
6:32
convenient way to receive the data of
6:35
length after the interrupt is triggered
6:38
we have the data and we have the size of
6:40
the received data so we can handle the
6:43
data very well now let's see the receive
6:49
mode right now the dma is configured in
6:52
the normal mode and it works similar to
6:55
the interrupt mode here I am just
6:58
replacing the interrupt part with the
7:00
dma the reset of the code Remains the
7:03
Same let's build and debug it
7:08
now I am sending nine bytes of data
7:13
first here we have received the data
7:16
along with the size it is working just
7:19
as how it worked using the
7:21
interrupt even if we sent 36 bytes of
7:24
data the index variable again has the
7:27
value six with the first six of RX data
7:33
overlapped let me write a separate code
7:35
for the dma let's delete this part as I
7:39
want to run the receive function just
7:41
once here I am planning to receive a
7:44
large amount of data so defining a large
7:47
buffer also Define a count variable
7:50
which will count how many times the call
7:52
back was called during the transfer the
7:55
size is going to be big now so the index
7:58
variable is 16 bit now in the main
8:01
function we will call the receive to
8:03
idle in the dma mode this time we will
8:09
4,096 bytes we also need to increment
8:13
the count variable in the call back so
8:15
that we can track how many times the
8:17
call back was called all right let's
8:20
build and debug the project I am going
8:23
to send the same files via the uart that
8:26
I used in the previous videos I have
8:29
also added the count to the live
8:31
expression all right let's send the file
8:34
with 2044 bytes data here you can see
8:38
the number of bytes sent by the software
8:41
all 2044 bytes have been sent note that
8:45
the value of the index variable is
8:51
2044 the count value is one that means
8:54
the call back was just called once now
8:57
let's check the RX data buffer since we
9:01
sent 2044 bytes let's check if we have
9:04
received the last few data bytes well
9:07
the buffer is just empty here this means
9:10
we did not receive the entire data so
9:13
what happened here the function was set
9:18
4,096 bytes so we should have been able
9:21
to receive that much data or less but we
9:24
only received 1,08 bytes this is because
9:28
the software we use to send these files
9:31
does not send the entire file in a
9:33
single attempt instead it sends the data
9:37
in small chunks here it sent 1,8 bytes
9:41
once then it might have sent another set
9:43
of 1,8 bytes and so on the large data
9:48
file is sent in a smaller number of data
9:51
bytes and hence the RX event call back
9:53
is called multiple times but we only set
9:57
the function to be called just once and
9:59
hence we did not receive the entire data
10:02
the number of times this Loop will be
10:06
unpredictable when I was testing the
10:08
project it kept varying even if we call
10:12
the dma function again the data will
10:14
just start storing from the beginning of
10:16
the RX data buffer hence it will overlap
10:20
the previously received
10:22
data we can still use some offset to
10:25
handle such a situation but that would
10:27
be too much work and we we have to
10:29
consider too many variables here so to
10:32
handle such scenarios and to receive
10:35
large data of unknown size we better use
10:38
the circular mode Let's Open the cube MX
10:41
and change the dma to Circular
10:48
mode all right now I am keeping the code
10:51
as it is and let's see how it behaves in
10:57
mode I am going going to send the same
11:00
file again here you can see the value of
11:03
the index variable is now equal to the
11:05
file size the count is three that means
11:09
the call back was called three times one
11:13
interesting thing to note here is that
11:15
even after multiple calls the size
11:17
variable keeps record of its previous
11:19
value and it keeps on adding the new
11:22
size to it this is why the index
11:25
variable is 2044 and is not equal to the
11:29
received in the last time the call back
11:32
called now let's check the data at the
11:37
position here we have received the
11:39
complete data so we can receive a large
11:43
amount of data in the circular mode we
11:46
can also find out the number of bites
11:48
received so we don't have to rely on the
11:51
sender to send this information just
11:53
like we did in the dma mode in the
11:55
previous video note that the dma is in
11:58
the the circular mode so the next
12:01
received data will be stored at the very
12:03
next position in the RX buffer let's
12:06
open the RX data buffer to observe this
12:10
here I am going to send three bytes of
12:13
data you can see the data is stored at
12:16
the very next position in the RX data
12:19
buffer also the index variable is now
12:23
2047 in circular mode the dma will
12:26
always store the new data at the very
12:28
next position in the buffer but let's
12:31
assume that we don't want something like
12:34
this instead when all the data is
12:37
received the new set of data should be
12:39
stored at the beginning of the RX buffer
12:42
it is a bit complicated to achieve this
12:45
as we do not know the size of the data
12:47
so we can't figure out if the sender has
12:49
sent all the data or is it still sending
12:52
more but there is one parameter that we
12:55
need to consider here even though the
12:58
sender can send the data in smaller
13:00
chunks the delay between two successive
13:04
large so we could Implement some timeout
13:07
feature to identify if we have received
13:09
all the data let's Define a 16-bit
13:13
variable in the main
13:15
file Now define the same as an external
13:18
variable in the interrupt file the Cy
13:21
tich Handler is called every millisecond
13:24
so we will increment the variable in
13:27
Handler now whenever the RX event call
13:30
back is called we will reset the
13:32
variable to zero the time delay between
13:35
two successive chunks of data cannot be
13:39
milliseconds but to keep the maximum
13:42
flexibility for the sender I am assuming
13:44
that the sender can send data within 1
13:47
second in the while loop we will check
13:50
if the timer value is more than 1
13:53
second this will imply that no data has
13:56
been received in the last 1 second and
13:58
we could could assume that the sender
14:00
has stopped sending the data to keep
14:03
things more practical keep this timeout
14:05
small like 100 milliseconds or so once
14:09
the timeout is reached you can process
14:12
the received data then stop the dma and
14:14
start the receive to idle in dma mode
14:17
again I have already mentioned it in the
14:19
previous video the circular dma needs to
14:22
be stopped first before making the same
14:25
call again so we can implement this
14:28
method to receive a large amount of
14:30
unknown data and can still get the size
14:32
of the received data but what if the
14:35
data is huge say in megabytes and we
14:38
need to store it in the SD card or a
14:41
flash drive we can't store the data in
14:44
megabytes in the ram as most of the mcus
14:47
do not have enough memory for that we
14:50
will use a small buffer to receive this
14:52
data and then send the received data
14:55
directly to the file I am writing a
14:58
separate code for this section let's
15:00
define our X size as we are going to use
15:03
it in multiple places so here we will
15:06
only receive 256 bytes in the ram buffer
15:10
at once and using only these 256 bytes
15:14
we will save the entire data in the
15:16
final buffer or in an external file in
15:18
the SD card let's define some more
15:22
variables which will be used in this
15:25
method now once the 256 or less are
15:29
received the call back will be
15:32
called here we will copy the data from
15:35
the RX buffer to the final buffer the
15:38
index 2 variable will keep track of the
15:40
data position in the final buffer and
15:42
the index one variable will keep track
15:46
buffer here we are copying the number of
15:49
bytes as stored in the size variable as
15:52
this variable holds the actual number of
15:54
data bytes received when the call back
15:57
called now we need to update the
16:00
variables so that there is no
16:03
overlap we will check if the size
16:05
variable is equal to the RX
16:08
I this means that all 256 bytes were
16:12
received when this call back was
16:14
called in this case we will increment
16:19
variable Now update the index to
16:22
variable which will be equal to the RX
16:25
size times the RX complete so when the
16:29
256 bytes are received the RX complete
16:32
will be one and hence the index 2 will
16:37
256 when 512 bytes are received the RX
16:41
complete will be two and hence the index
16:46
512 at this moment the new data will be
16:49
received at the beginning of the RX data
16:51
buffer so we will reset the index one
16:54
variable this is to make sure that the
16:57
next data will be coped coped from the
16:59
beginning of the RX data buffer if the
17:02
call back was called before we even
17:04
received the 256 bytes we will increment
17:08
the index 2 according to the size
17:11
parameter and also update the value of
17:15
variable here I am adding the index 2
17:19
variable with the difference between the
17:23
variable this is because the size
17:25
variable retains its value between
17:29
say for example if we received 20 bytes
17:32
first then the index one and index 2
17:37
20 now we received 30 bytes in the next
17:41
chunk the size variable will keep adding
17:44
its value which will be 50 now so we
17:47
need to remove 20 from it to get the
17:49
actual number of bytes received during
17:52
this call also the index one variable
17:56
will now have the value 50 so we can use
17:59
this in the next call if you want to
18:01
implement the timeout set the timer to
18:04
zero each time the call back is called
18:07
in the main function we will receive 256
18:11
bytes using the idle line in the dma
18:19
mode all right let's build and debug the
18:26
now let me of all the necessary
18:29
variables to the live expression all
18:32
right let's send the 2044 file first
18:37
here the index 2 variable is 2044 which
18:40
means we have received all the data the
18:43
RX complete is seven which means it is
18:46
seven times that we received 256 bytes
18:49
of data the index one variable is
18:53
252 which are the additional bytes we
18:56
received after last time the RX complete
18:59
incremented Let's cross check the data
19:02
once let's check the beginning of the
19:04
data here we have the value 086
19:09
726 let's verify it with the actual file
19:13
we have the correct data at the
19:15
beginning here the data at the end is
19:20
1355 let's check the data at the
19:24
243rd position in the final
19:28
here you can see that we have the exact
19:32
positions if you note here we have
19:35
received some additional data most
19:37
probably the garbage data but you don't
19:40
need to worry about it as we have the
19:42
total size so we will only handle the
19:45
data as for the size received you can
19:48
use the timeout to reset the buffer stop
19:51
and restart the dma I have not
19:54
implemented it so I will just reset the
19:57
debugger let's try sending another data
20:00
file I am sending this
20:03
2,176 bytes file now here you can see
20:07
that we have received the entire data
20:10
again so we are able to receive all the
20:13
data using a small or buffer unlike the
20:16
previous video we don't need to know the
20:18
size of the data in advance One Last
20:21
Thing Before we end this video the timer
20:25
function can reset the dma in the middle
20:27
of the reception so we will Implement
20:29
one more check for it let's Define a
20:32
variable which will be used to enable or
20:35
disable the timer every time the call
20:38
back is called we will set this variable
20:41
and once the timeout occurs we will
20:44
reset the variable let's also Define
20:47
this as an external variable in the
20:55
file now in the cystic Handler we will
20:58
will only increment the timer if the
21:00
timer is enabled this will prevent the
21:03
timer from resetting the dma while no
21:05
data is being received so I hope you
21:09
understood how to use the receive to
21:10
idle feature to receive the data of
21:13
unknown size you can download the code
21:16
from the link in the description leave
21:19
comments in case of any doubt keep
21:22
watching and have a nice day