2008-03-19 11:50 PM
Bit Banding DMA problem
2011-05-17 03:27 AM
I'm trying to use bit banding to enabled/disable a DMA channel. The problem is when I write to the DMA enable bit, other bits in the DMA's CCR register are written to as well. Bits TCIE, MINC, PSIE & MSIZE are zeroed in this case and a bus error results as soon as the DMA transfer starts.
I'm using the recommended method for creating a C macro.#define PERIPH_BB_BASE ((u32)0x42000000)
#define PERIPH_BASE ((u32)0x40000000) #define BITBAND_PERI(a,b) ((PERIPH_BB_BASE + (a-PERIPH_BASE)*32 + (b*4))) #define DMA2_EN *((volatile unsigned char *)(BITBAND_PERI(DMA_Channel2_BASE,0)))So to enable the DMA channel in C:DMA2_EN = 1;
which creates the assembly code:LDR R0, [PC, #0x5C] ; R0 is loaded with the correct value of 0x42400380
MOVS R1, #0x1 STRB R1, [R0]A workaround would be to use a read-modify-write method for accessing the CCR register, but that defeats the purpose of having the bit band. Or, if I change the macro to point to a long instead of a char the enable bit is written to correctly and no other bit is modified. But why does this make a difference? The bit band isn't supposed to care if I write 0x01 or 0x00000001 to it. The DMA CCR register is the only one I've had this issue with when using bit banding (so far). This macro works:#define DMA2_EN *((volatile unsigned long *)(BITBAND_PERI(DMA_Channel2_BASE,0)))
So to enable the DMA channel in C:DMA2_EN = 1;
which creates the assembly code:LDR R0, [PC, #0x5C] ; R0 is loaded with the correct value of 0x42400380
MOVS R1, #0x1 STR R1, [R0]2011-05-17 03:27 AM
hi ryan,
hardware need not be insensitive to access width. for instance, GPIO registers must be accessed in word mode and flash must be written as half-words. I seem to remember that bitband bits must be accessed as words, which makes sense if as a hardware designer you are forced to choose. in the #define DMA2_EN macros remember to parenthesize the whole definition. I prefer to use these macros: #include ''stm32f10x_lib.h'' #define BB_BIT(REGISTER, BIT_NUMBER, BASE, BB_BASE) ((volatile s32*) ((BB_BASE) + (((u32) &(REGISTER)) - (BASE)) * 32 + (BIT_NUMBER) * 4)) #define PERIPHERAL_BIT(REGISTER, BIT_NUMBER) BB_BIT(REGISTER, BIT_NUMBER, PERIPH_BASE, PERIPH_BB_BASE) #define SRAM_BIT(REGISTER, BIT_NUMBER) BB_BIT(REGISTER, BIT_NUMBER, SRAM_BASE, SRAM_BB_BASE) #define MY_LED PERIPHERAL_BIT(GPIOC->ODR, 12) // *MY_LED = 1;2011-05-17 03:27 AM
lanchon,
Thanks for the reply. It's not really clear in the documentation whether the bit band should be accessed as a byte or word. ARM's technical FAQ shows an SRAM bit-band being accessed as a word and a peripheral bit-band being accessed as a byte. I guess I'll stick with word access only unless I can find some documentation that states otherwise. I like those macros... A lot easier to read. Ryan2011-05-17 03:27 AM
I'm sorry I can't remember where I read about word access. but I'm sure I did read something when I had to choose the ''return type'' of the BB_BIT macro.
2011-05-17 03:27 AM
There is a bitbanding example in ST's firmware library here;-
Look in folder STM32F10xFWLib\FWLib\examples\CortexM3\Example1