0:09
welcome to another video of controllers
0:13
in the past i have covered few ways to
0:15
handle the incoming data from the uart
0:17
like the circular buffer or the ring
0:20
even the methods were very effective
0:23
there was always some
0:24
issue with different microcontrollers it
0:27
happened because there were some
0:30
and they change with different series of
0:34
so today we will be looking at yet
0:35
another method which is not only easier
0:38
but completely based on the whole so the
0:41
same method will remain universal for
0:47
cortex m7 processors needs a little
0:50
changes due to memory restrictions
0:52
and i will show them in the end so
0:55
without wasting any more time
0:57
let's start with cube id i am using
1:04
i will do my usual clock setup first
1:12
now let's enable the uart 2 for the
1:23
leave everything to default here go to
1:27
and add a receiver request
1:32
make sure the mode is normal because
1:34
this process will not work with the
1:38
data width is bytes as we transfer
1:41
characters via the uart
1:43
direction is peripheral to memory
1:49
now go to nvic and enable the global
1:53
interrupt for the uart
1:58
this is it for the setup let's start the
2:08
i am going to use two buffers and these
2:17
create the buffers now rx buffer is
2:20
where the dma is going to copy the data
2:22
and the main buffer is where the data
2:24
will be finally stored
2:30
now in the main function we will call
2:32
the uart receive function
2:35
the data will be stored in the rx buffer
2:39
is the size of rx buffer this function
2:44
note that it's urtex here it's mentioned
2:48
that it will receive data till either
2:50
the data is completely received
2:52
or an idle event occurs idle event means
2:56
when there is no incoming data for some
3:00
in that case it will trigger the
3:02
interrupt the callback we are going to
3:06
is the rx event callback here the event
3:10
it could be idle event or the complete
3:12
event but that's okay and we will handle
3:15
the data in the same way for both of
3:18
inside the callback we will check if the
3:20
callback is called by the uart too
3:24
i am putting this check so that you can
3:26
use multiple uarts in the same function
3:28
just make sure to check which you are
3:32
this could be you art also it depends on
3:34
if you are using usart
3:36
or you aren't if the data is incoming in
3:40
too we will just copy the data to the
3:44
now after the callback the dma will stop
3:48
and we must start it again
3:58
the hall sets all the interrupts for the
4:02
and we will disable the half transfer
4:06
this interrupt triggers when half the
4:08
data has been transferred
4:10
and we don't need it here so this is it
4:23
seems like i forgot to include the
4:31
build it again and now we will debug
4:41
i have added the buffers in the live
4:46
let's put a break point here to
4:48
understand the process
5:00
i will send one two three four first
5:04
we hit the break point even though the
5:07
receive size was set to 10
5:10
the interrupt gets triggered with just
5:13
this is because the line was idle after
5:17
and that's what set the interrupt the
5:20
another interesting thing to note here
5:24
of the size variable it's same as the
5:27
number of characters we sent
5:29
so whenever the idle line triggers the
5:31
interrupt we will know how many
5:33
characters actually got stored in the
5:36
now we will do the mem copy and copy the
5:39
content in the main buffer
5:48
this time i will send a single character
5:51
you can see the value of the size
5:54
it is one here it starts writing in the
5:57
rx buffer from the beginning again
6:00
and that's why we need a second buffer
6:02
where we can store the data in the
6:06
not like this of course we will modify
6:10
but before that let's see what happens
6:12
if i try to send data greater than the
6:21
these are obviously more than 10
6:27
this time the size is 10 so the
6:29
remaining data is pretty much lost
6:32
to avoid this use the larger size for
6:36
but not very large i will demonstrate
6:40
let's modify this code so that it can
6:43
handle the incoming data in a proper
6:57
here it is a big solution
7:00
let me explain what's happening here
7:04
we need to keep track of the current
7:06
position in the main buffer
7:11
now let's assume we got some data if the
7:14
current position plus data
7:16
size exceeds the buffer size then we
7:18
need to overlap from the start of the
7:23
for example if the buffer size is 20
7:26
and our current position is 15 now if we
7:29
get eight bytes of new data
7:31
the new position should be 23 which is
7:34
exceeding the buffer size
7:36
here we will first find how many bytes
7:39
are remaining in the buffer
7:40
which in our case are five we will copy
7:44
5 bytes of data now we have reached the
7:48
so we will start from the beginning
7:51
update the position to 0
7:53
and copy the remaining bytes which in
7:56
r3 and finally we will update the
8:00
position according to the current
8:03
in another scenario if the position plus
8:05
the data does not exceed the buffer
8:07
we will simply copy the data into the
8:10
update the current position i have also
8:14
included a test check function
8:17
this can be used for quickly checking
8:19
for a particular string in the incoming
8:22
keep this very small as it might disturb
8:27
let's build and run this
8:33
let's see the working now since we have
8:38
this time things will be different here
8:48
we have the one two three four in the
8:52
now the p is saved in the next position
8:55
keep checking the values of the old
8:57
position and the new position
9:00
now the new data is saved in the proper
9:02
order and the positions are also
9:04
updating as per the changes
9:19
now if i send this data let's see what
9:23
here the data is written till the end of
9:26
the buffer and then it started from the
9:29
it's overlapping the old data
9:33
let's see if this particular search
9:37
i will just send some random data and
9:50
notice this variable this should set to
9:57
you can see it's 1 since it found that
10:00
in the middle if the data you can use
10:03
this to check for the strings
10:04
but not the large ones you can implement
10:08
the functions from ring buffer code here
10:11
and they will work all right you might
10:13
need to modify them a little
10:15
i will do that and update the code in
10:20
keep checking the github the program
10:22
works fine for small data
10:24
but how effective is it if the large
10:26
data arrives in the uart
10:29
let's test it i am going to send a huge
10:33
so let's modify these size rx buffer can
10:37
accept 512 bytes at once
10:40
and the main buffer is 2 kilobytes
10:43
here is the data i am going to send
10:49
this is a text file which is 1.42
10:54
1459 bytes to be exact
10:58
let's see if it can receive the file
11:03
keep an eye on the position variable
11:10
let's send the file now
11:18
the new position is 1459
11:22
which was the size of the file this
11:25
means the entire file has been received
11:30
we can cross check the data
11:40
here the file starts with this sentence
11:43
and that's exactly we have in the
11:45
beginning of the buffer
11:51
the data is ending at 14 59
11:54
so let's check that part
11:59
this is the end of the file
12:04
here we have the same sentence in the
12:07
so even the rx buffer was set to receive
12:12
the entire data was received
12:16
this is because the transfers take place
12:19
and we can receive one chunk of data
12:21
process it and get ready to receive the
12:24
chunk there is enough time in between
12:28
so that we can process this data
12:31
so the things works just fine and we are
12:34
able to receive the receive unknown
12:35
length data from the uart
12:38
soon i will make a video about file
12:40
transfer using the uart
12:42
where we can save the file in the sd
12:46
by using the uart and stm32
12:49
this is it for the video the next part
12:52
will focus on the cortex
12:58
in the cortex m7 series we need to make
13:01
few changes in our memory location
13:06
i am using the h745 and i have the same
13:15
i would recommend that you watch my
13:17
previous video on memory management
13:20
the link is in the description
13:27
if we see the memory details here the rx
13:30
buffer is at the location 2.4 million rc
13:34
like i mentioned in the previous video
13:36
also that in my case
13:38
this location is in the axi ram so no
13:41
issues for me as the dma do have the
13:45
but in some cases this location will be
13:49
and there you have the issue as the dma
13:54
so if you have the controller whose main
13:58
i would suggest that you move the buffer
14:00
to some other location
14:01
like sram one or two it's explained in
14:05
that memory management video
14:07
so watch it i have it in the sram
14:10
so i will go ahead with the next step
14:14
go to the cube mx and the cortex m7 tab
14:18
here we will modify the mpu
14:23
just follow it for this video i will
14:25
surely make another video to explain it
14:30
select this background region privileged
14:33
and mpu disabled during hard fault
14:37
now enable the memory region
14:41
enter the address of the rx buffer
14:44
keep in mind that there is some
14:46
alignment parameter also
14:49
so if it doesn't work for you put the
14:51
buffer at the start of any sram
14:53
and then try with that address i will
14:56
explain about mpu region
14:58
size and or other things in few other
15:02
next we have to choose the region size
15:04
and since the rx buffer is set to
15:09
we will choose 512 bytes or more here
15:17
in the access permission select all
15:25
and disable all the permissions
15:28
so this region is not cacheable not
15:32
or bufferable that's all let's test it
16:02
i will send the same file again
16:09
it received the file successfully the
16:15
we can cross check the data in the
16:17
beginning and end of the file
16:33
now if we send the file again the main
16:35
buffer will be overlapped
16:41
you might be wondering how the main
16:42
buffer is able to work here
16:44
since we haven't configured it in the
16:48
well that's because we are performing
16:49
mem copy while copying data between
16:52
rx buffer and main buffer
16:55
and like i mentioned in the previous
16:57
video the cpu have access to all the
17:00
so it can freely copy the data around
17:06
the dma was the problem and since the
17:08
dma is copying the data from the
17:10
peripheral into the rx buffer
17:12
we need to modify the region for the rx
17:18
let me quickly show you what happens if
17:20
we don't configure the mpu
17:34
i will set a breakpoint in the callback
17:42
so we did hit the breakpoint means the
17:45
interrupt is working just fine
17:51
but if we see the rx buffer there is
17:56
this means that the data did arrived in
17:58
the uart data register
18:00
but it didn't got copied in the rx
18:05
this happens due to the cachable region
18:08
and we will discuss it in another video
18:16
if we send the data again the interrupt
18:19
the positions are updating but there is
18:21
nothing in the rx buffer
18:28
so properly configure the mpu to avoid
18:32
this is it for this video i hope you
18:35
understood the topic
18:37
like i mentioned in the beginning this
18:40
setup does not require particular
18:41
registers to deal with
18:43
so you can use it in any stm32 device
18:46
if it supports idle line interrupt
18:49
i will try to add few more functions to
18:52
this so it can be used it with the esb
18:55
or the gsm gps modules
18:58
you can download the code from the link
19:02
keep watching and have a nice day ahead