/** ************************************************************************************************** * @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); } 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); }