I hope this is not a silly question, but I'm not able to find the answer to my problem myself.
I'm working on an Atmega32U4 microcontroller device, which is supposed to receive a series of bytes and store them. My code is based on a CDC Virtual Serial driver template from the LUFA-Library 151115. In order to test my code, I use the very useful tool ScriptCommunicator 04.11. The microcontroller unit (MCU) is connected via USB to the PC and is treated as a serial com port device by the PC host. My OS is Windows 7 64 bit.
Currently, I'm writing a function in which six values shall be received and stored.
For that I use the following code:
int16_t Register_1 = 0;
int16_t Register_2 = 0;
int16_t Register_3 = 0;
int16_t Register_4 = 0;
int16_t Register_5 = 0;
int16_t Register_6 = 0;
int16_t serial_byte = 0;
int8_t loop = 1;
do
{
serial_byte = CDC_Device_ReceiveByte(&VirtualSerial_CDC_Interface);
serial_byte &= 0x00FF;
switch (loop)
{
case 1: Register_1 = ad7194_byte; break;
case 2: Register_2 = ad7194_byte; break;
case 3: Register_3 = ad7194_byte; break;
case 4: Register_4 = ad7194_byte; break;
case 5: Register_5 = ad7194_byte; break;
case 6: Register_6 = ad7194_byte; break;
}
CDC_Device_USBTask(&VirtualSerial_CDC_Interface);
USB_USBTask();
loop ++ ;
printf("%i" PRId32 "\n", serial_byte) ;
_delay_ms(1000);
} while (loop < 7);
I have previously used a similar code snippet and everything seemed to be working fine. Now I identified the following problem:
The device is continuously reveiving the value "255ld". For when I test the above code with the ScriptCommunicator, I receive this value six times(which is why the printf-statement is included in the above code).
I have the suspicion that this happens because Windows is treating the MCU as a common USB device, e.g. a mouse? Could that be the case?
Or what could else be the reason for this?
How can I work around my problem?
Thanks in advance for any hints and answers!
Wrong use of format.
int16_t serial_byte = 0;
// v (remove i)
// printf("%i" PRId32 "\n", serial_byte) ;
// 16 not 32
printf("%" PRId16 "\n", serial_byte) ;
Thanks for the answer, which did not solve my problem directly, but kind of brought me to the solution.
Solution:
I received the 255 values although I didn't send anything to the MCU.
But:
If no byte is received, the LUFA CDC_Device_ReceiveByte-function returns -1. I forgot to check for that value before the serial_byte &= 0x00FF; statement. The -1 value was then mixed up and the 255 value turned out.
Silly mistake again, which costed me a lot of time again.
Related
This is going to be a bit abstract due to the specific ARM (LPCXpresso 1115R/303) Cortex M0 and the H6 bluetooth module, and with NXP software there are a ton of driver files that are linked so hopefully the code snip below will be enough to identify the problem.
I am creating a simple menu system through bluetooth. Everything works with communcation. I send the message from the board, it is visible on the phone, I respond and print the value in the console of the program. All are exactly what I want them to be. But this is what happens:
1) start debug session and resume
2) 1st menu sends to phone, correct.
3) Type response to phone and send, correct.
4) message appears in console exactly as entered from phone (Just the number 1 appears)
5) Have if loop that checks to see if Buffer value == '1';
6) must not == 1 because it never enters the loop.
7) reprints the value of the buffer, and it still equals 1.
The only hint I have is a warning that says "makes integer from pointer without a cast [-Wint-conversion]" on the assignment line as indicated below.
void ArmPeripheral() {
UARTCount = 0;
LPC_UART->IER = IER_THRE | IER_RLS; /* Disable RBR */
UARTSend( (uint8_t *)menu1, sizeof(menu1));
LPC_UART->IER = IER_THRE | IER_RLS | IER_RBR; /* Re-enable RBR */
while(1) {
if(UARTCount != 0){
printf("%s 1st print\n",UARTBuffer);
int bVal = UARTBuffer; // This is where the error occurs, tried uint8_t, did not work.
printf("%s This is bVal\n",bVal);
if(bVal == 1) { //have tried 1, '1', and "1" none work
printf("inside loop %s...\n",UARTBuffer);
printf("%s This is bVal\n",bVal);
LEDControl();
}
printf("%s second print\n",UARTBuffer);
UARTCount = 0;
}
}
}
enter image description here
Nevermind, it was just a simple pointer issue. UARTBuffer is a external volatile uint8_t in the UART.c file, and even though it is not defined as a pointer, it is pointing to a buffer somehow.
int bVal = *UARTBuffer;
if(bVal == '1') {
The above worked, but if anyone has any more in depth information that could explain why I would be interested in knowing. This is how I initialized the buffer:
extern volatile uint32_t UARTCount;
extern volatile uint8_t UARTBuffer[BUFSIZE];
Using Atmel studio 7, with STK600 and 32UC3C MCU
I'm pulling my hair over this.
I'm sending strings of a variable size over UART once every 5 seconds. The String consists of one letter as opcode, then two chars are following that tell the lenght of the following datastring (without the zero, there is never a zero at the end of any of those strings). In most cases the string will be 3 chars in size, because it has no data ("p00").
After investigation I found out that what supposed to be "p00" was in fact "0p0" or "00p" or (only at first try after restarting the micro "p00"). I looked it up in the memory view of the debugger. Then I started hTerm and confirmed that the data was in fact "p00". So after a while hTerm showed me "p00p00p00p00p00p00p00..." while the memory of my circular uart buffer reads "p000p000p0p000p0p000p0p0..."
edit: Actually "0p0" and "00p" are alternating.
The baud rate is 9600. In the past I was only sending single letters. So everything was running well.
This is the code of the Receiver Interrupt:
I tried different variations in code that were all doing the same in a different way. But all of them showed the exact same behavior.
lastWebCMDWritePtr is a uint8_t* type and so is lastWebCMDRingstartPtr.
lastWebCMDRingRXLen is a uint8_t type.
__attribute__((__interrupt__))
void UartISR_forWebserver()
{
*(lastWebCMDWritePtr++) = (uint8_t)((&AVR32_USART0)->rhr & 0x1ff);
lastWebCMDRingRXLen++;
if(lastWebCMDWritePtr - lastWebCMDRingstartPtr > lastWebCMDRingBufferSIZE)
{
lastWebCMDWritePtr = lastWebCMDRingstartPtr;
}
// Variation 2:
// advanceFifo((uint8_t)((&AVR32_USART0)->rhr & 0x1ff));
// Variation 3:
// if(usart_read_char(&AVR32_USART0, getReadPointer()) == USART_RX_ERROR)
// {
// usart_reset_status(&AVR32_USART0);
// }
//
};
I welcome any of your ideas and advices.
Regarts Someo
P.S. I put the Atmel studio tag in case this has something to do with the myriad of debugger bugs of AS.
For a complete picture you would have to show where and how lastWebCMDWritePtr, lastWebCMDRingRXLen, lastWebCMDRingstartPtr and lastWebCMDRingBufferSIZE are used elsewhere (on the consuming side)
Also I would first try a simpler ISR with no dependencies to other software modules to exclude a hardware resp. register handling problem.
Approach:
#define USART_DEBUG
#define DEBUG_BUF_SIZE 30
__attribute__((__interrupt__))
void UartISR_forWebserver()
{
uint8_t rec_byte;
#ifdef USART_DEBUG
static volatile uint8_t usart_debug_buf[DEBUG_BUF_SIZE]; //circular buffer for debugging
static volatile int usart_debug_buf_index = 0;
#endif
rec_byte = (uint8_t)((&AVR32_USART0)->rhr & 0x1ff);
#ifdef USART_DEBUG
usart_debug_buf_index = usart_debug_buf_index % DEBUG_BUF_SIZE;
usart_debug_buf[usart_debug_buf_index] = rec_byte;
usart_debug_buf_index++
if (!(usart_debug_buf_index < DEBUG_BUF_SIZE)) {
usart_debug_buf_index = 0; //candidate for a breakpoint to see what happened in the past
}
#endif
//uart_recfifo_enqueue(rec_byte);
};
it's the first time I see something like this. I'm starting to suspect it's a hardware fault.
whenever I try to send the contents of array "test" and that array is larger than 4 elements or I initialize all elements in the declaration it contains 0xff instead of values I try to initialise with.
this works fine. when I read values from the array in while(sending them to the lcd and uart) both readouts are consistent with test values:
uint8_t i=0;
uint8_t test[4] = {1,2,3,4};
while(i<5){
GLCD_WriteData(test[i]);
USART_Transmit(test[i]);
i++;
}
this doesn't, it returns 0xff instead of test[i] value:
uint8_t i=0;
uint8_t test[5] = {1,2,3,4,5};
while(i<5){
GLCD_WriteData(test[i]);
USART_Transmit(test[i]);
i++;
}
but this works! it returns proper values
uint8_t i=0;
uint8_t test[6] = {1,2,3,4,5};
while(i<5){
GLCD_WriteData(test[i]);
USART_Transmit(test[i]);
i++;
}
this also works:
uint8_t i=0;
uint8_t test[5];
test[0]=1;
test[1]=2;
test[2]=3;
test[3]=4;
test[4]=5;
while(i<5){
GLCD_WriteData(test[i]);
USART_Transmit(test[i]);
i++;
}
it works fine when compiled on linux
I swapped out an mcu for a different one and it works the way it should. must be an hardware problem
In first example you are going out of bounds of array test[4]. You are running while 5 times, when array has only 4 items length.
I think your problem is that you're overloading the USART. I assume that GLCD_WriteData() is VERY quick, and that USART_Transmit() buffers the character for transmission and then quickly returns. I don't know your hardware, so I can't tell - but a four-character buffer for a USART sounds reasonable.
Your five-character examples don't work because the actual character that you're trying to transmit is lost - so it puts an 0xFF in instead. You need to check the state of the USART buffer and wait for it to show that space is available (note NOT empty - that'd be inefficient!).
In the 8250 and 16450 UART chips there are two status bits:
TSRE says that the Transmit Shift Register is Empty;
THRE says that the Transmit Holding Register is Empty.
THRE can be set even when TSRE isn't - it's busy. I'd test TSRE and not send the next character until there's room - or set up a buffer and an interrupt handler.
If it's not the I/O hardware, then the only other thing that I can think of is the compiler is producing incorrect code. What is the exact declaration of USART_Transmit()? Does it expect a uint8_t? Or something else, like an int (for some reason)?
If it's something else, like int, please try the following code:
while(i<5){
int c = test[i]; // Whatever USART_Transmit wants
GLCD_WriteData(test[i]);
USART_Transmit(c);
i++;
} // while
If that always works, then you've got a compiler problem, not a hardware problem.
EDIT: Code for USART_Transmit() provided:
void USART_Transmit( uint8_t data ) {
//Wait for empty transmit buffer
while( !( UCSR0A & (1<<UDRE0)) );
//Put data into buffer, sends the data
UDR0 = data;
}
You've got something better than JTAG - you've got an LCD display! Although I don't know how many characters it has, or how long it takes to transmit a character...
You could try something like:
char Hex(uint8_t nibble) {
return nibble<10 ?
'0'+nibble :
'A'+nibble-10;
} // Hex
...
void Send(uint8_t c) {
uint8_t s;
UDR0 = c; // Send character NOW: don't wait!
do {
s = UCSR0A; // Get current USART state
//s = UCSR0A & (1<<UDRE0); // Or this: isolate ready bit...
GLCD_WriteData('x');
GLCD_WriteData(Hex(s >> 4)); // Write state-hi hex
GLCD_WriteData(Hex(s & 0xF)); // Write state-lo hex
} while (!(s & (1<<UDRE0))); // Until is actually ready
} // Send(c)
...
Send('A');
Send('B');
Send('C');
Assuming that UDRE0 is 3, then that code will result in a sequence like x00x00x00x00x00x08x00x00x00x00x08x00x00x00x08 if it is working. If it produces x08x08x08 then you've got a stuck UCSR0A bit, and it's hardware.
Old question, but giving my feedback since this is the first place I got sent while searching solution for same issue, getting even exact same results with the code samples in original question.
For me it was a bad Makefile that caused some sections to be left out by avr-objcopy as far as I know.
For example in my case, the original parameters for building my sample hex that were causing this issue:
${OBJCOPY} -j .text -O ihex led.elf led.hex
What worked a bit better:
${OBJCOPY} -O ihex -R .eeprom led.elf led.hex
I'm developing on an AD Blackfin BF537 DSP running uClinux. I have a total of 32MB SD-RAM available. I have an ADC attached, which I can access using a simple, blocking call to read().
The most interesting part of my code is below. Running the program seems to work just fine, I get a nice data package that I can fetch from the SD-card and plot. However, if I comment out the float calculation part (as noted in the code), I get only zeroes in the ft_all.raw file. The same occurs if I change optimization level from -O3 to -O0.
I've tried countless combinations of all sorts of things, and sometimes it works, sometimes it does not - earlier (with minor modifications to below), the code would only work when optimization was disabled. It may also break if I add something else further down in the file.
My suspicion is that the data transferred by the read()-function may not have been transferred fully (is that possible, even though it returns the correct number of bytes?). This is also the first time I initialize pointers using direct memory adresses, and I have no idea how the compiler reacts to this - perhaps I missed something, here?
I've spent days on this issue now, and I'm getting desperate - I would really appreciate some help on this one! Thanks in advance.
// Clear the top 16M memory for data processing
memset((int *)0x01000000,0x0000,(size_t)SIZE_16M);
/* Prep some pointers for data processing */
int16_t *buffer;
int16_t *buf16I, *buf16Q;
buffer = (int16_t *)(0x1000000);
buf16I = (int16_t *)(0x1600000);
buf16Q = (int16_t *)(0x1680000);
/* Read data from ADC */
int rbytes = read(Sportfd, (int16_t*)buffer, 0x200000);
if (rbytes != 0x200000) {
printf("could not sample data! %X\n",rbytes);
goto end;
} else {
printf("Read %X bytes\n",rbytes);
}
FILE *outfd;
int wbytes;
/* Commenting this region results in all zeroes in ft_all.raw */
float a,b;
int c;
b = 0;
for (c = 0; c < 1000; c++) {
a = c;
b = b+pow(a,3);
}
printf("b is %.2f\n",b);
/* Only 12 LSBs of each 32-bit word is actual data.
* First 20 bits of nothing, then 12 bits I, then 20 bits
* nothing, then 12 bits Q, etc...
* Below, the I and Q parts are scaled with a factor of 16
* and extracted to buf16I and buf16Q.
* */
int32_t *buf32;
buf32 = (int32_t *)buffer;
uint32_t i = 0;
uint32_t n = 0;
while (n < 0x80000) {
buf16I[i] = buf32[n] << 4;
n++;
buf16Q[i] = buf32[n] << 4;
i++;
n++;
}
printf("Saving to /mnt/sd/d/ft_all.raw...");
outfd = fopen("/mnt/sd/d/ft_all.raw", "w+");
if (outfd == NULL) {
printf("Could not open file.\n");
}
wbytes = fwrite((int*)0x1600000, 1, 0x100000, outfd);
fclose(outfd);
if (wbytes < 0x100000) {
printf("wbytes not correct (= %d) \n", (int)wbytes);
}
printf(" done.\n");
Edit: The code seems to work perfectly well if I use read() to read data from a simple file rather than the ADC. This leads me to believe that the rather hacky-looking code when extracting the I and Q parts of the input is working as intended. Inspecting the assembly generated by the compiler confirms this.
I'm trying to get in touch with the developer of the ADC driver to see if he has an explanation of this behaviour.
The ADC is connected through a SPORT, and is opened as such:
sportfd = open("/dev/sport1", O_RDWR);
ioctl(sportfd, SPORT_IOC_CONFIG, spconf);
And here are the options used when configuring the SPORT:
spconf->int_clk = 1;
spconf->word_len = 32;
spconf->serial_clk = SPORT_CLK;
spconf->fsync_clk = SPORT_CLK/34;
spconf->fsync = 1;
spconf->late_fsync = 1;
spconf->act_low = 1;
spconf->dma_enabled = 1;
spconf->tckfe = 0;
spconf->rckfe = 1;
spconf->txse = 0;
spconf->rxse = 1;
A bfin_sport.h file from Analog Devices is also included: https://gist.github.com/tausen/5516954
Update
After a long night of debugging with the previous developer on the project, it turned out the issue was not related to the code shown above at all. As Chris suggested, it was indeed an issue with the SPORT driver and the ADC configuration.
While debugging, this error messaged appeared whenever the data was "broken": bfin_sport: sport ffc00900 status error: TUVF. While this doesn't make much sense in the application, it was clear from printing the data, that something was out of sync: the data in buffer was on the form 0x12000000,0x34000000,... rather than 0x00000012,0x00000034,... whenever the status error was shown. It seems clear then, why buf16I and buf16Q only contained zeroes (since I am extracting the 12 LSBs).
Putting in a few calls to usleep() between stages of ADC initialization and configuration seems to have fixed the issue - I'm hoping it stays that way!
First my PIC is 16f1625 and I use MPLAB 8.86 for programming it.
My problem is simple, I have communicating between PC and PIC,PC sends one byte and PIC reads this byte, and do something.
My problem is that I would like to improve this for like this, PC send one letter like "R" and after he send the number that I'd like to set. Today i only have 4 possibility, PC send 0,1,2 or 5 and I set the resolution according to these.
switch(i) {
case 1:
pulsesPerMm = 10;
break;
case 2:
pulsesPerMm = 20;
break;
case 5:
pulsesPerMm = 51;
break;
case 10:
pulsesPerMm = 102;
break;
}
I receive the command like these:
while(!RCIF) /* set when register is not empty */
continue;
return RCREG;
Now I want to do something like this: I receive "R" that indicates that the next word will be resolution and after these, 2 bytes, that will be the new resolution and i will only have to do is convert the string into int (using atoi) and then i can set the pulsesPerMm.
The problem is that I have other commands that only requires one letter, so I don't want to change these.
Switch on rx chars instead of numbers then, in your 'R' case block only, call the getChar() function to return the next two chars and atoi() them.