Search code examples
stm32gpiostm32f0libopencm3

Unable to use PC15 as GPIO input on stm32f030rc


I'm working on a project using an stm32f030rc. I need to use PC15 as a GPIO input but it appears I'm unable to.

I understand the couple PC14/PC15 is shared with the LFE oscillator, but of course I'm not using that function. Moreover, I am able to read the correct pin level on the PC14 GPIO. In the datasheed regarding my model the PC15 pin is marked as a I/O with OSC32_OUT as additional function: can it be used as input at all?

For reference, this is the C code I'm using to test the functionality; I'm using libopencm3 for initialization.

#include <libopencm3/stm32/rcc.h>
#include <libopencm3/stm32/gpio.h>

static void clock_setup(void)
{
    rcc_clock_setup_in_hsi_out_48mhz();

    /* Enable GPIOA, GPIOB, GPIOC clock. */
    rcc_periph_clock_enable(RCC_GPIOA);
    rcc_periph_clock_enable(RCC_GPIOB);
    rcc_periph_clock_enable(RCC_GPIOC);
    rcc_periph_clock_enable(RCC_DBGMCU);

    /* Enable clocks for GPIO port B and C*/
    gpio_mode_setup(GPIOA, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO5);
    gpio_mode_setup(GPIOC, GPIO_MODE_INPUT, GPIO_PUPD_NONE, GPIO15);
    gpio_mode_setup(GPIOC, GPIO_MODE_INPUT, GPIO_PUPD_NONE, GPIO14);
}

int main(void)
{
    unsigned long long i = 0;

    clock_setup();

    /* Blink the LED (PA8) on the board with every transmitted byte. */
    while (1)
    {
        gpio_toggle(GPIOA, GPIO5); /* LED on/off */
        for (i = 0; i < 400000; i++) /* Wait a bit. */
            __asm__("nop");

        // This conditional is never entered
        if (gpio_get(GPIOC, GPIO15) == 0) {
            __asm__("nop");
            __asm__("nop");
            __asm__("nop");
        }

       // This one works
        if (gpio_get(GPIOC, GPIO14) == 0) {
            __asm__("nop");
            __asm__("nop");
            __asm__("nop");
        }

    }

    return 0;
}

Solution

  • PC14 & PC15 have the same configuration properties. Of course, there are some limitations regarding using these pins as outputs (including PC13), but it should be okay to use them as inputs as long as you don't activate LSE functionality.

    PC14 & PC15 are GPIO inputs after power-up and considering that LSE is disabled by default, you should be able to use them directly even without any configuration.

    As you don't have any problems with PC14, I suspect 3 possible causes:

    1) A bug in the GPIO code the library provides. Although it's very unlikely, it's easy to test. You can remove the configuration code for PC14 & PC15, as they are GPIO inputs after power-up by default. This eliminates the possibility of having a bug in gpio_mode_setup() function. To avoid using gpio_get() function, you can use the following code:

    if (GPIOC->IDR & (1 << 15) == 0)
    

    2) A bug in the clock config code the library provides. Again, this one is very unlikely, but you can test it by removing the rcc_clock_setup_in_hsi_out_48mhz() function. MCU uses HSI running at 8 MHz after power-up.

    3) This can be a hardware problem. I suggest checking the voltage on PC15. Test it by physically connecting it to GND. Also measure PC14 for comparison. Among these 3 possible causes I can think of, this is the most probable one.