title: Casting troubles when using bit-banding macros with a pre-cast address on Cortex-M3
body: <p>TL;DR: </p>
  
  <ol>
  <li>Why isn't <code>(unsigned long)(0x400253FC)</code> equivalent to <code>(unsigned long)((*((volatile unsigned long *)0x400253FC)))</code>?</li>
  <li>How can I make a macro which works with the former work with the latter?</li>
  </ol>
  
  <h1>Background Information</h1>
  
  <h2>Environment</h2>
  
  <p>I'm working with an ARM Cortex-M3 processor, the <a href="http://www.ti.com/tool/ek-lm3s6965" rel="nofollow">LM3S6965</a> by TI, with their <a href="http://www.ti.com/tool/sw-lm3s" rel="nofollow">StellarisWare</a> (free download, export controlled) definitions.  I'm using gcc version 4.6.1 (Sourcery CodeBench Lite 2011.09-69).  Stellaris provides definitions for some 5,000 registers and memory addresses in "inc/lm3s6965.h", and I really don't want to redo all of those.  However, they seem to be incompatible with a macro I want to write.</p>
  
  <h2>Bit Banding</h2>
  
  <p>On the ARM Cortex-M3, a portion of memory is aliased with one 32-bit word per bit of the peripheral and RAM memory space.  Setting the memory at address 0x42000000 to 0x00000001 will set the first bit of the memory at address 0x40000000 to 1, but not affect the rest of the word.  To change bit 2, change the word at 0x42000004 to 1. That's a neat feature, and extremely useful. According to the ARM Technical Reference Manual, the algorithm to compute the address is: </p>
  
  <pre><code>bit_word_offset = (byte_offset x 32) + (bit_number × 4)
  bit_word_addr = bit_band_base + bit_word_offset
  </code></pre>
  
  <p>where:</p>
  
  <ul>
  <li><code>bit_word_offset</code> is the position of the target bit in the bit-band memory region.</li>
  <li><code>bit_word_addr</code> is the address of the word in the alias memory region that maps to the
  targeted bit.</li>
  <li><code>bit_band_base</code> is the starting address of the alias region.</li>
  <li><code>byte_offset</code> is the number of the byte in the bit-band region that contains the targeted bit.</li>
  <li><code>bit_number</code> is the bit position, 0 to 7, of the targeted bit</li>
  </ul>
  
  <h1>Implementation of Bit Banding</h1>
  
  <p>The <code>"inc/hw_types.h"</code> file includes the following macro which implements this algorithm.  To be clear, it implements it for a word-based model which accepts 4-byte-aligned words and 0-31-bit offsets, but the resulting address is equivalent:</p>
  
  <pre><code>#define HWREGBITB(x, b)                                               \
      HWREGB(((unsigned long)(x) &amp; 0xF0000000) | 0x02000000 |               \
             (((unsigned long)(x) &amp; 0x000FFFFF) &lt;&lt; 5) | ((b) &lt;&lt; 2))
  </code></pre>
  
  <p>This algorithm takes the base which is either in SRAM at 0x20000000 or the peripheral memory space at 0x40000000) and ORs it with 0x02000000, adding the bit band base offset. Then, it multiples the offset from the base by 32 (equivalent to a five-position left shift) and adds the bit number.</p>
  
  <p>The referenced HWREG simply performs the requisite cast for writing to a given location in memory:</p>
  
  <pre><code>#define HWREG(x)                                                              \
      (*((volatile unsigned long *)(x)))
  </code></pre>
  
  <p>This works quite nicely with assignments like</p>
  
  <pre><code>HWREGBITW(0x400253FC, 0) = 1;
  </code></pre>
  
  <p>where 0x400253FC is a magic number for a memory-mapped peripheral and I want to set bit 0 of this peripheral to 1.  The above code computes (at compile-time, of course) the bit offset and sets that word to 1.</p>
  
  <h1>What doesn't work</h1>
  
  <p>Unfortunately, the aforememntioned definitions in "inc/lm3s6965.h" already perform the cast done by HWREG.  I want to avoid magic numbers and instead use provided definitions like </p>
  
  <pre><code>#define GPIO_PORTF_DATA_R       (*((volatile unsigned long *)0x400253FC))
  </code></pre>
  
  <p>An attempt to paste this into HWREGBITW causes the macro to no longer work, as the cast interferes:</p>
  
  <pre><code>HWREGBITW(GPIO_PORTF_DATA_R, 0) = 1;
  </code></pre>
  
  <p>The preprocessor generates the following mess (indentation added):</p>
  
  <pre><code>(*((volatile unsigned long *)
      ((((unsigned long)((*((volatile unsigned long *)0x400253FC)))) &amp; 0xF0000000)
      | 0x02000000 |
      ((((unsigned long)((*((volatile unsigned long *)0x400253FC)))) &amp; 0x000FFFFF) &lt;&lt; 5)
      | ((0) &lt;&lt; 2))
  )) = 1;
  </code></pre>
  
  <p>Note the two instances of </p>
  
  <pre><code>(((unsigned long)((*((volatile unsigned long *)0x400253FC)))))
  </code></pre>
  
  <p>I believe that these extra casts are what is causing my process to fail.  The following result of preprocessing <code>HWREGBITW(0x400253FC, 0) = 1;</code> does work, supporting my assertion: </p>
  
  <pre><code>(*((volatile unsigned long *)
      ((((unsigned long)(0x400253FC)) &amp; 0xF0000000) 
      | 0x02000000 |
      ((((unsigned long)(0x400253FC)) &amp; 0x000FFFFF) &lt;&lt; 5)
      | ((0) &lt;&lt; 2))
  )) = 1;
  </code></pre>
  
  <p>The <code>(type)</code> cast operator has right-to-left precedence, so the last cast should apply and an <code>unsigned long</code> used for the bitwise arithmetic (which should then work correctly).   There's nothing implicit anywhere, no float to pointer conversions, no precision/range changes...the left-most cast should simply nullify the casts to the right.</p>
  
  <h1>My question <sub><sup>(finally...)</sup></sub></h1>
  
  <ol>
  <li>Why isn't <code>(unsigned long)(0x400253FC)</code> equivalent to <code>(unsigned long)((*((volatile unsigned long *)0x400253FC)))</code>?</li>
  <li>How can I make the existing <code>HWREGBITW</code> macro work?  Or, how can a macro be written to do the same task but not fail when given an argument with a pre-existing cast?</li>
  </ol>