I built the code from the STM32CubeF4 for the USB CDC example. I added the missing receive code for CDC_Receive_FS() in usbd_cdc_if.c.
I loaded this into my STM32F4 Discovery and it works. A character typed on Tera Term returns and is displayed on Tera Term.
I am hoping that someone here, could give me some knowledge about how this USB CDC firmware works, specifically, is this being driven by an interrupt that is generated when there is a level shift in voltage on the USB -D and +D pins, or is there an infinite while loop that was launched somewhere, and it's just polling waiting for some data to appear?
What prompted my question is that I see that one can blink the LEDs on this board by toggling the state of the GPIO pins within an infinite while loop in main.c. However, there is nothing within this while loop at all within main.c for USB. So how does this USB CDC firmware get and send a character from/to Tera Term.
I will take the 2 minutes to answer you instead of lecturing you. Receive is done through interrupts. Very, very simply, the hardware sees the voltage change on the D+/D- and flags an interrupt based on the intialization functions. The interrupt calls HAL_PCD_IRQHandler, which calls USBD_LL_DataInStage in the usbd_conf.c file. That ends up calling the function USBD_CDC_DataIn in the usbd_cdc.c file. There is your starting point, but it is not simple. To do what you want you might have to stop the output to UART and just handle it in the main loop.
This question is to broad for this forum and not an actual question for a specific problem. However, as some hints, you might
Read the USB-specs, at least some basic overview (just start at wikipedia). USB does not work by toogling a GPIO in software (see next point)
Read the STM32F4xx reference manual. This is quite comprehensive.
Read the source code of the demo. This should answer all questions.
To track execution paths, you should remember that C always starts with the main() function, so this is a good start to see what's going on. (disclaimer: I know pretty well, it starts with startup, but this might confuse a beginner even more).
If you want to work with USB, you will have to do this all anyway, so you might start with it as well right now. Yes, this will take some time; no surprise, engineers have learned all this for years before they start with larger projects.
All information is available legal and for free on the web.
And, yes, USB is most likely interrupt-driven and might also use DMA to transfer data.
Related
I am new in embedded development and few times ago I red some code about a PIC24xxxx.
void i2c_Write(char data) {
while (I2C2STATbits.TBF) {};
IFS3bits.MI2C2IF = 0;
I2C2TRN = data;
while (I2C2STATbits.TRSTAT) {};
Nop();
Nop();
}
What do you think about the while condition? Does the microchip not using a lot of CPU for that?
I asked myself this question and surprisingly saw a lot of similar code in internet.
Is there not a better way to do it?
What about the Nop() too, why two of them?
Generally, in order to interact with hardware, there are 2 ways:
Busy wait
Interrupt base
In your case, in order to interact with the I2C device, your software is waiting first that the TBF bit is cleared which means the I2C device is ready to accept a byte to send.
Then your software is actually writing the byte into the device and waits that the TRSTAT bit is cleared, meaning that the data has been correctly processed by your I2C device.
The code your are showing is written with busy wait loops, meaning that the CPU is actively waiting the HW. This is indeed waste of resources, but in some case (e.g. your I2C interrupt line is not connected or not available) this is the only way to do.
If you would use interrupt, you would ask the hardware to tell you whenever a given event is happening. For instance, TBF bit is cleared, etc...
The advantage of that is that, while the HW is doing its stuff, you can continue doing other. Or just sleep to save battery.
I'm not an expert in I2C so the interrupt event I have described is most likely not accurate, but that gives you an idea why you get 2 while loop.
Now regarding pro and cons of interrupt base implementation and busy wait implementation I would say that interrupt based implementation is more efficient but more difficult to write since you have to process asynchronous event coming from HW. Busy wait implementation is easy to write but is slower; But this might still be fast enough for you.
Eventually, I got no idea why the 2 NoP are needed there. Most likely a tweak which is needed because somehow, the CPU would still go too fast.
when doing these kinds of transactions (i2c/spi) you find yourself in one of two situations, bit bang, or some form of hardware assist. bit bang is easier to implement and read and debug, and is often quite portable from one chip/family to the next. But burns a lot of cpu. But microcontrollers are mostly there to be custom hardware like a cpld or fpga that is easier to program. They are there to burn cpu cycles pretending to be hardware designs. with i2c or spi you are trying to create a specific waveform on some number of I/O pins on the device and at times latching the inputs. The bus has a spec and sometimes is slower than your cpu. Sometimes not, sometimes when you add the software and compiler overhead you might end up not needing a timer for delays you might be just slow enough. But ideally you look at the waveform and you simply create it, raise pin X delay n ms, raise pin Y delay n ms, drop pin Y delay 2*n ms, and so on. Those delays can come from tuned loops (count from 0 to 1341) or polling a timer until it gets to Z number of ticks of some clock. Massive cpu waste, but the point is you are really just being programmable hardware and hardware would be burning time waiting as well.
When you have a peripheral in your mcu that assists it might do much/most of the timing for you but maybe not all of it, perhaps you have to assert/deassert chip select and then the spi logic does the clock and data timing in and out for you. And these peripherals are generally very specific to one family of one chip vendor perhaps common across a chip vendor but never vendor to vendor so very not portable and there is a learning curve. And perhaps in your case if the cpu is fast enough it might be possible for you to do the next thing in a way that it violates the bus timing, so you would have to kill more time (maybe why you have those Nops()).
Think of an mcu as a software programmable CPLD or FPGA and this waste makes a lot more sense. Unfortunately unlike a CPLD or FPGA you are single threaded so you cant be doing several trivial things in parallel with clock accurate timing (exactly this many clocks task a switches state and changes output). Interrupts help but not quite the same, change one line of code and your timing changes.
In this case, esp with the nops, you should probably be using a scope anyway to see the i2c bus and since/when you have it on the scope you can try with and without those calls to see how it affects the waveform. It could also be a case of a bug in the peripheral or a feature maybe you cant hit some register too fast otherwise the peripheral breaks. or it could be a bug in a chip from 5 years ago and the code was written for that the bug is long gone, but they just kept re-using the code, you will see that a lot in vendor libraries.
What do you think about the while condition? Does the microchip not using a lot of CPU for that?
No, since the transmit buffer won't stay full for very long.
I asked myself this question and surprisingly saw a lot of similar code in internet.
What would you suggest instead?
Is there not a better way to do it? (I hate crazy loops :D)
Not that I, you, or apparently anyone else knows of. In what way do you think it could be any better? The transmit buffer won't stay full long enough to make it useful to retask the CPU.
What about the Nop() too, why two of them?
The Nop's ensure that the signal remains stable long enough. This makes this code safe to call under all conditions. Without it, it would only be safe to call this code if you didn't mess with the i2c bus immediately after calling it. But in most cases, this code would be called in a loop anyway, so it makes much more sense to make it inherently safe.
I am programming a microcontroller of the PIC24H family and using xc16 compiler.
I am relaying U1RX-data to U2TX within main(), but when I try that in an ISR it does not work.
I am sending commands to the U1RX and the ISR() is down below. At U2RX, there are databytes coming in constantly and I want to relay 500 of them with the U1TX. The results of this is that U1TX is relaying the first 4 databytes from U2RX but then re-sending the 4th byte over and over again.
When I copy the for loop below into my main() it all works properly. In the ISR(), its like that U2RX's corresponding FIFObuffer is not clearing when read so the buffer overflows and stops reading further incoming data to U2RX. I would really appreciate if someone could show me how to approach the problem here. The variables tmp and command are globally declared.
void __attribute__((__interrupt__, auto_psv, shadow)) _U1RXInterrupt(void)
{
command = U1RXREG;
if(command=='d'){
for(i=0;i<500;i++){
while(U2STAbits.URXDA==0);
tmp=U2RXREG;
while(U1STAbits.UTXBF==1); //
U1TXREG=tmp;
}
}
}
Edit: I added the first line in the ISR().
Trying to draw an answer from the various comments.
If the main() has nothing else to do, and there are no other interrupts, you might be able to "get away with" patching all 500 chars from one UART to another under interrupt, once the first interrupt has ocurred, and perhaps it would be a useful exercise to get that working.
But that's not how you should use an interrupt. If you have other tasks in main(), and equal or lower priority interrupts, the relatively huge time that this interrupt will take (500 chars at 9600 baud = half a second) will make the processor what is known as "interrupt-bound", that is, the other processes are frozen out.
As your project gains complexity, you won't want to restrict main() to this task, and there is no need to for it be involved at all, after setting up the UARTs and IRQs. After that it can calculate π ad infinitum if you want.
I am a bit perplexed as to your sequence of operations. A command 'd' is received from U1 which tells you to patch 500 chars from U2 to U1.
I suggest one way to tackle this (and there are many) seeing as you really want to use interrupts, is to wait until the command is received from U1 - in main(). You then configure, and enable, interrupts for RXD on U2.
Then the job of the ISR will be to receive data from U2 and transmit it thru U1. If both UARTS have the same clock and the same baud rate, there should not be a synchronisation problem, since a UART is typically buffered internally: once it begins to transmit, the TXD register is available to hold another character, so any stagnation in the ISR should be minimal.
I can't write the actual code for you, since it would be supposed to work, but here is some very pseudo code, and I don't have a PIC handy (or wish to research its operational details).
ISR
has been invoked because U2 has a char RXD
you *might* need to check RXD status as a required sequence to clear the interrupt
read the RXD register, which also might clear the interrupt status
if not, specifically clear the interrupt status
while (U1 TXD busy);
write char to U1
if (chars received == 500)
disable U2 RXD interrupt
return from interrupt
ISR's must be kept lean and mean and the code made hyper-efficient if there is any hope of keeping up with the buffer on a UART. Experiment with the BAUD rate just to find the point at which your code can keep up, to help discover the right heuristic and see how far away you are from achieving your goal.
Success could depend on how fast your micro controller is, as well, and how many tasks it is running. If the microcontroller has a built in UART theoretically you should be able to manage keeping the FIFO from overflowing. On the other hand, if you paired up a UART with an insufficiently-powered micro controller, you might not be able to optimize your way out of the problem.
Besides the suggestion to offload the lower-priority work to the main thread and keep the ISR fast (that someone made in the comments), you will want to carefully look at the timing of all of the lines of code and try every trick in the book to get them to run faster. One expensive instruction can ruin your whole day, so get real creative in finding ways to save time.
EDIT: Another thing to consider - look at the assembly language your C compiler creates. A good compiler should let you inline assembly language instructions to allow you to hyper-optimize for your particular case. Generally in an ISR it would just be a small number of instructions that you have to find and implement.
EDIT 2: A PIC 24 series should be fast enough if you code it right and select a fast oscillator or crystal and run the chip at a good clock rate. Also consider the divisor the UART might be using to achieve its rate vs. the PIC clock rate. It is conceivable (to me) that an even division that could be accomplished internally via shifting would be better than one where math was required.
I work in Code Composer Studio Version: 6.0.1.00040 with the card LCDK C6748.
In this card there is LINE_OUT for sampling out audio into speakers.
My question arises, because I encountered some phenomena that look like I reached a limit value when I assigened a value to LINE_OUT:
codec_data.channel[LEFT]= (uint16_t)outputLeft_referenceSignal;
// this union is where I have to "place" the audio sample I create,
// but I suspect outputLeft_referenceSignal exceed the limit value
When it happens it sounds, like a cracked "PACK" in the speakers and then the expected audio signal is not played
The T.I. has complete code examples on how to handle each of the built-in peripherals of the C6847 DSP.
I strongly suggest you start searching/reading the T.I. web site for info on the C6748 DSP
amongst other things, like initializing the DSP, you need to understand the usage of the McASP and the AIC31 peripherals.
It is not a simple write to a I/O address.
If you have setup the above peripherals, please post the relevant code so we can determine the underlying problem.
I'm working on a C program that transmits samples over USB3 for a set period of time (1-10 us), and then receives samples for 100-1000 us. I have a rudimentary pthread implementation where the TX and RX routines are each handled as a thread. The reason for this is that in order to test the actual TX routine, the RX needs to run and sample before the transmitter is activated.
Note that I have very little C experience outside of embedded applications and this is my first time dabbling with pthread.
My question is, since I know exactly how many samples I need to transmit and receive, how can I e.g. start the RX thread once the TX thread is done executing and vice versa? How can I ensure that the timing stays consistent? Sampling at 10 MHz causes some harsh timing requirements.
Thanks!
EDIT:
To provide a little more detail, my device is a bladeRF x40 SDR, and communication to the device is handled by a FX3 microcontroller, which occurs over a USB3 connection. I'm running Xubuntu 14.04. Processing, scheduling and configuration however is handled by a C program which runs on the PC.
You don't say anything about your platform, except that it supports pthreads.
So, assuming Linux, you're going to have to realize that in general Linux is not a real-time operating system, and what you're doing sure sounds as if has real-time timing requirements.
There are real-time variants of Linux, I'm not sure how they'd suit your needs. You might also be able to achieve better performance by doing the work in a kernel driver, but then you won't have access to pthreads so you're going to have to be a bit more low-level.
Thought I'd post my solution.
While the next build of the bladeRF firmware and FPGA image will include the option to add metadata (timestamps) to the synchronous interface, until then there's no real way in which I can know at which time instants certain events occurred.
What I do know is my sampling rate, and exactly how many samples I need to transmit and receive at which times relative to each other. Therefore, by using conditional variables (with pthread), I can signal my receiver to start receiving samples at the desired instant. Since TX and RX operations happen in a very specific sequence, I can calculate delays by counting the number of samples and multiplying by the sampling rate, which has proven to be within 95-98% accurate.
This obviously means that since my TX and RX threads are running simultaneously, there are chunks of data within the received set of samples that will be useless, and I have another routine in place to discard those samples.
I have a homework assignment for my Operating Systems class where I need to write an interrupt table for a simulated OS. I already have, from a previous assignment, the appropriate drivers all set up:
My understanding is that I should have an array of interrupt types, along the lines of interrupt_table[x], where x = 0 for a trap, x = 1 for a clock interrupt, etc. The interrupt_table should contain pointers to the appropriate handlers for each type of interrupt, which should then call the appropriate driver? Am I understanding this correctly? Could anyone point me in the right direction for creating those handlers?
Thanks for the help.
Most details about interrupt handlers vary with the OS. The only thing that's close to universal is that you typically want to do as little as you can reasonably get away with in the interrupt handler itself. Typically, you just acknowledge the interrupt, record enough about the input to be able to deal with it when you're ready, and return. Everything else is done separately.
Your understanding sounds pretty good.
Just how simulated is this simulated OS? If it runs entirely on a 'machine' of your professor's own design, then doubtless she's given some specifications about what interrupts are provided, how to probe for interrupts that may be there, and what sorts of tasks interrupt handlers should do.
If it is for a full-blown x86 computer or something similar, perhaps the Linux arch/x86/pci/irq.c can provide you with tips.
What you do upon receiving interrupt depends on the particular interrupt. The thumb rule is to find out what is critical that needs to be attended to for the particular interrupt, then do "just" that (nothing more nothing less) and come out of the handler as soon as possible. Also, the interrupt handlers are just a small part of your driver (that is how you should design). For example, if you receive an interrupt for an incoming byte on some serial port, then you just read the byte off the in-register and put it on some "volatile" variable, wind up things and get out of the handler. The rest (like, what you will do with the incoming byte on the serial port) can be handled in the driver code.
The thumb rule remains: "nothing more, nothing less"