You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
KED/ked/csl/stm32f042/Src/pin.c

211 lines
4.9 KiB

/**
**************************************************************************************************
* @file pin.c
* @author Kerem Yollu & Edwin Koch
* @date 03.11.2021
* @version 1.01
**************************************************************************************************
* @brief Implementation of pin.h for the STM32F042K6 MCU
*
* **Detailed Description :**
*
* This source code uses bit manipulation in order to minimise the footprint of pin initialisation
* and manipulation. It's based on the CMSIS/Device/ST/STM32F0xx/Include/stm32f042x6.h Header file
* to get the obtain the right Registers.
*
*
* @todo
* - 01.11.2021 : Should we add a seprate header in the cls layer containing the pinNo_t ?
* - 01.11.2021 : Depending on request implment a pinLock() function
**************************************************************************************************
*/
#include "pin.h"
#define MODER_IN 0x0UL
#define MODER_OUT 0x1UL
#define MODER_ALTERNATE 0x2UL
#define MODER_ANALOG 0x3UL
#define OSPEEDR_LOW 0x0UL
#define OSPEEDR_MEDIUM 0x1UL
#define OSPEEDR_HIGH 0x3UL
#define PUPDR_NO_PULL 0x0UL
#define PUPDR_PULL_UP 0x1UL
#define PUPDR_PULL_DOWN 0x2UL
#define OTYPER_PUSH_PULL 0x0UL
#define OTYPER_OPEN_DRAIN 0x1UL
#define PIN_NO (pinNo & 0x0F)
#define PIN_PORT ((pinNo & 0xF0)>>4)
#define PIN_BASE ((GPIO_TypeDef *)portBase_Addr_List[PIN_PORT])
/*! Table for binding the Pin mode_t enum index to the values that the MODER register needs */
const uint32_t moderMode[5] = {
MODER_ANALOG,
MODER_IN,
MODER_OUT,
MODER_ANALOG,
MODER_ALTERNATE
};
/**
* Table for binding the Pin pinNo_t's Port Offet to the PORT gesiter that needs to be activated
*/
const uint32_t pinPort[3] = {
RCC_AHBENR_GPIOAEN,
RCC_AHBENR_GPIOBEN,
RCC_AHBENR_GPIOFEN
};
/**
* Table for binding the Pin pullUpDown_t enum index to the values that the PUPDR register needs
*/
const uint32_t pinPullUpDown[4] = {
PUPDR_NO_PULL,
PUPDR_NO_PULL,
PUPDR_PULL_UP,
PUPDR_PULL_DOWN
};
/**
* Table for binding the Pin speed_t enum index to the values that the OSPEEDR register needs
*/
const uint32_t speedList[5] = {
OSPEEDR_MEDIUM,
OSPEEDR_LOW,
OSPEEDR_LOW,
OSPEEDR_MEDIUM,
OSPEEDR_HIGH
};
/**
* Table for binding the Pin stage_t enum index to the values that the OTYPER register needs
*/
const uint32_t outputStgeList[4] =
{
OTYPER_PUSH_PULL,
OTYPER_OPEN_DRAIN,
OTYPER_PUSH_PULL,
OTYPER_OPEN_DRAIN
};
void pinSetMode(pinNo_t pinNo, pinMode_t mode)
{
//Clear entry.
PIN_BASE->MODER &=~ (0x3 << (PIN_NO * 2));
//Set to corresponding mode.
PIN_BASE->MODER |= (moderMode[mode] << (PIN_NO * 2));
}
void pinSetOutputStage(pinNo_t pinNo, pinStage_t stage)
{
PIN_BASE->OTYPER &= ~(1 << PIN_NO);
PIN_BASE->OTYPER |= (outputStgeList[stage] << PIN_NO);
}
void pinSetPullUpDonw(pinNo_t pinNo, pinPullUpDown_t resistance)
{
PIN_BASE->PUPDR &= ~(0x3 << (PIN_NO * 2));
PIN_BASE->PUPDR |= (pinPullUpDown[resistance] << (PIN_NO * 2));
}
void pinSetSpeed(pinNo_t pinNo, pinSpeed_t speed)
{
PIN_BASE->OSPEEDR &= (0x3 << (PIN_NO * 2));
PIN_BASE->OSPEEDR |= (speedList[speed] << (PIN_NO * 2));
}
void pinSetAlternate(pinNo_t pinNo, uint16_t alternate)
{
if(!(altFunc_List[PIN_PORT][PIN_NO] & (1<<(7-alternate))))
{
pinThrowError(UnvalidAlternate);
}
if(alternate > 15)
{
pinThrowError(OutOfRangeAlternate);
}
if(PIN_NO < 8) {
PIN_BASE->AFR[0] &= ~(0x0F << (PIN_NO * 4));
PIN_BASE->AFR[0] |= ((alternate & 0x0F) << (PIN_NO * 4));
return;
}
PIN_BASE->AFR[1] &= ~(0x0F << ((PIN_NO-8) * 4));
PIN_BASE->AFR[1] |= ((alternate & 0x0F) << ((PIN_NO-8) * 4));
}
void pinConfig(pinNo_t pinNo, pinMode_t mode, pinStage_t stage, pinPullUpDown_t resistance, pinSpeed_t speed)
{
pinInit(pinNo); //Very important to init first so that the corresponding bus gets his clock
pinSetMode(pinNo, mode);
pinSetOutputStage(pinNo, stage);
pinSetPullUpDonw(pinNo, resistance);
pinSetSpeed(pinNo,speed);
}
uint8_t pinRead(pinNo_t pinNo)
{
return ((PIN_BASE->IDR & (1<<PIN_NO)) >> PIN_NO);
}
void pinToggle(pinNo_t pinNo)
{
if(pinRead(pinNo))
{
PIN_BASE->BSRR |= (GPIO_BSRR_BR_0 << (PIN_NO));
return;
}
PIN_BASE->BSRR |= (GPIO_BSRR_BS_0 << (PIN_NO));
}
void pinWrite(pinNo_t pinNo, uint8_t state)
{
if(state) {
PIN_BASE->BSRR |= (GPIO_BSRR_BS_0 << (PIN_NO));
return;
}
PIN_BASE->BSRR |= (GPIO_BSRR_BR_0 << (PIN_NO));
}
//Enable the pin port's clock
//in this family of MCU ell the cloks are on the same bus that is why we dion't need to
//modfify the AHBENR.
//DS Page : 121
void pinInit(pinNo_t pinNo)
{
RCC->AHBENR |= pinPort[PIN_PORT];
}
//in this family of MCU ell the cloks are on the same bus that is why we dion't need to
//modfify the AHBENR.
//DS Page : 121
void pinDeInit(pinNo_t pinNo)
{
RCC->AHBENR &=~(pinPort[PIN_PORT]);
}
void pinReset(pinNo_t pinNo)
{
}
void pinHardwareInfo(pinNo_t pinNo)
{
//TODO : define where to print anh woh to print
}
void pinThrowError(pinErrors_t error)
{
while(1);
}