0:09
welcome to another video of controllers
0:12
this is yet another video on
0:14
register-based programming series
0:16
and today we will see the dma
0:22
some users reported that they can't get
0:24
the dma to work with the blue pill
0:26
so i decided to make a separate video on
0:28
it i will demonstrate the working of dma
0:33
you art have already been covered with
0:37
and here is the main file from that the
0:41
identical and that's why i will not go
0:46
you can check out the other video for
0:50
we will use the same steps for blue pill
0:53
with the addition of dma of course
0:56
so let's create a project with kyle
0:59
select the cm syscor and the device
1:11
here first of all we will include the
1:17
now we will write a function to
1:24
here are the steps to configure the uart
1:31
they are identical to that for the f4
1:33
series we discussed earlier
1:37
enable the clocks configure the pins
1:41
define the word length here we will also
1:45
enable the dma for transmit
1:47
or receive this is the additional step
1:51
then we will set the baud rate and
1:53
enable the transmitter or receiver
2:03
i am going to use the uart 2 so the pins
2:17
here is the entire program for it
2:20
first we will enable the uart clock and
2:26
then we will configure the pins for the
2:30
this configuration of pins is a little
2:32
different in the blue pill
2:33
as compared to the f4 series
2:38
let's see it in the reference manual
2:44
we need to check the gpio configuration
2:48
for the device peripherals
2:55
here we have the uart section for
2:58
transmit in the full duplex mode
3:00
the pin must be set as the alternate
3:05
and for receive it must be set as the
3:11
to set these modes for the pins we will
3:14
check the configuration register
3:17
here we have alternate function output
3:20
0 and the output mode at maximum speed
3:32
so we are setting the pin p-a-2 as the
3:37
and the pin p-a-3 in the input mode
3:44
let's see how to enable the internal
3:52
here is the table as mentioned here
3:56
for the internal pull-up the output data
3:58
register must be high
4:09
next we will enable the uart and then
4:11
configure the dma for the transmit
4:29
here is the uart control register 3 and
4:33
and 6 controls the dma
4:43
i am only enabling it for the receive
4:46
next is the setting of the board rate
4:50
is the peripheral clock divided by the
4:53
times the usart division if you
4:56
rearrange the formula for the desired
4:59
you will get the values of the mantissa
5:03
this is explained in the previous video
5:05
so i am not explaining it again here
5:08
anyway this will set up the board rate
5:13
200 while the peripheral clock is
5:15
running at 36 megahertz
5:20
you can check which clock is connected
5:22
to the uart in the clock diagram in the
5:32
finally we will enable the transmitter
5:37
this is it for the uart configuration
5:40
now we will initialize the dma
5:46
before initializing it we need to check
5:48
which channels will we be working with
5:56
here we have the table for dma1 requests
6:00
you can see the uart 2 receive is
6:03
connected to the channel 6 of the dma-1
6:06
so we will write our initialization
6:14
first we will enable the dma-1 clock
6:17
now for the rest of the configuration we
6:20
will check the dma registers
6:25
the first register we have is the
6:27
interrupt status register
6:29
the bits here are red only bits and they
6:32
indicate the status of the interrupt
6:35
which was triggered next register is the
6:39
clear register and this register is used
6:41
to clear the interrupt bits
6:43
that were set in the previous register
6:46
next we have the channel configuration
6:50
let's start from the least significant
6:56
the first bit is to enable the dma and
6:59
that we will do in the end
7:01
then the next three bits are interrupt
7:05
and we will enable all three interrupts
7:09
next is the data direction as we are
7:12
copying data from the uart peripheral to
7:14
the buffer in the memory
7:16
we will keep this bit zero
7:22
next is the bit to enable the circular
7:24
mode and yes we will enable the circular
7:30
next bit indicates whether we want to
7:32
increment the peripheral address
7:35
since we are copying the data from the
7:37
data register of the uart
7:39
we don't want to increment the address
7:42
but we will increment the memory address
7:45
so that the new data is copied in the
7:57
next we have the data size for the
7:59
peripheral and the memory
8:01
here we will use 8 bits as that's how
8:09
next is the priority for the channel and
8:13
this is an important bit if you are
8:15
using more than one channel
8:18
you can control the priority of the
8:22
this is it for the initialization of the
8:23
dma but we still need to configure it
8:26
and we will write a new function for
8:28
that this function takes three
8:32
the address of the source destination
8:35
and the size of the data
8:45
the next register we have in line is the
8:48
number of data register
8:50
this register stores the number of data
8:54
transfer this is a 16 bit register
8:57
so we can transfer up to 65 535 values
9:06
once the transfer is complete the
9:08
register will stay at zero if the normal
9:13
but if the circular mode is selected the
9:15
value in the register will be auto
9:17
reloaded to the previous value
9:19
and this way transfer never finish
9:24
this is how the circular mode of dma
9:37
next is the peripheral address register
9:40
and here we will write the address of
9:47
in this case the source address since
9:50
our source is the peripheral itself
9:53
next we have is the memory address
9:55
register and in our case
9:57
it will be the destination address this
10:01
will set up everything in the dma
10:03
so finally we will enable the dma
10:06
this is done by writing the bit 0 of the
10:18
this is it for the dma part now we will
10:21
write a callback function for the dma
10:32
the callback function are defined in the
10:36
and we need this one dma1 channel 6
10:45
once the interrupt is triggered we need
10:47
to check whether it's half transfer
10:49
interrupt or full transfer
10:52
this can be done by checking the dma isr
10:57
here you can see we have bit 22 for the
11:00
transfer interrupt 23 for transfer error
11:03
and 21 for transfer complete
11:06
based on which interrupt is set we can
11:09
do the rest of the processing
11:12
let's define some buffers first
11:29
here if the half transfer interrupt is
11:32
set we will copy the data from rx buffer
11:35
starting from the first position in the
11:40
the size of the data will be half of the
11:43
since that's the data which arrived in
11:47
after copying this data we will clear
11:49
the interrupt bit by writing the
11:51
respective ifcr register value
11:54
this register is used to clear the
12:04
we will update the index and if it is
12:06
more than the main buffer size
12:18
similarly if the transfer complete
12:20
interrupt bit is set
12:22
we will copy the other half of the rx
12:25
after copying the data we will clear the
12:27
transfer complete interrupt flag
12:30
this is a good advantage circular mode
12:34
while we are handling the first half of
12:35
the buffer the second half is receiving
12:39
even if the data arrives during the
12:43
it will be saved in the buffer this way
12:45
the data is never lost
12:48
once all the data is received the dma
12:51
will reset the counter to the original
12:53
and prepare itself for the new data and
12:57
all this happens place without affecting
13:01
now we will write the main function
13:06
let's initialize the system
13:12
as i mentioned this in the previous blue
13:15
that by default the mcu will be running
13:19
and we are okay with it
13:25
now configure the uart initialize the
13:30
and now we will call the dma
13:34
here source address is the address of
13:36
the data register of the uart
13:38
as that's where the data is going to
13:41
destination address is the address of
13:45
and the size is the size of the rx
13:54
i forgot to set the interrupt we will
13:57
set it before configuring the dma
13:59
as the dma will start as soon as the
14:04
first we will set the priority of the
14:07
channel 6 interrupt and then we will
14:10
enable the interrupt
14:28
so that's all now it's the time to test
15:02
i will set a break point in the half
15:09
i am sending this one 2 3 4.
15:12
for some reason it's not displaying here
15:15
but it's being received
15:17
don't worry about it
15:21
remember that the rx buffer size is set
15:25
so nothing happens until i send at least
15:29
and now we have got a t hit at the break
15:33
dma was set to receive 20 bytes and as
15:36
soon as it received half the data
15:38
the half transfer interrupt was
15:41
here you can see all the 10 bytes of
15:45
now let's transfer again
15:51
notice that nothing will happen until we
15:53
receive the full 20 bytes
16:01
another hit at breakpoint and this time
16:03
the transfer complete interrupt was set
16:06
now we will run again and the new data
16:09
has also been copied to the main buffer
16:16
let's try to send the 20 bytes at the
16:26
something weird is going on with the
16:30
let me try one more time
16:41
it received it this time
16:46
and here you can see the data is copied
16:50
also don't worry about those glitches
16:54
it was some connection issue
16:58
let's do one last test and this time i
17:16
so we have 12 bytes of data in the rx
17:20
but only the 10 bytes were copied to the
17:23
i guess you understand why this happened
17:27
the half transfer interrupt was set
17:30
so only the 10 bytes will be processed
17:33
but this does not mean that we lost the
17:37
those two bytes will be copied next time
17:40
let's send the same data again
17:54
you can see in the 10th and 11th
17:57
we have those two bytes which was left
18:05
well that's how it works like i said few
18:09
the data is never lost in the circular
18:13
the bytes remain in the buffer and can
18:15
be handled in the next interrupt
18:18
even when we are processing the first
18:20
half of the buffer the data can still be
18:22
saved in the second half
18:24
and this is the entire purpose of having
18:26
half transfer interrupt
18:29
so that we can handle half the data
18:31
while the dma keeps on receiving the
18:35
this is it for the uart dma the same
18:39
can be used across all the peripherals
18:42
the dma settings will remain same and
18:45
all you need to configure is the source
18:47
and the destination address the
18:50
peripheral address in almost all cases
18:52
is the data register of the respective
18:56
that's all for the video leave comments
18:59
in case of any doubt
19:01
you can download the code from the link
19:05
keep watching and have a nice day ahead