Presentation is loading. Please wait.

Presentation is loading. Please wait.

Baremetal C Programming for Embedded Systems

Similar presentations


Presentation on theme: "Baremetal C Programming for Embedded Systems"— Presentation transcript:

1 Baremetal C Programming for Embedded Systems
Class 3: Driver Design Techniques February 25, 2015 Jacob Beningo, CSDP

2 Course Overview C Concepts for Embedded Systems
Baremetal Scheduling Techniques Driver Design Techniques Design Patterns for Firmware Writing Portable Code

3 Session Overview Reviewing the bits Direct Register Access
Drivers using structs Portable Driver Concepts A DIO (GPIO) Driver

4 Reviewing the Bits Bit Manipulation Operator Example Clear bit 4
Reg &=~0x10; 0b (Original) 0b (Negated) 0b (& Result) Set bit 4 Reg |= 0x10; 0b (Original) 0b (OR’d) 0b (| Result) Toggle bit 4 Reg ^= 0x10; 0b (Original) 0b (^ Result) Shift left 2 then right 2 Reg <<= 2; 0b (Original) 0b (<< Result) Reg >>= 2; 0b (New Original) 0b (>> Result)

5 Direct Register Access
// GPIO Port A is located at 0x1000 uint32_t * Gpio_PortA = (uint32_t *) 0x1000U; // Set the 0 bit high on PortA *Gpio_PortA |= 0x01; // Valid Gpio_PortA++; // Invalid! uint32_t * volatile const Gpio_PortA = (uint32_t *) 0x1000U;

6 Struct Based Drivers /** GPIO - Peripheral register structure */
typedef struct GPIO_MemMap { uint32_t PDOR; /**< Port Data Output Register, offset: 0x0 */ uint32_t PSOR; /**< Port Set Output Register, offset: 0x4 */ uint32_t PCOR; /**< Port Clear Output Register, offset: 0x8 */ uint32_t PTOR; /**< Port Toggle Output Register, offset: 0xC */ uint32_t PDIR; /**< Port Data Input Register, offset: 0x10 */ uint32_t PDDR; /**< Port Data Direction Register, offset: 0x14 */ } volatile *GPIO_MemMapPtr; Example #define PORTA_BASE_PTR ( (GPIO_MemMapPtr)0xF80FF000u) PORTA_BASE_PTR->PDIR |= (1UL << 23); PORTA_BASE_PTR++;

7 Portable Driver Concepts
Many different ways to organize code Break the code up into different layers Driver Layer Contains MCU peripheral drivers Generic initialization functions Mcu start-up code and copy down Possibly BSP for external chips

8 Portable Driver Concepts
Application Layer Product features Scheduler Applications for drivers Ex Button response behavior Configuration Layer Configuration for drivers Configuration for applications Application settings

9 GPIO Driver Example // GPIO_CONFIG.h /**
* Defines the digital input/output configuration table elements that are used * by Dio_Init to configure the Dio peripheral. */ typedef struct { uint8_t Channel; /**< The I/O channel */ uint8_t Implement; /**< Pin Implemented - TRUE or FALSE */ uint8_t Resistor; /**< Pullup/Pulldown Resistor - DISABLED, PULLUP, or PULLDOWN */ uint8_t SlewRate; /**< Pin Slew Rate - SLOW or FAST */ uint8_t DriveStrength; /**< Pin Drive Strength - HIGH or LOW */ uint8_t PassiveFilter; /**< Passive Input Filter - ENABLED or DISABLED */ uint8_t Direction; /**< Data Direction OUTPUT or INPUT */ uint8_t Data; /**< Data HIGH or LOW */ uint8_t Function; /**< Mux Function Dio_FunctionSelect */ }Gpio_ConfigType;

