Recursive Struct

Go To Last Post
5 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi All,

I have a problem that I hope some of you might be able to give me some hints on.

I'm using an ARM9 and ARMCC compiler, so not AVR related this time, but i was hoping for some generic ANSI C guidence from the wealth of knowledge in the forum.

I have a MCU with 5 UARTs, all of which are serviced by ISRs on Rx and Tx Ready signals that copy one character from a circular buffer to the UART or vida versa. When a situation where Tx Ready interrupt fires and there is no data in the buffer waiting for transmission an underrun occurs. This is signaled to the main program using a flag so that the main program can copy the first byte of the data for transmission directly to the UART instead of placing it in the buffer as I shall not see another Tx Ready interrupt until the UART has finished sending a character.

To keep things generic and re-useable I have described a buffer using a structure to keep everything in one place. There two buffers for each UART (Rx and Tx), all of which are serviced by the same functions by passing in a pointer to the structure of the comm port of interest.

The struct is given below:

typedef struct 
{
    volatile Int16 in;
    volatile Int16 out;
    volatile Int16 sizeOfBuffer;
    Int8            *buffer;
    Boolean         underrunFlag;
    Boolean         overrunFlag;
    Int8            tempChar;
    void (*underrunFunct_p)(void * ptr);
    void (*overrunFunct_p)(void * ptr);
}commNBuffer_t;
 void comm0TxBuf_underrunFunct(void * ptr )
 {
    commNBuffer_t *commNBuffer_p;
    commNBuffer_p = (commNBuffer_t) ptr;
    
    M_writeInt32(SIOSTA,SIOSTA_TRIRQ);      /* clear TRIRQ flag */
    M_writeInt32(SIOBUF, commNBuffer_p->tempChar);
    
 }

It contains two markers (in & out), the size of the buffer, a pointer to the buffer, flags and two pointers to functions that are to be called in the event to a overrun or underrun.

My problem is that the pointers to functions need to pass in a reference to the (same) structure so that they know the parameters of the buffer, however this can't be done in my current way as the type commNBuffer_t has not been defined yet. I have in effect made a recursive type! :-( So I have tried to use the type void instead.

Can I define the function pointers in such as way as to take a generic pointer (to the strucure) that is not of the type commNBuffer_t, but can still point to the structure? In the code above I have tried to pass in a void type and then to cast it in the called function for use but I receive an error:

Error: cast to type "commNBuffer_t" is not allowed.
commNBuffer_p = (commNBuffer_t) ptr;

Thanks for your help.

Tim

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Just a suggestion of the top of my head. Try:

commNBuffer_p = (commNBuffer_t*)ptr;

You need to typecast the void pointer into a commNBuffer_t pointer, not just a regular commNBuffer_t type.

- Dean :twisted:

Make Atmel Studio better with my free extensions. Open source and feedback welcome!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks Dean, That work a treat!

Tim
:D

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

w0067814 wrote:

My problem is that the pointers to functions need to pass in a reference to the (same) structure so that they know the parameters of the buffer, however this can't be done in my current way as the type commNBuffer_t has not been defined yet. I have in effect made a recursive type! :-( So I have tried to use the type void instead.

I wouldn't do that because you loose type checking that way. Instead, define the typedef before defining the struct:

typedef struct commNBuffer_s commNBuffer_t;

struct commNBuffer_s
{
    volatile Int16 in;
    volatile Int16 out;
    volatile Int16 sizeOfBuffer;
    Int8            *buffer;
    Boolean         underrunFlag;
    Boolean         overrunFlag;
    Int8            tempChar;
    void (*underrunFunct_p)(commNBuffer_t * ptr);
    void (*overrunFunct_p)(commNBuffer_t * ptr);
};
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks dicks, that seems like a much more professional way of doing it. I shall change my code accordingly.

Tim