SAM7 CDC example

nobody wrote on Saturday, August 20, 2005:

[moved from private email thread]

Rumor has it that there is a different version of the AT91SAM7S port and USB
example that has some bug fixes and uses the USB differently, however I
don’t see anything like this listed on your site.  Is there any chance that
you could forward me the project?  I’m working with USB on the AT91SAM7S and
would love to play with FreeRTOS as well.

nobody wrote on Saturday, August 20, 2005:

[moved from private email thread]

Attached find two zip files.  USB.zip contains the original serial port
emulation USB files, USBCDC.zip contains a modification there of for later
versions of FreeRTOS.

These files were not written by me so I cannot directly support them,
although they are heavily based on the file included in the FreeRTOS
download.

nobody wrote on Saturday, August 20, 2005:

[moved from private email thread]

Thanks!  I’m actually using different headers as well that are dated 3/2005
and have quite a few definition changes from the headers you’ve included.
Since you’re running these files, I had a question for you about a possible
bug.  I’ve tried to port over the USB-CDC project using these files and I
get compiler errors at the call to portEXIT_SWITCH_ISR() and upon looking at
portmacro.h this code looks a bit peculiar.  The compiler barfs from what
looks like a second #define in the middle of the curly braced expression.  I
could modify the placement of the braces to get it to compile, but I don’t
want to change the functionality from what it was intended.  The code
section is below.  Comments? Thanks!

/*-----------------------------------------------------------
* ISR entry and exit macros.  These are only required if a task switch
* is required from the ISR.
*----------------------------------------------------------*/

#define portENTER_SWITCHING_ISR()

/* Save the context of the interrupted task. */

portSAVE_CONTEXT();
\


/* We don’t know the stack requirements for the ISR, so the frame
*/
/* pointer will be set to the top of the task stack, and the
stack*/
/* pointer left where it is.  The IRQ stack will get used for any
*/
/* functions calls made by this ISR. */

asm volatile ( “MOV R11, LR” );

{

#define portEXIT_SWITCHING_ISR( SwitchRequired )

/* If a switch is required then we just need to call */

/* vTaskSwitchContext() as the context has already been */

/* saved. */

if( SwitchRequired )

{

vTaskSwitchContext();

}

}

/* Restore the context of which ever task is now the highest */

/* priority that is ready to run. */

portRESTORE_CONTEXT();

#define portYIELD() asm volatile ( "SWI"
);
/*-----------------------------------------------------------*/

nobody wrote on Saturday, August 20, 2005:

I can’t really see from email as the formatting is all screwy, however I
assume you are referring to the positioning of the ‘{’ and ‘}’ in the macro?

The two macros ENTER_SWITCHING and EXIT_SWITCHING have to be used in pairs.
The ENTER macro opens a {, the closing macro closes with a }, so the { and }
match up in a pair.

The ENTER macro MUST be the FIRST line in the ISR code, the EXIT macro must
be the last line in the ISR.

The reason for this is stack usage.  If your ISR uses any local stack
variables then the compiler will add function prologue code to allocate
space on the stack for the variables - and this must NOT happen prior to the
context being saved.  Therefore the inner block ({}) is used to allow local
variables to be declared later.

Therefore the ISR looks like this:

void vAnISR( void )
{
____portENTER_SWITCHING_ISR();

____/* Macro places an opening { here. Therefore the variable below is not
____allocated until after the macro has completed. */

____int iAVariableCanBeDeclaredHere;

____/* ISR code can go here. */

____/* Macro places a closing } here to close the block. */
____portEXIT_SWITCHING_ISR();
}

Making sense?

nobody wrote on Saturday, August 20, 2005:

Ah that is very clear, thanks much for the explanation.  My confusion
originated from the USB-CDC.c file you sent, where the vUSB_ISR makes the
following call before the end of the ISR:

portEND_SWITCHING_ISR( cTaskWokenByPost );

This macro was undefined in the port files you sent, so I did some searching
in the FreeRTOS distribution and found it in
Source\portable\IAR\AtmelSAM7S64\portmacro.h with the following definition
(sorry for the formatting problems):

/* Task utilities. */
#define portEND_SWITCHING_ISR( xSwitchRequired )
{

extern void vTaskSwitchContext( void ); \


if( xSwitchRequired )

{

vTaskSwitchContext();

}

}
/*-----------------------------------------------------------*/

I looked in the portmacro.h that you had sent and there was something that
looked similar (the portEXIT_SWITCHING_ISR) with almost identical format
except for its necessary coupling to the portENTER_SWITCHING_ISR, so I
assumed that there was just a bug in the define for the portENTER and
portEXIT macros.

Should the portEND_SWITCHING_ISR in USB-CDC.c be removed and instead the
whole ISR surrounded by portENTER_SWITCHING_ISR and portEXIT_SWITCHING_ISR?
Since space needs to be allocated on the stack for a switching ISR, I don’t
see how a lone portEND_SWITCHING_ISR worked before.

nobody wrote on Saturday, August 20, 2005:

[moved from private email thread]

Ok I see, IAR Vs GCC differences.  Yes you need to use the macros, in a
pair, from the GCC and discard the IAR equivalent.

In the IAR version the context is saved from an ASM wrapper, before the C
code is ever called.  This is necessary as IAR does not have the same inline
assembler capabilities of GCC.

Take a look at the SerialISR.c file in the GCC LPC2000 demo.  This shows how
to use the GCC type macros.

rtel wrote on Saturday, September 03, 2005:

The GCC USB CDC demo is now included in the FreeRTOS V3.2.1 download - see the SAM7X lwIP demo documentation page for more information.