This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

HTTP Server example - stuck on recv

Other Parts Discussed in Thread: MSP430G2553

Alright. It's me again.

I am trying to port the HTTP Server to my platform (AVR32/UC3). I got already pretty far and accept works as expected. Yet, I do not receive any data. It appears that my controller hangs during the following code section:

int
simple_link_recv(long sd, void *buf, long len, long flags, sockaddr *from,
                socklen_t *fromlen, long opcode)
{
	unsigned char *ptr, *args;
	tBsdReadReturnParams tSocketReadEvent;
	
	ptr = tSLInformation.pucTxCommandBuffer;
	args = (ptr + HEADERS_SIZE_CMD);
	
	// Fill in HCI packet structure
	args = UINT32_TO_STREAM(args, sd);
	args = UINT32_TO_STREAM(args, len);
	args = UINT32_TO_STREAM(args, flags);
	
	// Generate the read command, and wait for the 
	hci_command_send(opcode,  ptr, SOCKET_RECV_FROM_PARAMS_LEN);
	
	// Since we are in blocking state - wait for event complete
	SimpleLinkWaitEvent(opcode, &tSocketReadEvent);
	
	// In case the number of bytes is more then zero - read data
	if (tSocketReadEvent.iNumberOfBytes > 0)
	{
		// Wait for the data in a synchronous way. Here we assume that the bug is 
		// big enough to store also parameters of receive from too....
		SimpleLinkWaitData(buf, (unsigned char *)from, (unsigned char *)fromlen);
	}
	
	errno = tSocketReadEvent.iNumberOfBytes;
	
	return(tSocketReadEvent.iNumberOfBytes);
}

To be more exact, it's the SimpleLinkWaitData call that never finishes. So I get the event, iNumberOfBytes is 347 (Wireshark shows 347 for the length of the TCP part so this seems ok) but SimpleLinkWaitData then never returns. What is supposed to happen here? Do I get all data at once or how does the module device how much data to send?

