Macros for bit band access?

Tip / Sign in to post questions, reply, level up, and achieve exciting badges. Know more

cross mob
Anonymous
Not applicable

Are there macros anywhere in the standard generated code (or, in a code sample, if need be) for setting / clearing / toggling bits through the Cortex M3 bit-banding feature?

   

I'd like to take advantage of this for uninterruptible read/modify/write of some status bits associated with each of a bunch of buffers in the SRAM. From what I understand it should be possible, but I'm wondering if I need to roll my own. I'm OK with assembly, not so much with the C preprocessor.

0 Likes
10 Replies
Anonymous
Not applicable

Doug,

   

 

   

The info provided at the link below may be of some help.

   

http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.faqs/ka4203.html

0 Likes
Anonymous
Not applicable

Thanks, I will do that.

   

You guys should consider rolling this into the libraries that come with PSoC Creator. It looks to me like there's no impact on code size as long as it is unused.

0 Likes
Anonymous
Not applicable

 Thanks for the reference, dasq... I'm also interested in an easy and consistent way to access the bitband region.

   

 

   

For anyone interested, the target URL has been slightly changed to http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.faqs/ka4203.html

   

 

   

IOW, just add an 'l' to the original URL and you should be fine. But be aware, this document has been cached on the ARM site, so I'm not sure if that will limit its availability

   

-PCPete

0 Likes
Anonymous
Not applicable

bump for feature request! it would be great if the API generated defines for this so you don't need to roll your own.

ideally, the API functions for GPIOs etc should just USE this, they're crazy slow as it is now.

as an example, try running this and compare the speed. when just toggling pins, the three methods below got me output frequencies of about 300 KHz (API call), 1.1 MHz (API macro) and 1.7 MHz (bitbanding).

#define BITBAND_PERI_REF  0x40000000

#define BITBAND_PERI_BASE  0x42000000

#define BITBAND_PERI(a,b) ((BITBAND_PERI_BASE + (a-BITBAND_PERI_REF)*32 + (b*4)))  // Convert PERI address

#define TESTPIN_BITBAND_DATAOUT *((volatile unsigned char *) (BITBAND_PERI(Testpin_0,0))) // bit 0 is CY_PINS_PC_DATAOUT

#define TESTPIN_BITBAND_DATAIN  *((volatile unsigned char *) (BITBAND_PERI(Testpin_0,4))) // bit 4 is CY_PINS_PC_PIN_STATE

int main()

{  

    while (1) {

        // API call

        Testpin_Write(1);

        Testpin_Write(0);

      

        // API macro

        CyPins_SetPin(Testpin_0);

        CyPins_ClearPin(Testpin_0);

      

        // Bitbanding

        TESTPIN_BITBAND_DATAOUT = 1;

        TESTPIN_BITBAND_DATAOUT = 0;

    }

}

this is awesome!

team Cypress,

please implement this in the code-generators & replace all _write(1) (0) with this instead for a great & free speed-up

seems for GPIO TESTPIN_BITBAND_DATAOUT has a less stable duty cycle
test.PNG

0 Likes

For fastest Pin write in PSoC5 you can use (use Release / Compile for Speed settings)

TestPin_Control=1; // 2 clocks

TestPin_Control=0; // 3 clocks

Explanation:

C++ vs Assembly vs Verilog. on Vimeo

0 Likes

It seems in PSoC Creator 4.0 it looks like this:

while (1)

{

Testpin_DR = 1 << Testpin_SHIFT;  

Testpin_DR = 0 << Testpin_SHIFT;

I see 12MHz. Thank you.

0 Likes

Evgeniy,

Indeed, looks like the Cypress changed underlying code and made it faster. Now setting pin High takes only one clock. Setting pin Low is also one clock, and 2 clocks goes to "for" loop. Attached screenshots at 24MHz

IMG_20180407_134859.jpg

Below is a screenshot when 8 consecutive Hi/Lo statement are placed in the loop, making it 1000 will assimptotically bring it to clock/2:

/odissey1

IMG_20180407_134359.jpg

0 Likes
WaHo_350141
Level 2
Level 2
10 sign-ins 10 replies posted First solution authored

Bit-banding works for PSoC5 CM3, but not for the later Cortex M7.  An easy and efficient way to use bit-banding is to make three changes to the linker .LD file.

MEMORY
{
rom (rx) : ORIGIN = 0x0, LENGTH = 262144
ram (rwx) : ORIGIN = 0x20000000 - (65536 / 2), LENGTH = 65536
bitbandalias (rw) : ORIGIN = 0x22000000, LENGTH = 640
}

Then between the .heap and .stack sections add

.bitband 0x20000000 (NOLOAD) :
{
*(.bitband)
} >ram

And finally add

.bitbandalias 0x22000000 (NOLOAD) :
{
*(.bitbandalias)
} >bitbandalias

Then in the source code create a variable in ram to allocate the memory:

// allocate bitband space (32 * 5 = 160 bits)
uint32_t bb_flag[5] __attribute__((section (".bitband")));

bb_flag is never referenced directly, but its bits are accessed with the following:

struct bb_Data {
// Bit Band flag bit definitions
int32 SCAL_REQUEST; // Recalibrate shunt a/d request
int32 SHUNTDATA; // Shunt data available flag
int32 SPISETTINGS; // SPI settings available
} bbdata __attribute__((section (".bitbandalias")));

For instance,

bbdata.SHUNTDATA=0 will clear the second bit

value = bbdata.SHUNTDATA;

Exactly three assembly instuctions are required to set or clear a bit!

0 Likes