cancel
Showing results for 
Search instead for 
Did you mean: 

Improve bitbang driver speed

martingingras9
Associate II
Posted on November 24, 2014 at 21:06

Hi,

I am using the STM32F2xx cube API to implement a raw bitbang usb driver for the FTDI ft245.  I am currently achieving speed of 5000 bytes/s.  I would like to improve the speed.  The bitbang code is simple as:

<..>

__disable_irq();

// set data pins      

        HAL_GPIO_WritePin(FT_D0_PORT, FT_D0_PIN, (CHECK_BIT(data, 0) == 0) ? GPIO_PIN_RESET : GPIO_PIN_SET);

        HAL_GPIO_WritePin(FT_D1_PORT, FT_D1_PIN, (CHECK_BIT(data, 1) == 0) ? GPIO_PIN_RESET : GPIO_PIN_SET);

        HAL_GPIO_WritePin(FT_D2_PORT, FT_D2_PIN, (CHECK_BIT(data, 2) == 0) ? GPIO_PIN_RESET : GPIO_PIN_SET);

        HAL_GPIO_WritePin(FT_D3_PORT, FT_D3_PIN, (CHECK_BIT(data, 3) == 0) ? GPIO_PIN_RESET : GPIO_PIN_SET);

        HAL_GPIO_WritePin(FT_D4_PORT, FT_D4_PIN, (CHECK_BIT(data, 4) == 0) ? GPIO_PIN_RESET : GPIO_PIN_SET);

        HAL_GPIO_WritePin(FT_D5_PORT, FT_D5_PIN, (CHECK_BIT(data, 5) == 0) ? GPIO_PIN_RESET : GPIO_PIN_SET);

        HAL_GPIO_WritePin(FT_D6_PORT, FT_D6_PIN, (CHECK_BIT(data, 6) == 0) ? GPIO_PIN_RESET : GPIO_PIN_SET);

        HAL_GPIO_WritePin(FT_D7_PORT, FT_D7_PIN, (CHECK_BIT(data, 7) == 0) ? GPIO_PIN_RESET : GPIO_PIN_SET);

__enable_irq();

<...>

The pins are configured as follow:

FT_DX_PORT, FT_DX_PIN, GPIO_MODE_INPUT, GPIO_NOPULL, GPIO_SPEED_HIGH

is there anything I can do or example I could follow or inspire myself? (beside implementing some asm?)

thanx

Mart

#bitband-bit-bang
20 REPLIES 20
Posted on November 25, 2014 at 04:40

Architecturally BSRR is a 32-bit register

The assignment would permitted a rotate, harder to do in C

Remember the interactions with the APB/AHB will be less efficient than operations on processor registers, and that peripheral registers are ''volatile'' and will be re-read, often unnecessarily with compound modification. Consider loading settings into a temporary register, and modify that before storing the finished value back.
Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
mrjaner
Associate II
Posted on November 25, 2014 at 08:38

why doesnt stm32cube have any usb samples for stm32f4-discovery? there is a FS USB port on

Posted on November 25, 2014 at 08:45

The barrel shift in ARM is ''free'', i.e. rotation can be added to any instruction without timing penalty. Thumb(2) places restrictions on this, but still rotation is quite effective.

This:

void foo(uint8_t a) __attribute__((noinline));

void foo(uint8_t a) {

  uint32_t t;

  t = a & 0x0F;

  t = (t >> 2) | (t << (32 - 2)); // ROR 2

  t = t | ((t >> 16) | (t << (32 - 16))); // + ROR 16

  GPIOD->BSRR = t;               // this needs augmented stm32f4xx.h

}

compiles in gcc into

 800019c:    f000 000f     and.w    r0, r0, #15

 80001a0:    f44f 6340     mov.w    r3, #3072    ; 0xc00

 80001a4:    ea4f 00b0     mov.w    r0, r0, ror #2

 80001a8:    f2c4 0302     movt    r3, #16386    ; 0x4002

 80001ac:    ea40 4030     orr.w    r0, r0, r0, ror #16

 80001b0:    6198          str    r0, [r3, #24]

 80001b2:    4770          bx    lr

which runs in 9 cycles including the ''call'' and ''ret''; and much of the time is consumed to load the register address which in real program would often get optimized for multiple accesses to the same peripheral.

JW

Posted on November 25, 2014 at 08:47

> why doesnt stm32cube have any usb samples for stm32f4-discovery? there is a FS USB port

on

1. don't hijack other threads, start your own

2. don't start it in this forum as it is a cube-related question - rather, start it in the dedicated [DEAD LINK /public/STe2ecommunities/mcu/Lists/STM32Java/AllItems.aspx]''software tools'' subforum
mrjaner
Associate II
Posted on November 25, 2014 at 08:58

if you read my posts, i started but nobody answer to me. but i will start again

Posted on November 25, 2014 at 16:37

if you read my posts, i started but nobody answer to me. but i will start again

Forums depend on others to answer the posts, if no one present has an answer, it will be left unanswered.
Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
martingingras9
Associate II
Posted on November 27, 2014 at 16:14

Hi,

I understand what Clive1 said about ''design ahead of time''.  If all ports were aligned, it will be easy to write directly in the GPIOX->BSSR register.   Now, according to the current state, if I have the value 0x6 to transmit:

Port D

0                1               1             0

PIN_1    PIN_0       PIN_15    PIN_14

I dont see how can I can do it with doing a stupid HAL_GPIO_WritePin for each like I am doing in order to save some cycle and improve performance...

Mart

Posted on November 27, 2014 at 17:00

> 0                1               1             0

> PIN_1    PIN_0       PIN_15    PIN_14

>

> I dont see how can I can do it with doing a stupid HAL_GPIO_WritePin for each like I am

> doing in order to save some cycle and improve performance...

But why would you use HAL_GPIO_WritePin(), once it's stupid?

I gave you the solution above, what is in it that is not clear?

JW

martingingras9
Associate II
Posted on December 01, 2014 at 20:35

Hi Mr. waclawek,

obviously, I dont understand the mechanic behind it.

However, testing the provided function, I ended up with a value of of 0x80018001 in ''t''. However, using  HAL_GPIO_WritePin, I have 0x00008001 in the GPIOD->ODR register which is correct:

input: 0x46

Port E

0              1               0                 0

PIN_7    PIN_8     PIN_9       PIN_10

Port D

0                1               1             0

PIN_1    PIN_0       PIN_15    PIN_14

Mart

martingingras9
Associate II
Posted on December 01, 2014 at 20:47

I made a mistake:

input: 0x46

Port E

0              1               0                 0

PIN_10    PIN_9     PIN_8       PIN_7

Port D

0                1               1             0

PIN_1    PIN_0       PIN_15    PIN_14