 We move to the next part of this course, in this part we will cover the host functionality on the STM32 with our libraries and we are starting directly with the first hand zone, so with the virtual comport on the CDC. So with host you know there is the need for the microcontroller now to handle the flow of the communication, so the microcontroller is initializing the communication, driving all the transfers and its its responsibility to manage all the transfer on the bus. Using the Kube MX there is again the standard offer of the classes and for example for the CDC it's very easy to start the project and run the communication with any kind of virtual comport device. So what will be the change we will be see later on now there is a dedicated process for the USB host which need to be code periodically either in the main in the while loop or the possibility is to run using the timer interrupt or probably most convenient way how to drive this process is to use RTOS where Kube MX is creating a dedicated task for a USB process which is then calling it automatically. With the USB CDC we will get two main function first is the CDC transmit second one is CDC receive so either for transmission or for receiving in the case of the receive we send the packet in packet to the device that we are expecting some data and in basic configuration it's like that that this request is repeated until we get the valid data so upon a knock receive there is another one until successful data which can low the microcontroller a lot but we will be able to see it later on. Also there are introduced two types of callback in the class driver so transmit callback and receive callback maybe it will be best to see it on the flowchart so now we are acting as a host so if we want to transmit any kind of data to the device we call the transmit function with the packet to be transmit and using the out endpoint we send to the device. When device accessor receive the packet send the acknowledge and we receive transmit callback to make additional action after this step. When the STM32 acting as a host dedicate to receive any kind of data called receive function which activate in endpoint the number is not important in our case it's number and point number one and the packet is sent to the host which triggers the receive callback. So now we can move again to QPMX to create the project we will use again F446 Nucle and initialization will be quite similar to the device so like usual with F4 it's mandatory to use high speed external for USB application now in the OTG full speed we will activate host only and in the middle wire we will use virtual comport additionally we will also use PC13 as GPIO input for the button and our LEDs which are on PB0 in the button part or we can use the find button so for example PB7 is the next LED we want to find and it's upstairs and PB14 on the right bottom side GPIO output for LED and additionally for the debug purposes we can activate the UR3 which is connected to the steering virtual comport so we will be able to see what we sent or received unfortunately not correct alternative pins are choose here so we need to move the UR pins to PD9 and PD8 we want to use any more advanced type of transfers on the UR so no DMA no interrupt for the case of simplicity we will use standard blocking transfers so in the clock settings again we have the 8 mega Hertz with high speed external so 48 for USB verify the UR okay and our project is almost ready just one more thing we need to remember when we are creating host device is that host is responsible for providing the power on VBAS so let's take a look into the nuclear board data sheet we are using so we go to the electrical schematics and to USB and we can see there is a USB power switch controlling the switch for the power on VBAS and on PG6 we need to define the pin and keep it high in order to provide the VBAS on the USB bus so let's search for PG6 and set it as a GPIO output so like that and we can generate the project here the application is a bit more greedy on the resources so we will increase the heap size and stack size and we can go for code generation open the project and we can take a look what was created for us so in the main in the while we can see the host process which is periodically calling the USB process taking care about the enumeration and after that if we enumerate about the communication and also about the disconnection but where we need to go first is the configuration here we also see to to do points from QPMX and this is the driver VBAS so here it's prepared space for controlling of the VBAS as we see before it's PG6 and on the high level we activate the charge pump so first here we need to put the PG6 to reset state like that this is the activating the charge pump but for us is the main task to activate so here we need to put the code for set this will enable the charge pump on the start second important part of the code for verification and also the file where we will use where we will write the functionality later on is the USB host so here is the host in it for from the hardware in it to registering the class and starting the process itself and in the user process are the state of the connection itself so whether we are in disconnect if we are in application ready here we are already able to communicate with the device and if the application start mean that we are connected but not yet enumerated so we will use this application a bit later on for differentiating if we are connected and we can communicate with our device so now we will create here a buffer which we will send to the device and also one buffer which will be used for receiving the messages from the device so two buffers so first one for the receive second one for transmit and we will type there some message so we will send to the device only hello and we will create 100 bytes buffer for the response for for from the device for the second step we will create the function which we will periodically call and using the button we will decide whether to send or don't do any action so it will be our user function without any parameters so first we will create one variable which will iterate us and give us a bit more delay to prevent this overloading of the bus so we will be able to see better what what message we sent and the amount of messages we send now we need to check if the application is ready for communication so we already see that we are able to communicate if the application state is in the state application ready which is said here downstairs in the user process so we can copy this line so if the application state is in the application ready we can proceed to sending the message but here it would be one one by one so we will also wait for the button and introduce small delay using the I variable so let's check the button so we pin GPIO C and GPIO pin 13 we want to see that is press so it's set and additionally we will use some delay for the I variable so in this moment we want to transmit some kind of buffer which we already created so we will call usb h for the host CDC and transmit again we will have we will pass the handler the TX buffer and the size this will set the transfer and we will put the timing variable to zero if it's not higher than zero then we will increase okay the timer should be more sophisticated but to make it simple so now once we push the button message will be sent but we will we want to also see some response from the device as a device we will use exactly the same configuration like we create during the very first hands on during the VCP device so we know that this device is just echoing the incoming communication so after we will send some message we want to also receive okay so I show you once that there are the callbacks but how to find them so it's like usual for any kind of callbacks in all the STM32 class functionalities or peripheral functionalities so we will go to class so USB H CDC and here we will search for weak keyword so double underscore weak and what we find here is the CDC transmit callback which is called to one we successfully finish the transmission and the second callback is the receive one so after we receive so we will copy and use in our host configuration without the weak keyword so this will be now called once we will receive any kind of response so when we transmit any kind of buffer we want also to receive so USB H receive okay CDC also yes that's better here the handler either we can use the original one or the one which is passed in the function our RX buffer and the size we know that it's echoing so it will be again the same size and we will talk about to make it visible also without the analyzer which I will still use to show you exactly what is happening on the bus so GP IO B we have three led so let's use the PB 13 and that's it so we sent one transfer and after the transfer we want to receive we are not able to receive in during different time in the current configuration I will show you bit later on on the receive we will again only toggle a lot so for example PB 0 so now our functions in USB host C are prepared only we need to call them also so we take our user function and pass it to the header files to USB host which is already included in the main C and put it also here so now in the main C we are also able to call the user function so we are good and let's compile the project hopefully there will be no error and we may switch to test of the project so host connection between two boards also with the analyzer may be a little bit complicated but fine our project was compiled so let's load to the microcontroller let's do it one more time probably some error was reached in the connection okay I probably know what is wrong so if you also forget from the DFU last DFU demo to erase the retail protection please do otherwise you will see the error like me so okay sorry for the problem now we are fine to test so let's start the recording and run the test so now we are connected we can see there is some activity on the bus you can press the button few times and stop the communication so here we are able to see nine bytes were transferred on out so from the host to the device and then it was returned so our message is past what is interested here is the calculation of the overall usage so I will also enable the knocks so we can see there are no knocks in the communication so let's try to measure between transfer 10 and 17 so we can see the load on the bus is very very low there are no knocks at all but the reason is that now the behavior of our host is not realistic because we are able to receive the message only after we send some and only one transfer so for the real host you would expect that you will be able to receive on this host data anytime from the device so here the load is low but we need to make some changes to make the behavior a bit more realistic so going back to our code leaving the debug and we will modify our host function so on start we will create one more static variable so in it to receive because only once we will we want to in it the receiving messages so once the application is ready if we haven't done yet we will call the USB receive which we have here in the callback and so when we in it the receive we will set to one like that in this we we can leave in the exactly same shape and we make a bit more changes here in the callback we don't want to initialize the receive upon the transmit but once we receive some message so now after the application is started and any type of device is connected we start the receive so we are able to receive anytime and that is fulfilled also by calling again in the receive callback so we are repeatedly enabling the receive for the transmit callback that show us that message was pass and and also we should follow this callback if we want to call multiple times the CDC transmit to do not overwrite the settings but now we have the LED only so let's compile and load to the microcontroller okay we need to send change the handler here and now we now we are good to proceed to the second test so again I will start the analyzer and run the application so now we can see that the load on the bus is much higher I will press the button few times and let's stop and let him proceed what we should be able to see right now is that the messages will look exactly the same like before in the first case but between the valid data will be a lot of nugs which are showing us that the host is repeatedly asking for on the device for the data but there are no data to be sent so the load is load will be much higher with the not use for data so in the in and out until now it's look exactly the same but if I disable the filtering of nugs I am able to see here a lot of nugs thousands of nugs so let's calculate the load from transfer 10 to 14 and already we can see that 4.2 megabits per second so in the overall we can see that the load of the bus is below 1% much much more below but the bandwidth for the nugs is quite occupied so there is a lot of transfers which are not carrying any useful data in the end so the not only the load on the bus is high but also the number of interrupts inside of the microcontroller because each of the nugs need to be handled and again retransmit so I will use a bit different view so to do not stack the view so we will be able to see the time between the nugs so we see that there is a knuck every 12 microseconds so every 12 microsecond need to be in an interrupt from from the USB which need to be handled by the USB core itself which is again increasing the load of the microcontroller for the USB task or for the USB handling and if the data bandwidth we need is not so high this is not really convenient so in the last part of this hands-on I will show you how to decrease the load of the microcontroller so the in-request which may be found by a knuck from the device will be sent only once per chosen time so the load will be decreased but also the performance and the bandwidth for the application will be decreased by that so it's a trade-off between the performance you want to dedicate to USB host functionality and the bandwidth you need so let's go back to our code and we will need to make some changes in the library file so for this purpose we need to go into the driver how driver source and to the ACD where are handled the interrupt from the USB and for us is important the ACD AC in RQ handler so for the in transverse in direction so we can see here on the right side in okay here we are here are handled the various flags from the peripheral if you want to go deeper with this problematic reference manual is the right place for you for for us is important the one handling the knucks okay so here we see so what is the crucial place here is the is this one so for the interrupts we are not using the interrupt transfer but here is that if the knuck is received from the control or from the bulk type of endpoint we will reactivate the channel so what we will do is that in this state we will use it only for the control to do not violate the enumeration and for the bulk we will rewrite so I will use this construction so what we need to do in case of bulk is to unmask the halt how the channel and flash the 5-4 so first how ACD and we will unmask unmask the halt interrupt with our channel number after that we will how the channel so where to get the handler it's from the instance ACD instance again we will use the channel number which we want to halt and at the end we also need to flash the 5-4 because already some other in the request may be in the 5-4 so we would be able to see more in the request even we would hear disable the repetition TX5-4 again the instance and channel number so using the steps we disabled the automatic retransmission of the knuck but now we also need to use some different mechanism to control the number of in request we want to send so for this we will bit rewrite the CDC process so we will go again back to middleware but first we can try that we made the change correctly obviously not but I type wrongly else if okay so let's go to the middleware host library and to the class and we now want to change bit header file so down here there is a the CDC process so we will need one more variable here that will call the take the last time of the cystic timer when we called in the request so now we have the information and in the CDC source file we will modify the process reception so on start we will add also the information about the current tick so about the cystic and here in the urb done we want to add the alternative that if else if we are in the urb status idle so nothing is the peripheral now is in the idle state so it's waiting for some next instruction so in this point we will evaluate the time we last send the in the request and if it's above some defined value we will go again to here to the CDC receive data state which called the bark receive data so stand for the same functionality like USB CDC receive so first we get the information from the tick and if so here is the current time and from that we want to get the last dig we have safe in the handle so CDC handle and variable we edit and if this is bigger than some defined amount of time so we can write either directly or using the define so here I will put one so this is showing us the time in millisecond which will be between two in the request for us so what we want to do first you want to move for the last stick so we will put to this variable the current tick so next time also it will be by one millisecond and we will change the state to on the data RX to CDC receive data to this one so next time it will be calling called in the process bark receive data will be called so that's our the changes we need to do and we can again go to debug and test the project so let's start the recording and run the application so we can see there is again some load not so high as before so let's try to press the button few times to send some data and stop recording so here we see again the in transfers out transfer from one to second from the host to the device and we can calculate the load so 10 20 in the transfers we can see that now the percentage idle is quite reasonable and also let's take a look on the time between two nugs and we can see that there is approximately one millisecond between two nugs so using this approach and changes in the library we are able to control the virtual comport host application timing and change more according to our need also with the respect to some reasonable load of our application