External Coexistence Interface Pin Reference

In the P1 datasheet it says that these pins can be used as GPIO if not used for Bluetooth coexistence. How do I access these pins in software?

At present, I don’t believe you can. This actually came up in discussion today - @BDub has the details there!

1 Like

Thanks @mdma. It would be good to know the details. We’ve already turned boards, based on the datasheet and are in the process of validating the functionality. If we can’t use these IO pins we’ll have to look at adding an IO expander and re-spinning the boards.

@BDub can you fill me in here? Thanks!

I’ll update this thread when I have more info on how to access these pins. AFAIK it’s possible, just need to work out the details on how.

Thanks @BDub! Please let me know if I can help.

These are hard to use:

  • WiFi has to be booted (ie you can’t access these in low power modes)
  • They are not failsafe GPIOs, so you need to be careful with voltage levels etc
  • Reading/writing is via the SDPCM_GET/_SET interface (ie packetized over SDIO)
  • Latency is not good (as packets are queued so network traffic will slow stuff down)
  • I don’t believe there’s example code in WICED to do this, we had to figure it out ourselves

Essentially you need to use IOVAR_STR_GPIOOUT to access the pins; you can get the values (SDPCM_GET with an IOVAR_STR_GPIOOUT buffer) and write them (SDPCM_GET with an IOVAR_STR_GPIOOUT buffer that contains a mask and value).

2 Likes

Thanks @hfiennes! I think I’m ok with these restrictions. For my application I’m using these pins to set the gain on an audio amplifier that will not change very often. Can you give me a quick example of setting these pins high and low?

So, not actually having a P1 to test this with this will be somewhat of a shot in the dark, but:

BTCX_TXCONF = GPIO_3
BTCX_STATUS = GPIO_4
BTCX_RF_ACTIVE = GPIO_5

GPIO_3 is bit 3 (1< <3) in the set ioctl. You may have to experiment a bit. The other problem is that the WICED libraries in Particle’s github may not actually have all the necessary symbols exported to be able to link these functions, but the particle people should be able to help here I guess - possibly by adding this to the closed source part of WICED and publishing an updated binary.

In theory to set GPIO_3 high and low you’d do

    ei_wwd_wifi_set_gpio_state((1<<3), (1<<3)); // high
    ei_wwd_wifi_set_gpio_state((1<<3), 0); // low

The following is pulled from the imp codebase (we had those GPIOs hooked up internally on the SD card imp to the STM32, so we needed to drive them for factory testing of modules to check all the pins were soldered… we’ve never used this outside of factory tests though):

    // Call with state pointing to a uint32_t[3]
    // I can't remember what comes back in these 3 words apart from the GPIO states are there somewhere
    wwd_result_t ei_wwd_wifi_get_gpio_state(uint32_t *state)
    {
        wiced_buffer_t buffer;
        wiced_buffer_t response;
        wwd_result_t result;
    
        if ( NULL == wwd_sdpcm_get_iovar_buffer( &buffer, 12, IOVAR_STR_GPIOOUT ) )
        {
            return WWD_BUFFER_ALLOC_FAIL;
        }
        result = wwd_sdpcm_send_iovar( SDPCM_GET, buffer, &response,
                                       WWD_STA_INTERFACE );
        if ( result == WWD_SUCCESS )
        {
            memcpy(state, host_buffer_get_current_piece_data_pointer(response),
                   12);
            host_buffer_release( response, WWD_NETWORK_RX );
        }
        return result;
    }
    
    // Called to set GPIOs. 
    // mask = bitset of bits TO SET (ie, to change a bit, the corresponding bit in the mask should be 1)
    // value = bitset of new bit values.
    // essentially this is : newval = (oldval & ~mask) | value
    wwd_result_t ei_wwd_wifi_set_gpio_state(uint32_t mask, uint32_t value)
    {
        wiced_buffer_t buffer;
    
        uint32_t *state = wwd_sdpcm_get_iovar_buffer(&buffer, 8, IOVAR_STR_GPIOOUT);
        if (!state) {
            return WWD_BUFFER_ALLOC_FAIL;
        }
    
        state[0] = mask;
        state[1] = value;
    
        wwd_result_t result = wwd_sdpcm_send_iovar( SDPCM_SET, buffer, NULL,
                                                    WWD_STA_INTERFACE );
        return result;
    }

(edited when I worked out code quoting!)

2 Likes

Sorry, I’ve been away for a little bit with other hardware issues. We now have an updated design and are using the P0 module but it’s still unclear to me how we access these pins. Thanks @hfiennes for the sample code but I wasn’t able to actually get it to set the pins.

Is there documentation some place about how to set register values and what registers are what? From the particle documentation it just says:
When two radios occupying the same frequency band are used in the same system, such as Wi-Fi and Bluetooth, a coexistence interface can be used to coordinate transmit activity, to ensure optimal performance by arbitrating conflicts between the two radios.
Pad # PØ Pin Name PØ Pin # I/O Description
1 BTCX_RF_ACTIVE 9 I Signals Bluetooth is active
2 BTCX_STATUS 10 I Signals Bluetooth priority status and TX/RX direction
3 BTCX_TXCONF 11 O Output giving Bluetooth permission to TX
When these pads are programmed to be used as a Bluetooth coexistence interface, they’re set as high impedance on power up and reset. Alternatively, they can be individually programmed to be used as GPIOs through software control. They can also be programmed to have an internal pull-up or pull-down resistor.

Thanks for the help!

There’s essentially no documentation from Broadcom on controlling these pins.

Did you manage to get my code compiled? It looked like you needed access to some bits of WICED that aren’t exposed in the photon github.

Yeah I spent a few hours looking at it but was not able to get the code to compile. Not really sure what else to do.