10 GPIO Driver Example const Gpio_ConfigType Dio_Config[] = { //
// Channel, Direction, Data, Function { SWD_CLK, OUTPUT, HIGH, GPIO, }, { PORTA_1, OUTPUT, HIGH, GPIO, }, { PORTA_2, OUTPUT, HIGH, GPIO, }, { PORTA_3, OUTPUT, HIGH, GPIO, }, { PORTA_4, OUTPUT, HIGH, GPIO, }, { PORTA_5, OUTPUT, HIGH, GPIO, }, { PORTA_6, OUTPUT, HIGH, GPIO, }, { PORTA_7, OUTPUT, HIGH, GPIO, } }; typedef enum { SWD_CLK, PORTA_1, PORTA_2, PORTA_3, PORTA_4, PORTA_5, PORTA_6, PORTA_7 }GpioChannelType;

11 GPIO Driver Example #ifdef __cplusplus extern "C"{ #endif
void Gpio_Init(const Gpio_ConfigType *Config); uint8_t Gpio_ReadChannel(Gpio_ChannelType Channel); void Gpio_WriteChannel(Gpio_ChannelType Channel, uint8_t State); void Gpio_ToggleChannel(Gpio_ChannelType Channel); void Gpio_SetChannelMode(Gpio_ChannelType Channel, uint8_t Mode); void Gpio_SetFuncMode(Gpio_ChannelType Channel, Gpio_FunctionSelect Func); } // extern "C"

12 Pointer Arrays What are Pointer Arrays?
A pointer array is an array where each element of the array is a pointer to a peripheral register of a particular type. How do they help? Groups registers into logical channels Simplifies initialization functions Easily ported Cross platform through templates Abstracts the register into something readable and understandable by a human. Creates design patterns that can be reused

13 GPIO Driver Example /**
* Defines a table of pointers to the Port Data Output Register on the * microcontroller */ uint32_t volatile * const ports[NUM_PORTS] = { (uint32_t*)&GPIOA_PDOR, (uint32_t*)&GPIOB_PDOR, (uint32_t*)&GPIOC_PDOR, (uint32_t*)&GPIOD_PDOR, (uint32_t*)&GPIOE_PDOR };

14 Pointer Arrays Key Features of the declaration
portsddr is a const pointer The register that is being pointed to in each index of the pointer array will always be the same so it is declared as a const portsddr points to a volatile uint16 The volatile keyword here is used to identify that the uint16 that is being pointed to (hardware register) may change without the software modifying it. Depending on how the registers are declared by the compiler, the register addresses may need to be cast to a pointer in order to silence the compilers objections.

15 GPIO Driver Example void Dio_Init(const Dio_ConfigType * Config) {
uint8_t i = 0; // Loop counter variable uint8_t PortIndex = 0; // Port Number uint8_t PinIndex = 0; // Pin Number // Loop through all pins, set the data register bit and the data direction // register bit according to the dio configuration table values for (i = 0; i < NUMBER_PORT_PINS; i++) PortIndex = Config[i].Channel / NUMBER_PORT_PINS; PinIndex = Config[i].Channel % NUMBER_PORT_PINS; // Set the Data register bit for this channel if (Config[i].Data == HIGH) *ports[number] |= (1UL<<(PinIndex)); } else *ports[number] &= ~(1UL<<(PinIndex));

16 GPIO Driver Example uint8_t Dio_ReadChannel(Dio_ChannelType Channel) { return ((*portsin[Channel/NUM_PINS_PER_PORT] & (1UL<<(Channel%NUM_PINS_PER_PORT))) ? HIGH : LOW); } void Dio_WriteChannel(Dio_ChannelType Channel, uint8_t State) if (State == HIGH) *ports[Channel/NUM_PINS_PER_PORT] |= (1UL<<(Channel%NUM_PINS_PER_PORT)); else *ports[Channel/NUM_PINS_PER_PORT] &=

17 Additional Resources Download Course Material for
Updated C Doxygen Templates (Feb 2015) Example drivers source code Microcontroller API Standard EDN Embedded Basics Articles Embedded Bytes Newsletter From under - Blog and Articles > Software Techniques > CEC Baremetal C Programming

18 Jacob Beningo Newsletters P.O. Box 400 Embedded Bytes
Linden, Michigan 48451 Newsletters Embedded Bytes Training MicroPython Bootloaders Low Power Design Real-time Software C/C++ Embedded : : : Jacob_Beningo : Beningo Engineering : JacobBeningo : Embedded Basics Jacob Beningo Principal Consultant 18


Download ppt "Baremetal C Programming for Embedded Systems"

Similar presentations


Ads by Google