Hi I want to send an array of data to a USB pen drive using LPC1768. and USBhostlite code is available here: >ics.nxp.com/.../ and I removed Uart from codes so that it just copies data to usb. the codes that i modified are:
void Main_Write(void){ USB_INT32S fdw; USB_INT32U bytes_read; char temp[8]; USB_INT08U temp_buf[504]={0}; int i,j={0}; bytes_read=9; fdw = FILE_Open(FILENAME_W, RDWR); if (fdw>0) { do{ sprintf(temp,"%d",bytes_read); for (j=0;j<9;j++){ temp_buf [i]=(temp[j]); i++; } temp_buf [i]=0xA; i++; bytes_read ++; }while(i<=504); FILE_Write(fdw,temp_buf,504); FILE_Close(fdw); }else{ return; } }
sprintf converts bytes_read to ascii codes then it is sent to temp_buf using a do{...}while() then an "MSWRITE.TXT" file is created in usb disk and finally the buffer will be written to the usb disk.
these codes work properly, when size of the buffer(temp_buf) is less than "90". but when i change the buffer size to a bigger number(eg: 504), the program doesn't work! it even doesn't creates any empty text file(due to file_open) i traced file_open routine and i found that the problem is in MS_BulkRecv routine. because the program runs before calling MS_BulkRecv and halts during calling this line. this routine is as follows:
*********************************************************************************************** * RECEIVE THE BULK DATA * * Description: This function is used to receive the bulk data * * Arguments : None * * Returns : OK if Success * ERR_INVALID_BOOTSIG if Failed * **********************************************************************************************/ USB_INT32S MS_BulkRecv ( USB_INT32U block_number, USB_INT16U num_blocks, volatile USB_INT08U *user_buffer) { USB_INT32S rc; int i; volatile USB_INT08U *c = user_buffer; for (i=0;i<MS_BlkSize*num_blocks;i++) *c++ = 0; Fill_MSCommand(block_number, MS_BlkSize, num_blocks, MS_DATA_DIR_IN, SCSI_CMD_READ_10, 10); rc = Host_ProcessTD(EDBulkOut, TD_OUT, TDBuffer, CBW_SIZE); if (rc == OK) { rc = Host_ProcessTD(EDBulkIn, TD_IN, user_buffer, MS_BlkSize * num_blocks); if (rc == OK) { rc = Host_ProcessTD(EDBulkIn, TD_IN, TDBuffer, CSW_SIZE); if (rc == OK) { if (TDBuffer[12] != 0) { rc = ERR_MS_CMD_FAILED; } } } } return (rc); }
can any body tell me why this increase in buffer size causes the program not to work? and help me to solve it?
thanks Amir
last lines of your badly formatted code
..... return; } } // what happens here?
} // what happens here?
when the size of buffer is less than 90: an "mswrite.txt" file is created in usb drive. but when this size is greater than 90, nothing is created in usb drive. even FILE_OPEN doesn't run properly. and next lines doesn't run!
Amir
*********************************************************************************************** * RECEIVE THE BULK DATA * * Description: This function is used to receive the bulk data * * Arguments : None * * Returns : OK if Success * ERR_INVALID_BOOTSIG if Failed * **********************************************************************************************/ USB_INT32S MS_BulkRecv ( USB_INT32U block_number, USB_INT16U num_blocks, volatile USB_INT08U *user_buffer)
/************************************************************************************************ * TYPE DEFINITIONS OF DATA TYPES ************************************************************************************************/ typedef unsigned int USB_INT32U; typedef signed int USB_INT32S; typedef unsigned short USB_INT16U; typedef signed short USB_INT16S; typedef unsigned char USB_INT08U; typedef signed char USB_INT08S;
there are some typo in Description of the routines. I think this is just a mistake. when the routines, recives the bulk data, it must exits parameters as input.
Thanks Amir
Your Main_Write function is doing a number of things that have 'undefined behavior' so basically anything can happen (see "nasal demons"):
- What do you think the initial value of 'i' is? (Hint: the compiler says "Warning: C3017W: i may be used before being set") - Why do you read uninitialized elements of 'temp' beyond what 'sprintf' has written? - Why do you think it's ok to access 'temp[8]'? (It is probably harmless to read it, but is poor style.)
>What do you think the initial value of 'i' is?.. the compiler didn't tell me any warning.Because 'i' is a local variable. >-Why do you think it's ok to access 'temp[8]'? thanks, i corrected it. >- Why do you read uninitialized elements of 'temp' beyond what 'sprintf' has written? i can't understand you. Can you explain this to me, more?
even if i remove if{...} (after FILE_OPEN), the problem exists. I think it belongs to addressing issues.
> > What do you think the initial value of 'i' is?..
You haven't answered the question. (I think that in answering the question you will discover something important.)
> the compiler didn't tell me any warning.Because 'i' is a local variable.
Have you perhaps suppressed or overlooked the warning? The compiler (armcc) *does* give me that warning when I build the code you posted. In fact, part of the reason it is able to give the warning is *because* 'i' is a local variable.
(Even if the compiler didn't give you a warning (for example, if it wasn't smart enough to do so) that would not change the fact that there is a problem with the initial value of 'i' in the code. The compiler is not required to warn about all 'undefined behavior' and it doesn't.)
> > - Why do you read uninitialized elements of 'temp' beyond what 'sprintf' has written? > i can't understand you. Can you explain this to me, more?
sprintf only writes the bytes up to the terminating '\0', so the first time it's called it effectively does:
temp[0] = '9'; temp[1] = '\0';
but then your code also reads temp[1]... which have never been written. This is technically 'undefined behavior' but is unlikely to do anything more harmful that read some arbitrary values. Still, you probably don't really want them in your output buffer.
> What do you think the initial value of 'i' is?.. int i,j={0}; Keil debugger recognizes the initial value as '0'.
>sprintf only writes the bytes up to the terminating '\0', so... Thanks I got it! it will be solved with an if{...}.
even if i remove if{...} (after FILE_OPEN), the problem exists.
but I was Wrong. the max buffer size is 360. when i define a new buffer it doesn't works! Total size of the buffers must not exceed 360. and i don't know how to solve it!
Best Regards Amir
"Keil debugger recognizes the initial value as '0'."
So when you have an uninitialized variable and look at it with the debugger, you think that the value you see represents a valid initialization? Don't you think it matters what contents there was in RAM before you entered the function?
I think your method of using the debugger and look is a very bad method. Don't you think it is sooo much better to let the language standard decide if the good is ok or not? Or do you think any program without known or seen error is a correct program?
i saw in the debugger that previous value of 'i' resets to 0. doesn't int i,j={0};, works as initialization too? OK, I initialize the i in a separated line.; is this helps the buffer to have the larger Size?
You saw in the debugger a machine-code instruction that assigned a value of 0 to i?
OK! I thought the compiler creates what shows in the debugger. I suppose to initialize the i separately. and concentrate on the buffer size.
Thanks Dr Westermark Amir
Auto variables takes whatever values that are in the memory at that specific memory location.
The debugger then allows you to see the value.
But it is up to you to make sure that there is an assign that guarantees that the variable has the _correct_ value. And not just happens, by pure chance, to get a random value that looks "good".
doesn't int i,j={0};, works as initialization too?
It doesn't. Not for 'i', anyway.
Thanks Every body! My problem was solved I defined the array before main (after #includes). and it worked. I don't know why save the data in stack can cause this problem.