Any thing I could try to get this working?

  • Alright, I've decided to go deeper and am now back at the physical level :-(

    I've been going through the code for simple_link_recv which is where the magic is supposed to happen. I made some screenshots from the first part (where it sends the command and receives a short response). At the end, an IRQ happens which is very short. Can you tell me if the following sequence is correct? I made some screenshots from the logicanalyzer and also extracted the data into readable form. Where can I decode this data? Is there some page that describes these commands in detail?

    "The "overview":

    "First part, probably the command":

    Second part, probably the response:

    The decoded data for convenience and the code:

    Code section (from simple_link_recv):
    // Generate the read command, and wait for the 
    hci_command_send(opcode,  ptr, SOCKET_RECV_FROM_PARAMS_LEN);
    
    // Since we are in blocking state - wait for event complete
    SimpleLinkWaitEvent(opcode, &tSocketReadEvent);
    
    Transmission:
    02 00 FF 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
    01 00 11 00 00 01 04 10 0C 01 00 00 00 90 03 00 00 00 00 00 00 14
    (Pause until IRQ)
    02 00 00 00 11 04 04 10 0D 00 01 00 00 00 5B 01 00 00 01 00 00 00
    03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03
    (Small IRQ Glitch, am I missing this, is this on purpose ?)

    I have a feeling that I am missing the last IRQ, but I would like to confirm what I am sending and receiving is correct, then I would go one step further.

  • Anyone able to send a logic analyzer sequence from a working recv call?

  • Again, going deeper:

    This is from the end of the sequence with additional pins:

    IRQENSTATE: Shows, if the IRQ for the IRQ line is in "enabled" state. If the signal is high, the IRQ is enabled

    DEBUG-A: Is high, whenever the Controller is within the ISR for the IRQ. 

    To me it looks like that the IRQ occurs although we are still in the ISR - is this intended behaviour? I am still wondering if the CC3000 now wants me to read from it. So should the sequence be:

    WRITE COMMAND -> READ DATA - READ DATA - ...

    Is the following assumption correct: Once the ISR is finished with, the IRQ flag has already been set again and the ISR shall be entered again immediately? 

  • Alright. Found out why the interrupt is not triggered again. This interrupt happens exactely between "SpiPause" and "SpiResume". The line DEBUG-C in the picture below shows when the interrupt is disabled (low) and when it's enabled (high). Since I'm basically using the code from your spi.c I assume this is intended behaviour. 

    What is supposed to happen after that: Shall the interrupt be triggered or not?

  • I have never been a big fan of the SpiResumeSpi and SpiPauseSpi functions...

    The wiki states: "SpiResumeSpi – Resumes SPI communication under the assumption that it was previously paused within the SPI driver itself."

    However, SpiResumeSpi and SpiPauseSpi (at least in my case) are identical to the "interrupt enable" and "interrupt disable" callback functions registered to wlan_init(). (I have asked before but I still don't understand why they don't just do away these call backs.) The documentation from the wiki on these callbacks is:

    "sWlanInterruptEnable – The callback provided during the wlan_init call and invoked to enable an interrupt on the IRQ line of SPI"

    "sWlanInterruptDisable - The callback provided during the wlan_init call and invoked to disable an interrupt on the IRQ line of SPI"

    In my code, I have also simply disabled the interrupt and re enable it. However looking at your scenario above, that certainly seems to be wrong...  what I am now pretty sure of is they are supposed to defer the interrupt.

    Looking at the MSP4302553 basic wifi application code, they do technically "disable the interrupt" however there is more to the MSP430 architecture....

    *MSP430 Digression*

    For MSP430 ports, there are three key registers for port interrupts:

    PxIE - Interrupt Enable. Each bit sets whether an interrupt with be triggered when the corresponding PxIFG bit is set.

    PxIFG - Interrupt Flags. Each bit is set if the corresponding port undergoes the selected edge trigger determined by PXIES. 

    PxIES - Interrupt Edge Select. A 0 monitors for a low to high transition in the corresponding port pin, a 1 monitors for a high to low transition.

    It was this thread that made me go back and check what TI are doing in the MSP430G2553 code. Their functions are the following:

    #define SPI_IRQ_PIN    BIT6
    #define SPI_IRQ_PORT   P2IE
    
    
    //*****************************************************************************
    //
    //! This function enter point for write flow
    //!
    //!  \param  SpiPauseSpi
    //!
    //!  \return none
    //!
    //!  \brief  The function triggers a user provided callback for 
    //
    //*****************************************************************************
    
    void 
    SpiPauseSpi(void)
    {
    	SPI_IRQ_PORT &= ~SPI_IRQ_PIN;
    }
    
    
    //*****************************************************************************
    //
    //! This function enter point for write flow
    //!
    //!  \param  SpiResumeSpi
    //!
    //!  \return none
    //!
    //!  \brief  The function triggers a user provided callback for 
    //
    //*****************************************************************************
    
    void 
    SpiResumeSpi(void)
    {
    	SPI_IRQ_PORT |= SPI_IRQ_PIN;
    }
    

    What I realised was while they disable the interrupt (PxIE), they do nothing for the interrupt flag (PxIFG). PxIFG will monitor the pin regardless if PxIE bit is set (I had to Google this one to be sure: http://e2e.ti.com/support/microcontrollers/msp430/f/166/t/144187.aspx).

    So in their code, if an interrupt comes in and SpiPauseSpi has been called, PxIFG gets set, but the code continues as expected. In SpiResumeSpi PxIE is set, and the MSP430 immediately calls the interrupt handler.

    *End of MSP430 Digression*


    So SpiPauseSpi() / sWlanInterruptDisable shouldn't really be seen as disabling interrupts, but deferring them until SpiResumeSpi()/sWlanInterruptEnable is called. How this is handled seems to be very much platform dependant, which I think is why there is some confusion, since presumably whoever wrote the wiki were more familiar with MSP430's.

  • Alan, you're awesome. That sounds perfectly logical. I will have to try this to see if it is really the case and potentially my problem here. I'll update this thread once I can confirm this.

  • Alright. The "defer IRQ" part seems to be correct because I get one step further now. So thank you a lot, Alan.

    Nevertheless. I will dump the module and switch to a Wiznet or H&D Wireless type. With a driver that is so fragile, contains infinite loops en masse and doesn't appear to work "out of the box" plus the lack of documentation for the various commands plus non-existing support from TI there is no use in pursuing any further. Just what I experienced in the last few hours (all with the same codebase, only change was SPI frequency):

    • When I set the SPI speed to 4 MHz, recv doesn't work at all
    • When I set the SPI speed to 10 MHz, I was able to successfully call recv about 25% of my tries
    • When I set the SPI speed to 16MHz, the previous "select" call starts to fail

    TI, get this driver in shape so it isn't dependent on any timing and so it is more robust. Then the module might be a good choice but until then there is no way this module can be used in a real product.