Electronics > Microcontrollers

Issue with STM32F1 pull up pin

<< < (3/4) > >>

yashrk:

--- Quote from: radiolistener on April 11, 2024, 09:05:06 am ---you're needs to configure clock and enable clock for GPIO port

--- End quote ---

I have this function doing it.


--- Code: ---void gpio_init (GPIO_TYPE gpio_type){
    if(gpio_type.port == PORTA)
        GPIO_CLOCK_ENABLE_PORTA;

    if(gpio_type.port == PORTB)
        GPIO_CLOCK_ENABLE_PORTB;

    if(gpio_type.port == PORTC)
        GPIO_CLOCK_ENABLE_PORTC;

    if(gpio_type.port == PORTD)
        GPIO_CLOCK_ENABLE_PORTD;

    config_pin(gpio_type.port, gpio_type.pin, gpio_type.mode_type);
    config_pin_speed(gpio_type.port, gpio_type.pin, gpio_type.speed, gpio_type.mode);
}

--- End code ---

and defines are as follows.


--- Code: ---//CLOCK ENABLING
#define GPIO_CLOCK_ENABLE_ALT_FUNC  (RCC -> APB2ENR |= ( 1 << 0 ))
#define GPIO_CLOCK_ENABLE_PORTA     (RCC -> APB2ENR |= ( 1 << 2 ))
#define GPIO_CLOCK_ENABLE_PORTB     (RCC -> APB2ENR |= ( 1 << 3 ))
#define GPIO_CLOCK_ENABLE_PORTC     (RCC -> APB2ENR |= ( 1 << 4 ))
#define GPIO_CLOCK_ENABLE_PORTD     (RCC -> APB2ENR |= ( 1 << 5 ))

--- End code ---

pcprogrammer:
Take a good look at the code that sets the mode and configuration bits in the GPIO control registers. Either low or high control register.

It uses two separate functions to set the speed and the configuration but very nontransparent. It might be correct but I would fire the person who made it on the spot.
Setting up an array to obtain a number that can be calculated with two left shifts is absurd. Then doing bit manipulations where and-ing and or-ing just 4 bits is enough.  :palm:


--- Code: ---static uint32_t PINPOS[16] = {
    (0x00),
    (0x04),
    (0x08),
    (0x0C),
    (0x10),
    (0x14),
    (0x18),
    (0x1C),
    (0x00),
    (0x04),
    (0x08),
    (0x0C),
    (0x10),
    (0x14),
    (0x18),
    (0x1C)
};

static void config_pin (GPIO_TypeDef *port, uint32_t pinNumber, uint32_t mode_type){
    if (pinNumber >= 8){ // CONTROL HIGH REGISTER
        switch (mode_type)
        {
        case OUTPUT_GEN_PURPOSE | INPUT_ANALOG:
            port -> CRH &= ~(( 1 << CNF_POS_BIT1 ) | ( 1 << CNF_POS_BIT2 ));
            break;

        case OUTPUT_OD | INPUT_FLOATING:
            port -> CRH &= ~( 1 << CNF_POS_BIT2);
            port -> CRH |= ~( 1 << CNF_POS_BIT1);
            break;
       
        case OUTPUT_ALT_FUNCTION | INPUT_PU_PD:
            port -> CRH |= OUTPUT_ALT_FUNCTION << (CNF_POS_BIT1);
            break;
       
        case OUTPUT_ALT_FUNCTION_OD:
            port -> CRH |= OUTPUT_ALT_FUNCTION_OD << (CNF_POS_BIT1);
            break;
        }
    }
    else { // CONTROL LOW REGISTER
        switch (mode_type)
        {
        case OUTPUT_GEN_PURPOSE | INPUT_ANALOG:
            port -> CRL &= ~(( 1 << CNF_POS_BIT1 ) | ( 1 << CNF_POS_BIT2 ));
            break;

        case OUTPUT_OD | INPUT_FLOATING:
            port -> CRL &= ~( 1 << CNF_POS_BIT2);
            port -> CRL |= ~( 1 << CNF_POS_BIT1);
            break;
       
        case OUTPUT_ALT_FUNCTION | INPUT_PU_PD:
            port -> CRL |= OUTPUT_ALT_FUNCTION << (CNF_POS_BIT1);
            break;
       
        case OUTPUT_ALT_FUNCTION_OD:
            port -> CRL |= OUTPUT_ALT_FUNCTION_OD << (CNF_POS_BIT1);
            break;
        }
    }
}

