Jump to content

yugr

Members
  • Content Count

    7
  • Joined

  • Last visited

  1. yugr

    TI Compiler ABI

    My understanding was that COFF can't express some C++ semantics (e.g. templates) properly hence EABI is default. COFF and EABI also have different approach to initialization of globals which may be the reason for size differences.
  2. Try __get_interrupt_state/__set_interrupt_state and you'll never regret. -Yuri
  3. Nice to know, although it won't help in this particular case. Yes. While some compilers may treat those intrinsics as sequence points, there is nothing about them that tells the compiler that it can't cache a copy of the variable that's being examined (for example, in a loop waiting for head to be updated) because somebody else might change it outside visible flow of control. That's what volatile does. Hm, in gcc there's this infamous asm volatile ("" : : : "memory"); Maybe there's an equivalent in CCS compiler? Well, that is a solution but it'll force me to use internal details of my data type instead of nice abstract interface. Coming from PC world I strongly dislike abstraction leakage. Good point but user code can only access this module with public API so it should not be a problem.
  4. Np Looks like volatile is not precise enough. I wonder what happens if I just blindly cast it inside critical section: ring_buf *mybuf_efficient = (ring_buf *)mybuf; I'm afraid that would still be undefined and compiler-dependent behavior... That's an easy route but I'd try my best to avoid abstraction leakage, even when programming uC's. -Yuri
  5. oPossum, thanks for the comment although it didn't add much to what I already know. > One way is to temporally disable interrupts during critical sections of mainline code. > That will prevent an ISR from changing something 'behind your back'. It's clear that I need to disable interrupts but will it stop compiler from rearranging memory accesses? In particular from moving memreads before _disable_interrupts or after _enable_interrupts? I haven't found anything in TI compiler man on this topic. > You may still need volatile for some vars - like the head and tail pointer - requires careful study. The question is - do I need volatile if variable is already protected by _enable/disable_interrupts? -Yuri
  6. Hi guys, I've recently used ring buffer in my code which I declared volatile as I usually do for all variables which are shared between interrupts and normal code. It occured to me after a while that volatile would force compiler to generate a rather inefficient code. Here's an example typedef struct { char bytes[RING_BUF_SIZE]; unsigned head, tail; } ring_buf; #define rb_empty(rb) (rb.head == rb.tail) #define rb_pop(rb, byte) do { \ byte = rb.bytes[rb.head]; \ rb.head = (rb.head + 1) & RING_BUF_SIZE_MASK; \ } while(0) ... static volatile ring_buf mybuf; // Note the "volatile" here ... // Somewhere in main() _disable_interrupts(); if( !rb_empty(mybuf) ) rb_pop(mybuf, *byte); // 2 redundant memory accesses to rb.head due to volatile _enable_interrupts(); Because of volatile, rx_bytes.head will be read from memory three times: once in rb_empty and twice in rb_pop. In other words volatile will force compiler to load field every time instead of caching result in a register thus significantly decreasing performance. Is there any way to achieve interrupt safety without resorting to volatile (and loosing precious perf) in this case? My idea is that _enable/disable_interrupts may serve as compiler barriers (i.e. they prevent compiler from moving memory references behind and past them) they alone should be enough to guarantee correctness. Unfortunately compiler mans (for CCS at least) are silent on this topic. -Yuri
×