In the code below where is the variable, and where is the variable type? We have here properties of registers being changed.
If its an object oriented then we need an object name where we change its properties.
In here I don't see where is the type where is the variable name and how exactly we change its inner properties?
#include <stm32f0xx.h>
int main(void)
{
RCC->AHBENR|=RCC_AHBENR_GPIOCEN ;
GPIOC->MODER|=GPIO_MODER_MODERG_O ;
}
This has nothing to do with OOP, it is just a structure member assignment. RCC and GPIOC are defined in stm32f0xx.h:
#define RCC ((RCC_TypeDef *) RCC_BASE)
and
#define GPIOC ((GPIO_TypeDef *) GPIOC_BASE)
Where RCC_BASE and GPIOC_BASE are are defined in the same header as abaolute addresses, and RCC_TypeDef and GPIO_TypeDef are structure types - for example:
typedef struct
{
__IO uint32_t MODER; /*!< GPIO port mode register, Address offset: 0x00 */
__IO uint16_t OTYPER; /*!< GPIO port output type register, Address offset: 0x04 */
uint16_t RESERVED0; /*!< Reserved, 0x06 */
__IO uint32_t OSPEEDR; /*!< GPIO port output speed register, Address offset: 0x08 */
__IO uint32_t PUPDR; /*!< GPIO port pull-up/pull-down register, Address offset: 0x0C */
__IO uint16_t IDR; /*!< GPIO port input data register, Address offset: 0x10 */
uint16_t RESERVED1; /*!< Reserved, 0x12 */
__IO uint16_t ODR; /*!< GPIO port output data register, Address offset: 0x14 */
uint16_t RESERVED2; /*!< Reserved, 0x16 */
__IO uint32_t BSRR; /*!< GPIO port bit set/reset registerBSRR, Address offset: 0x18 */
__IO uint32_t LCKR; /*!< GPIO port configuration lock register, Address offset: 0x1C */
__IO uint32_t AFR[2]; /*!< GPIO alternate function low register, Address offset: 0x20-0x24 */
__IO uint16_t BRR; /*!< GPIO bit reset register, Address offset: 0x28 */
uint16_t RESERVED3; /*!< Reserved, 0x2A */
}GPIO_TypeDef;
So expanding the macros in:
RCC->AHBENR|=RCC_AHBENR_GPIOCEN ;
resolves to:
((RCC_TypeDef*)0x40021000)->AHBENR |= ((uint32_t)0x00080000) ;
Where 0x40021000 is the base address of the RCC, an AHBENR refers to an RCC register to which the GPIOC enable flag is being set.
stm32f0xx.h defines structures for the register set of each peripheral, then defined macros that map the structure to the address at which each peripheral resides.
Related
I have following c++ code for an embedded system:
//LIBRARY code:
typedef struct { /*!< (# 0x48028100) PORT1 Structure */
__IO uint32_t OUT; /*!< (# 0x48028100) Port 1 Output Register */
__O uint32_t OMR; /*!< (# 0x48028104) Port 1 Output Modification Register */
__I uint32_t RESERVED[2];
__IO uint32_t IOCR0; /*!< (# 0x48028110) Port 1 Input/Output Control Register 0 */
__IO uint32_t IOCR4; /*!< (# 0x48028114) Port 1 Input/Output Control Register 4 */
__IO uint32_t IOCR8; /*!< (# 0x48028118) Port 1 Input/Output Control Register 8 */
__IO uint32_t IOCR12; /*!< (# 0x4802811C) Port 1 Input/Output Control Register 12 */
__I uint32_t RESERVED1;
__I uint32_t IN; /*!< (# 0x48028124) Port 1 Input Register */
__I uint32_t RESERVED2[6];
__IO uint32_t PDR0; /*!< (# 0x48028140) Port 1 Pad Driver Mode 0 Register */
__IO uint32_t PDR1; /*!< (# 0x48028144) Port 1 Pad Driver Mode 1 Register */
__I uint32_t RESERVED3[6];
__I uint32_t PDISC; /*!< (# 0x48028160) Port 1 Pin Function Decision Control Register */
__I uint32_t RESERVED4[3];
__IO uint32_t PPS; /*!< (# 0x48028170) Port 1 Pin Power Save Register */
__IO uint32_t HWSEL; /*!< (# 0x48028174) Port 1 Pin Hardware Select Register */
} PORT1_Type;
#define PORT1_BASE 0x48028100UL
#define PORT1 ((PORT1_Type *) PORT1_BASE)
// MY MINIMAL EXAMPLE CODE:
...
uint32_t u32SourceAddress = (uint32_t)(&(PORT1->IN)), // error: expected unqualified-id
// ^
...
This code works just fine when I compile it with GCC or ARMCC. When I use clang-tidy, I get an error: expected unqualified-id [clang-diagnostic-error] on it. What am I doing wrong and how can I fix it?
Thanks, Moritz
edit:
Added comments regarding library based code and my code.
I'm trying to read interrupt changes from a MCP23017 board using pigpio but i'm not getting any notification... what seems that i do not know is the initialize procedures that i need to do (looking into the documentation http://ww1.microchip.com/downloads/en/devicedoc/20001952c.pdf it seems that i'm not using the correct values...).
I'm using B side for inputs and A for outputs:
i2cWriteByteData(i2cHandle, IODIRB, 0xFF); // inputs
i2cWriteByteData(i2cHandle, IODIRA, 0x00); // outputs
then i try to set the interrupt state (that it seems to be wrong), but i'm copied from 'I2C Sonar' example from http://abyz.me.uk/rpi/pigpio/examples.html
i2cWriteByteData(i2cHandle, GPINTENB, 0x00); // Disable.
i2cWriteByteData(i2cHandle, DEFVALB, 0x00) ; // N/A.
i2cWriteByteData(i2cHandle, INTCONB, 0x00) ; // On change.
and then registe the handler to read the changes:
gpioSetMode(ALERTPIN, PI_INPUT); /* start capacitor recharge */
gpioSetISRFuncEx(ALERTPIN, EITHER_EDGE, 0, alert, nullptr); /* call alert when state changes */
So my question is what I'm missing that my alert function is never called when states change (strangely it is called when i do a dump on the console (sudo i2cdump -y 1 0x20)
Other question is are my defines correct? why are two sets of values (Address IOCON.BANK = 1 and 0)? what are the addresses for MCP23017? (i'm using Address IOCON.BANK = 0):
#define IODIRA 0x00
#define IODIRB 0x01
#define IPOLA 0x02
#define IPOLB 0x03
#define GPINTENA 0x04
#define GPINTENB 0x05
#define DEFVALA 0x06
#define DEFVALB 0x07
#define INTCONA 0x08
#define INTCONB 0x09
#define IOCONA 0x0A
#define IOCONB 0x0B
#define GPPUA 0x0C
#define GPPUB 0x0D
#define INTFA 0x0E
#define INTFB 0x0F
#define INTCAPA 0x10
#define INTCAPB 0x11
#define GPIOA 0x12
#define GPIOB 0x13
#define OLATA 0x14
#define OLATB 0x15
#define ALERTPIN 26
Update:
Next i show all the code that I perform and after read the documentation I think that i'm doing everything correct, but it seems that i'm missing some initialization... and strangely the GPIOA read when input button connected to GPA0 is pressed the value is 255 (0xff) and if is not press then is 0... strange it should be 1 when pressed right?
void estimulateMCP23017(unsigned i2cAddr=0x20,unsigned i2cBus=1){
//open i2c MCP23017
int i2cHandle = i2cOpen(i2cBus, i2cAddr, 0);
//open is with success if is >=0
if(i2cHandle>=0){
//IODIR: I/O DIRECTION REGISTER (ADDR 0x00)
//1 = Pin is configured as an input.
//0 = Pin is configured as an output
//we can set each separately if we want
//set side A as output (0)
i2cWriteByteData(i2cHandle, IODIRA, 0xFF); // A is inputs
//set side B as input (1)
i2cWriteByteData(i2cHandle, IODIRB, 0x00); // B is outputs
//turn all outputs to on (pins 0 to 7 is the bit high in 0x00-0xFF)
i2cWriteByteData(i2cHandle, OLATA, 0x00);
i2cWriteByteData(i2cHandle, OLATB, 0xFF);
//now listen for changes on side (B)
// General purpose I/O interrupt-on-change bits <7:0>
//1 = Enables GPIO input pin for interrupt-on-change event.
//0 = Disables GPIO input pin for interrupt-on-change event.
i2cWriteByteData(i2cHandle, GPINTENA, 0xFF); // Enable all
i2cWriteByteData(i2cHandle, GPINTENB, 0x00); // disable
//Sets the compare value for pins configured for interrupt-on-change from defaults <7:0>
//If the associated pin level is the opposite from the register bit, an interrupt occurs
i2cWriteByteData(i2cHandle, DEFVALA, 0x00); // does not matter
i2cWriteByteData(i2cHandle, DEFVALB, 0x00); // does not matter
// Controls how the associated pin value is compared for interrupt-on-change <7:0>
//1 = Pin value is compared against the associated bit in the DEFVAL register.
//0 = Pin value is compared against the previous pin value.
i2cWriteByteData(i2cHandle, INTCONA, 0x00) ; // On change.
i2cWriteByteData(i2cHandle, INTCONB, 0x00) ; // does not matter.
cout << "waiting for changes...(input value: "<<i2cReadByteData(i2cHandle, GPIOA)<<")\n";
gpioSetMode(ALERTPIN, PI_INPUT); /* set alert pin as input */
gpioSetISRFuncEx(ALERTPIN, EITHER_EDGE, 0, alert, nullptr); /* call alert when state changes */
cin.get();
i2cClose(i2cHandle);
}
}
Since Bank A is your input, you should use:
i2cWriteByteData(i2cHandle, GPINTENA, 0xFF); // Enable.
i2cWriteByteData(i2cHandle, INTCONA, 0x00) ; // On change.
Your defines look right. The MCP23017 has two different modes of addressing the registers. The mode is set using the IOCON.BANK flag. Just never touch that bit, there's no reason to do so.
I am programming a microcontroller using Kinetis Design Studio(KDS) and i want to implement an interrupt such that at anytime during runtime if a specific I/O pin has a "high" level the microcontroller should stop working until the pin is back to "low" .
Any ideas?
Try this code from free scale forum
https://www.element14.com/community/community/designcenter/kinetis_kl2_freedom_board/blog/2015/08/21/kinetis-design-studio-30-kinetis-sdk-12-processor-expert-using-frdm-kl43z-quick-tutorial-on-gpio-interrupt-toggling-led-using-button-with-interrupt-logic
or
below is an usart interrupt code you can modify it
/* p6_4.c UART0 Receive using interrupt */
/* This program modifies p4_2.c to use interrupt to handle the UART0 receive.
Receiving any key from terminal emulator (TeraTerm) of the host PC to the UART0 on Freescale FRDM-KL25Z board.
UART0 is connected to openSDA debug agent and has a virtual connection to the host PC COM port.
Launch TeraTerm on a PC and hit any key.
The LED program from P2_7 of Chapter 2 is used to turn on the tri-color LEDs according to the key received.
By default in SystemInit(), FLL clock output is 41.94 MHz.
Setting BDH=0, BDL=0x17, and OSR=0x0F yields 115200 Baud. */
#include <MKL25Z4.H>
void UART0_init(void);
void delayMs(int n);
void LED_init(void);
void LED_set(char value);
int i=0;
int main (void) {
__disable_irq(); /* global disable IRQs */
UART0_init();
LED_init();
__enable_irq(); /* global enable IRQs */
while (1) {
/* UART0 receive is moved to interrupt handler*/
}
}
/* UART0 interrupt handler */
void UART0_IRQHandler(void)
{
char c;
c = UART0->D; /* read the char received */
LED_set(c); /* and use it to set LEDs */
}
/* initialize UART0 to receive at 115200 Baud */
void UART0_init(void)
{
SIM->SCGC4 |= 0x0400; /* enable clock for UART0 */
SIM->SOPT2 |= 0x04000000; /* use FLL output for UART Baud rate generator */
UART0->C2 = 0; /* turn off UART0 while changing configurations */
UART0->BDH = 0x00;
UART0->BDL = 0x17; /* 115200 Baud */
UART0->C4 = 0x0F; /* Over Sampling Ratio 16 */
UART0->C1 = 0x00; /* 8-bit data */
UART0->C2 = 0x24; /* enable receive and receive interrupt*/
NVIC->ISER[0] |= 0x00001000; /* enable INT12 (bit 12 of ISER[0]) */
SIM->SCGC5 |= 0x0200; /* enable clock for PORTA */
PORTA->PCR[1] = 0x0200; /* make PTA1 UART0_Rx pin */
}
/* initialize all three LEDs on the FRDM board */
void LED_init(void)
{
SIM->SCGC5 |= 0x400; /* enable clock to Port B */
SIM->SCGC5 |= 0x1000; /* enable clock to Port D */
PORTB->PCR[18] = 0x100; /* make PTB18 pin as GPIO */
PTB->PDDR |= 0x40000; /* make PTB18 as output pin */
PTB->PSOR |= 0x40000; /* turn off red LED */
PORTB->PCR[19] = 0x100; /* make PTB19 pin as GPIO */
PTB->PDDR |= 0x80000; /* make PTB19 as output pin */
PTB->PSOR |= 0x80000; /* turn off green LED */
PORTD->PCR[1] = 0x100; /* make PTD1 pin as GPIO */
PTD->PDDR |= 0x02; /* make PTD1 as output pin */
PTD->PSOR |= 0x02; /* turn off blue LED */
}
/* turn on or off the LEDs according to bit 2-0 of the value */
void LED_set(char value)
{
if (value=='c')
{ /* use bit 1 of value to control green LED */
PTB->PCOR = 0x80000; /* turn on green LED */
s }
if (~(value=='c') )
{ /* use bit 1 of value to control green LED */
PTB->PSOR = 0x80000; /* turn off green LED */
}
}
With the following Code I'm trying to get the struct in hwPort to start at the memory address 0x48001000. How would I do this as I'm currently stuck
struct PortGPIOs
{
volatile uint32_t MODER; /*!< GPIO port mode register, Address offset: 0x00 */
volatile uint32_t OTYPER; /*!< GPIO port output type register, Address offset: 0x04 */
volatile uint32_t OSPEEDR; /*!< GPIO port output speed register, Address offset: 0x08 */
volatile uint32_t PUPDR; /*!< GPIO port pull-up/pull-down register, Address offset: 0x0C */
volatile uint32_t IDR; /*!< GPIO port input data register, Address offset: 0x10 */
volatile uint32_t ODR; /*!< GPIO port output data register, Address offset: 0x14 */
volatile uint16_t BSRRL; /*!< GPIO port bit set/reset low register, Address offset: 0x18 */
volatile uint16_t BSRRH; /*!< GPIO port bit set/reset high register, Address offset: 0x1A */
volatile uint32_t LCKR; /*!< GPIO port configuration lock register, Address offset: 0x1C */
volatile uint32_t AFR[2]; /*!< GPIO alternate function registers, Address offset: 0x20-0x24 */
volatile uint32_t BRR; /*!< GPIO bit reset register, Address offset: 0x28 */
};
class hwPort {
public:
hwPort(PortGPIOs *, uint32_t, uint32_t, uint32_t);
uint32_t read();
void readOr(uint32_t);
void readAnd(uint32_t);
void write(uint32_t);
void writeOr(uint32_t);
void writeAnd(uint32_t);
private:
PortGPIOs *GPIO;
};
Just initialise the GPIO member variable in your constructor, as follows:
GPIO = (PortGPIOs *) 0x48001000;
[Note: use a C++-style cast if you prefer - the end result is the same.]
When I use this struct just after flashing device it works well, but after restarting (power on/off) using this struct(assign to any bit) cause a HardFault irq. I use Keil uVision with STM32F205. Why it not works? and what should I change/remove/add to fix it? Direct using GPIOC->ODR don't cause any problems what is wrong with bitfields in Kail?
#pragma anon_unions
typedef union {
struct {
__IO uint16_t Data_Bus:8; // 0-7 data bus
__IO uint16_t Ctr_Pins:6; // 8-13 control pins
__IO uint16_t :2; // 14-15 unused here
};
struct {
__IO uint16_t D0:1; // 0 data bus pin
__IO uint16_t D1:1; // 1 data bus pin
__IO uint16_t D2:1; // 2 data bus pin
__IO uint16_t D3:1; // 3 data bus pin
__IO uint16_t D4:1; // 4 data bus pin
__IO uint16_t D5:1; // 5 data bus pin
__IO uint16_t D6:1; // 6 data bus pin
__IO uint16_t D7:1; // 7 data bus pin
// --------------------------------
__IO uint16_t RS:1; // 8 reset
__IO uint16_t CS:1; // 9 chip select
__IO uint16_t CD:1; // 10 control / data
__IO uint16_t RD:1; // 11 read tick
__IO uint16_t WR:1; // 12 write tick
__IO uint16_t EN:1; // 13 enable display
// ---------------------------------
__IO uint16_t :1; // 14 unused
__IO uint16_t LD:1; // 15 led
};
} *PC_STRUCT_PTR, PC_STRUCT;
PC_STRUCT_PTR __TMP = (PC_STRUCT_PTR)(GPIOC_BASE+0x14);
#define PINOUTS (*__TMP)
it's used like this:
void Write_Reg(unsigned char command)
{
PINOUTS.CD = 0; PINOUTS.RD = 1; PINOUTS.CS = 0; PINOUTS.WR = 0;
PINOUTS.Data_Bus = command; wait();
PINOUTS.WR = 1; PINOUTS.CS = 1; PINOUTS.CD = 1; wait();
}
In file 'startup_stm32f20x.s', make sure that you have the following piece of code:
EXTERN HardFault_Handler_C ; this declaration is probably missing
__tx_vectors ; this declaration is probably there
DCD HardFault_Handler
Then, in the same file, add the following interrupt handler (where all other handlers are located):
PUBWEAK HardFault_Handler
SECTION .text:CODE:REORDER(1)
HardFault_Handler
TST LR, #4
ITE EQ
MRSEQ R0, MSP
MRSNE R0, PSP
B HardFault_Handler_C
Then, in file 'stm32f2xx.c', add the following ISR:
void HardFault_Handler_C(unsigned int* hardfault_args)
{
printf("R0 = 0x%.8X\r\n",hardfault_args[0]);
printf("R1 = 0x%.8X\r\n",hardfault_args[1]);
printf("R2 = 0x%.8X\r\n",hardfault_args[2]);
printf("R3 = 0x%.8X\r\n",hardfault_args[3]);
printf("R12 = 0x%.8X\r\n",hardfault_args[4]);
printf("LR = 0x%.8X\r\n",hardfault_args[5]);
printf("PC = 0x%.8X\r\n",hardfault_args[6]);
printf("PSR = 0x%.8X\r\n",hardfault_args[7]);
printf("BFAR = 0x%.8X\r\n",*(unsigned int*)0xE000ED38);
printf("CFSR = 0x%.8X\r\n",*(unsigned int*)0xE000ED28);
printf("HFSR = 0x%.8X\r\n",*(unsigned int*)0xE000ED2C);
printf("DFSR = 0x%.8X\r\n",*(unsigned int*)0xE000ED30);
printf("AFSR = 0x%.8X\r\n",*(unsigned int*)0xE000ED3C);
printf("SHCSR = 0x%.8X\r\n",SCB->SHCSR);
while (1);
}
If you can't use printf at the point in the execution when this specific Hard-Fault interrupt occurs, then save all the above data in a global buffer instead, so you can view it after reaching the while (1).
Then, refer to the 'Cortex-M Fault Exceptions and Registers' section at http://www.keil.com/appnotes/files/apnt209.pdf in order to understand the problem, or publish the output here if you want further assistance.