static void config_pin_speed (GPIO_TypeDef *port, uint32_t pinNumber, uint32_t pinSpeed, uint32_t mode){
    if (pinNumber >= 8){ // CONTROL HIGH REGISTER
        if (mode == INPUT_MODE)
            port -> CRH &= ~( 1 << (PINPOS[pinNumber]) | 1 << (PINPOS[pinNumber] + 1));
        else
            port -> CRH |= (pinSpeed << (PINPOS[pinNumber]));
    }
    else { // CONTROL LOW REGISTER
        if(mode == INPUT_MODE)
            port -> CRL &= ~( 1 << (PINPOS[pinNumber]) | 1 << (PINPOS[pinNumber] + 1));
        else
            port -> CRL |= (pinSpeed << (PINPOS[pinNumber]));
    }
}

--- End code ---


--- Code: ---// INPUT MODES TYPE
#define INPUT_ANALOG    ((uint32_t) 0x00)
#define INPUT_FLOATING  ((uint32_t) 0x01) // default state at reset
#define INPUT_PU_PD     ((uint32_t) 0x02) // input with pullup or pulldown

// OUTPUT MODE TYPE
#define OUTPUT_GEN_PURPOSE          ((uint32_t) 0x00) // gerneal purpose output
#define OUTPUT_OD                   ((uint32_t) 0x01) // output open drain
#define OUTPUT_ALT_FUNCTION         ((uint32_t) 0x02) // push pull
#define OUTPUT_ALT_FUNCTION_OD      ((uint32_t) 0x03) // open drain

// HIGH BIT POSITION FOR CRH REGISTER CNFYG AND MODE
#define CNF_POS_BIT1    (PINPOS[pinNumber] + 2)
#define CNF_POS_BIT2    (PINPOS[pinNumber] + 3)

--- End code ---

With all the macros and the way it is done with the switch statement and the indexed array to change the mode and configuration bits it is needlessly complex.

If you really want to learn bare metal programming, forget that youtube channel and download the ST reference manual for the STM32F103 series and start with writing programs writing directly to the registers. When you understand the working of it try to come up with your own abstraction layer to make it easier for future development.

DavidAlfa:
I'd use ST LL libraries, they are basically the same..

GromBeestje:
PB3 is one of the JTAG pins (TDO). You need to release this pin from that role.
Assuming you are running SWD to debug, you could call
LL_GPIO_AF_Remap_SWJ_NOJTAG();
found in stm32f1xx_ll_gpio.h, then the pin will be usable.

Edit:typo

yashrk:
First, thank you everyone for their comments and reviewing the convoluted code which I shared.


--- Quote from: GromBeestje on April 11, 2024, 09:36:12 pm ---PB3 is one of the JTAG pins (TDO). You need to release this pin from that role.
Assuming you are running SWD to debug, you could call
LL_GPIO_AF_Remap_SWJ_NOJTAG();
found in stm32f1xx_ll_gpio.h, then the pin will be usable.

--- End quote ---

Tried it didn't work.


--- Quote from: pcprogrammer on April 11, 2024, 01:56:31 pm ---If you really want to learn bare metal programming, forget that youtube channel and download the ST reference manual for the STM32F103 series and start with writing programs writing directly to the registers. When you understand the working of it try to come up with your own abstraction layer to make it easier for future development.

--- End quote ---

Did just that and it worked, thanx! Here is the code BTW if someone stumbles on this thread.


--- Code: ---#include "stm32f10x.h"

int main(void){
// Configuring GPIO

RCC -> APB2ENR |= ( 1 << 4 ); // Enabling Clock for Port C

// For Pin C13 - LED
GPIOC -> CRH |= ( ( 1 << 20 ) | ( 1 << 21) ); // Set to 50 MHz Output Mode
GPIOC -> CRH &= ( uint32_t ) ~( ( 1 << 22 ) | ( 1 << 23) ); // Set to General Purpose push-pull

// For Pin C14
GPIOC -> CRH &= ( uint32_t ) ~( ( 1 << 24 ) | ( 1 << 25) ); // Set to Input mode 00
// Set Config to 10
GPIOC -> CRH &= ( uint32_t ) ~( 1 << 26 );
GPIOC -> CRH |= ( 1 << 27 );

GPIOC -> ODR |= ( 1 << 14 ); // Set pin pull up


while(1) {

for ( int i = 0; i <= 1000000; i++) ;
GPIOC -> BSRR = ( 1 << 13 ); // Set Pin C13
for ( int i = 0; i <= 5000000; i++) ;
GPIOC -> BSRR = ( 1 << ( 13 + 16 ) ); // Reset Pin C13

}

}

--- End code ---

I am planning to use libopencm3 for my future experiments, any comments on that will be helpful.

Also, any suggestion on how to do this bit wise operation better.

--- Code: --- // Set Config to 10
GPIOC -> CRH &= ( uint32_t ) ~( 1 << 26 );
GPIOC -> CRH |= ( 1 << 27 );

--- End code ---

Navigation

[0] Message Index

[#] Next page

[*] Previous page

There was an error while thanking
Thanking...
Go to full version
Powered by SMFPacks Advanced Attachments Uploader Mod