Sunday, March 30, 2014

Generate STM32 MCU pin configuration automatically on MCU

Building a project for STM32F4-Discovery I realized it's really hard to keep track of all the pins as they get configured in different files all over the project. It's either keeping a separate list of assignments and functions (maybe using STM's cube software) or just going through source files every time.

Or maybe just having MCU report how pins are configured?

Here's what I managed to get out of my STM32F407VGT6:
==============================
SMT32F407VG Configuration
------------------------------
PA0     Input           LOW,  NO_PULL
PA1     Input           LOW,  NO_PULL



PA2     Input           LOW,  NO_PULL
PA3     Input           LOW,  NO_PULL
PA4     Input           LOW,  NO_PULL
PA5     Input           HIGH, NO_PULL
PA6     Input           HIGH, NO_PULL
PA7     Input           HIGH, NO_PULL
PA8     AltFunc         AF1
PA9     Input           LOW,  NO_PULL
PA10    Input           LOW,  NO_PULL
PA11    Input           LOW,  NO_PULL
PA12    Input           LOW,  NO_PULL
PA13    AltFunc         AF0
PA14    AltFunc         AF0
PA15    AltFunc         AF0
------------------------------
PB0     Input           LOW,  NO_PULL
PB1     Input           LOW,  NO_PULL
PB2     Input           LOW,  NO_PULL
PB3     AltFunc         AF0
PB4     AltFunc         AF0
PB5     Input           LOW,  NO_PULL
PB6     Input           LOW,  NO_PULL
PB7     Input           HIGH, NO_PULL
etc...

You've got the idea. Here's the source code and you just need to call function printPinMap();.

utils.c:

#include "utils.h"
#include <stdio.h>

void printSeparator(uint8_t Symbol, uint8_t numOfSymb)
{
  int i = 0;
  for (i = 0; i < numOfSymb; i++)
  {
    printf("%c", Symbol);
  }
  printf("\r\n");
}

void printPinName(GPIO_TypeDef *port, uint8_t pin)
{
  if (port == GPIOA)
  { 
      printf("PA%d", pin);
  }
  if (port == GPIOB)
  { 
      printf("PB%d", pin);
  }
  if (port == GPIOC)
  { 
      printf("PC%d", pin);
  }
  if (port == GPIOD)
  { 
      printf("PD%d", pin);
  }
  if (port == GPIOE)
  { 
      printf("PE%d", pin);
  }
}

void printPinAf(GPIO_TypeDef *port, uint8_t pin)
{
  uint8_t idx = 0;
  if (pin >= 8)
  {
    pin -= 8;
    idx = 1;
  }
  printf("AF%d", ( port->AFR[idx] >> (pin*4) ) & 0x0F );
} 

void printPinInp(GPIO_TypeDef *port, uint8_t pin)
{
  if (port->IDR & (1 << pin))
  {
    printf("HIGH, ");
  } else
  {
    printf("LOW,  ");
  }
}

void printPinOut(GPIO_TypeDef *port, uint8_t pin)
{
  if (port->ODR & (1 << pin))
  {
    printf("HIGH, ");
  } else
  {
    printf("LOW,  ");
  }
}

void printPinOutTyp(GPIO_TypeDef *port, uint8_t pin)
{
  if (port->OTYPER & (1 << pin))
  {
    printf("OD, ");
  } else
  {
    printf("PP, ");
  }
}

void printPinPull(GPIO_TypeDef *port, uint8_t pin)
{
  uint8_t pv = (port->PUPDR >> (pin * 2))&0x3;
  switch (pv)
  {
  case 0:
    printf("NO_PULL");
    break;
  case 1:
    printf("PULL_UP");
    break;
  case 2:
    printf("PULL_DN");
    break;  
  }
}

void printPinOutSpeed(GPIO_TypeDef *port, uint8_t pin)
{
  uint8_t pv = (port->OSPEEDR >> (pin * 2))&0x3;
  switch (pv)
  {
  case 0:
    printf("2M,   ");
    break;
  case 1:
    printf("25M,  ");
    break;
  case 2:
    printf("50M,  ");
    break;  
  case 3:
    printf("100M, ");
    break;
  }
}


void printPinMode(GPIO_TypeDef *port, uint8_t pin)
{
  uint8_t *modes[4] = {"Input", "Output", "AltFunc", "Analog"};
  uint8_t m = (port->MODER >> (pin*2))&0x3;
  printf("%s", modes[m]);
  printf("\t\t");
  switch (m)
  {
  case 0:
    printPinInp(port, pin);
    printPinPull(port, pin);
    break;
  case 1:
    printPinOut(port, pin);
    printPinOutTyp(port, pin);
    printPinOutSpeed(port, pin);
    printPinPull(port, pin);
    break;
  case 2:
    printPinAf(port, pin);
    break;
  case 3:
    break;
  }
}

void printPin(GPIO_TypeDef *port, uint8_t pin)
{
  printPinName(port, pin);
  printf("\t");  
  printPinMode(port, pin);
  printf("\r\n");
}

void printPort(GPIO_TypeDef *port)
{
  uint8_t i = 0;
  for (i = 0; i < 16; i++)
  {
    printPin(port, i);
  }
}

void printPinMap(void)
{
  printSeparator('=', 30);
  printf("SMT32F407VG Configuration\r\n");
  printSeparator('-', 30);
  printPort(GPIOA);
  printSeparator('-', 30);
  printPort(GPIOB);
  printSeparator('-', 30);
  printPort(GPIOC);
  printSeparator('-', 30);
  printPort(GPIOD);
  printSeparator('-', 30);
  printPort(GPIOE);
  printSeparator('=', 30);
}

utils.h:

#ifndef UTILS_H
#define UTILS_H

#include "stm32f4xx.h"

void printPinMap(void);

#endif

This one will work with STM32F4(07xx) only, but I guess it's easy to adapt for other MCUs.

No comments: