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.
Related
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.
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.
I'm trying to understand initializing an ADC on the ARM Cortex M4 MK20DX256VLH7 on the Teensy 3.1. I'm curious about the terminology and relevant search terms as to what the symbols below mean. &= ~(3<<18), which I interpret as a bitwise AND on a bitwise NOT(3 bitwise left shift 18), means very little to me. I interpret what is inside the parenthetical as BIN 11 shifts to BIN 11000000000000000000. I understand that there is a pointer dereference happening to PINMODE1 (which is a little fuzzy to me) and that it is initializing pin 25 on the chip as an ADC input? I am not at all confident in my ability to parse this. Please advise. Thank you for your time.
void ADC_Init (void) {
LPC_PINCON->PINMODE1 &= ~(3<<18); /* P0.25 */
LPC_PINCON->PINMODE1 |= (1<<18); /* has neither pull-up nor pull-down */
LPC_PINCON->PINSEL1 &= ~(3<<18); /* P0.25 is GPIO */
LPC_PINCON->PINSEL1 |= (1<<18); /* P0.25 is AD0.2 */
LPC_SC->PCONP |= (1<<12); /* Enable power to ADC block */
LPC_ADC->ADCR = (1<< 2) | /* select AD0.2 pin */
(4<< 8) | /* ADC clock is 25MHz/5 */
(1<<16) | /* Burst mode */
(1<<21); /* enable ADC */
// LPC_ADC->ADINTEN = (1<< 8); /* global enable interrupt */
// NVIC_EnableIRQ(ADC_IRQn); /* enable ADC Interrupt */
}