I have C type struct like this code below
typedef struct GPIO_PIN_CONFIG
{
uint8_t GPIO_PinNumber;
uint8_t GPIO_PinMode;
uint8_t GPIO_PinSpeed;
uint8_t GPIO_PinPuPdControl;
uint8_t GPIO_PinOpType;
uint8_t GPIO_PinAltFunMode;
}GPIO_PinConfig_t;
and I need to initialize it with certain C macros
/*
* GPIO modes
*/
#define GPIO_INPUT_MODE 0 /* 00: Input (reset state) */
#define GPIO_OUTPUT_MODE 1 /* 01: General purpose output mode */
#define GPIO_ALT_FUNC_MODE 2 /* 10: Alternate function mode */
#define GPIO_ANALOG_MODE 3 /* 11: Analog mode */
#define GPIO_INPUT_INT_FT 4 /* GPIO input interrupt mode falling edge triger*/
#define GPIO_INPUT_INT_RT 5 /* GPIO input interrupt mode Raising edge triger*/
/*
* GPIO output types
*/
#define GPIO_OP_TYPE_PP 1 /* 00: GPIO output push-pull type */
#define GPIO_OP_TYPE_OD 2 /* 01: GPIO output open-drain type */
/*
* GPIO output speeds
*/
#define GPIO_SPEED_LOW 0 /* 00: Low speed */
#define GPIO_SPEED_MEDIUM 1 /* 01: Medium speed */
#define GPIO_SPEED_FAST 2 /* 10: Fast speed */
#define GPIO_SPEED_HIGH 3 /* 11: High speed */
/*
* GPIO pull-up/pull-down configuration
*/
#define GPIO_PIN_NO_PUPD 0 /* 00: No pull-up, pull-down */
#define GPIO_PIN_PULLUP 1 /* 01: Activate Pull-up */
#define GPIO_PIN_PULLDOWN 2 /* 10: Activate Pull-down */
so I was wondering If there's a way to generate autosuggestion for a group of certain macros, for each member of the struct
I have tried comments but I would like autosuggest
I am trying to generate system_stm32f1xx.c which will set up my clock as shown on the picture.
The problem is that, when I generate the code with CubeMX, I don't get this configuration. Instead, I get the (I guess) default configuration with internal RC clock enabled.
I had many problem with configuring timers and USART before I find out that some thing is wrong with my clock configuration.
Content of the system_init() function.
void SystemInit (void)
{
/* Reset the RCC clock configuration to the default reset state(for debug purpose) */
/* Set HSION bit */
RCC->CR |= 0x00000001U;
/* Reset SW, HPRE, PPRE1, PPRE2, ADCPRE and MCO bits */
#if !defined(STM32F105xC) && !defined(STM32F107xC)
RCC->CFGR &= 0xF8FF0000U;
#else
RCC->CFGR &= 0xF0FF0000U;
#endif /* STM32F105xC */
/* Reset HSEON, CSSON and PLLON bits */
RCC->CR &= 0xFEF6FFFFU;
/* Reset HSEBYP bit */
RCC->CR &= 0xFFFBFFFFU;
/* Reset PLLSRC, PLLXTPRE, PLLMUL and USBPRE/OTGFSPRE bits */
RCC->CFGR &= 0xFF80FFFFU;
#if defined(STM32F105xC) || defined(STM32F107xC)
/* Reset PLL2ON and PLL3ON bits */
RCC->CR &= 0xEBFFFFFFU;
/* Disable all interrupts and clear pending bits */
RCC->CIR = 0x00FF0000U;
/* Reset CFGR2 register */
RCC->CFGR2 = 0x00000000U;
#elif defined(STM32F100xB) || defined(STM32F100xE)
/* Disable all interrupts and clear pending bits */
RCC->CIR = 0x009F0000U;
/* Reset CFGR2 register */
RCC->CFGR2 = 0x00000000U;
#else
/* Disable all interrupts and clear pending bits */
RCC->CIR = 0x009F0000U;
#endif /* STM32F105xC */
#if defined(STM32F100xE) || defined(STM32F101xE) || defined(STM32F101xG) || defined(STM32F103xE) || defined(STM32F103xG)
#ifdef DATA_IN_ExtSRAM
SystemInit_ExtMemCtl();
#endif /* DATA_IN_ExtSRAM */
#endif
#ifdef VECT_TAB_SRAM
SCB->VTOR = SRAM_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal SRAM. */
#else
SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal FLASH. */
#endif
}
The clock configuration function is in the generated by the CubeMx main.c file and is called SystemClock_Config. The SystemInit does not set the clock. I do not know why my previos answer was removed as it answers the question.
The clock configuration function is in tge main.c file. Do not touch the system files unless you know what you are doing.
SystemInit does something else and you should leave it as it is
I enabled MMU on my s3c2440 board (3G - 4G memory :: the fault attribute),everything was just fine when I didn't read/write 3G - 4G memory .So to test the page fault vector ,I wrote to a 0xFF to the 3G address,as I expected ,I got the right value from FSR ,So I did this in _do_page_fault (), the step was like this :
..... // set new page to translation table
.....
invlidate_icache (); // clear icache
clr_dcache (); // wb is used ,clear dcache
invalidate_ttb (); // invalidate translation table
and then ISR_dataabort returned ,I read the 3G address to get the 0xFF which I wote before .
Unfortunately I got a data abort again .(I am sure the translation table value I set is ok)
So what is the correct way to update the MMU translation table .Any help is appreciate ! thanks
here is the Main code I used (just for some test),
(I am a littlte strange to ARM ARCH,so this code might be urgly )
/* MMU TTB 0 BASE ATTR */
#define TTB0_FAULT (0|(1<<4)) /* TTB FAULT */
#define TTB0_COARSE (1|(1<<4)) /* COARSE PAGE BASE ADDR */
#define TTB0_SEG (2|(1<<4)) /* SEG BASE ADDR */
#define TTB0_FINE (3|(1<<4)) /* FINE PAGE BASE ADDR */
/* MMU TTB 1 BASE ATTR */
#define TTB1_FAULT (0)
#define TTB1_LPG (1) /* Large page */
#define TTB1_SPG (2) /* small page */
#define TTB1_TPG (3) /* tiny page */
/* domain access priority level */
#define FAULT_PL (0x0) /* domain fault */
#define USR_PL (0x1) /* usr mode */
#define RSV_PL (0x2) /* reserved */
#define SYS_PL (0x3) /* sys mode */
#define DOMAIN_FAULT (0x0<<5) /* fault 0*/
#define DOMAIN_SYS (0x1<<5) /* sys 1*/
#define DOMAIN_USR (0x2<<5) /* usr 2*/
/* C,B bit */
#define CB (3<<2) /* cache_on, write_back */
#define CNB (2<<2) /* cache_on, write_through */
#define NCB (1<<2) /* cache_off,WR_BUF on */
#define NCNB (0<<2) /* cache_off,WR_BUF off */
/* ap 2 bits */
#define AP_FAULT (0<<10) /* access deny */
#define AP_SU_ONLY (1<<10) /* rw su only */
#define AP_USR_RO (2<<10) /* sup=RW, user=RO */
#define AP_RW (3<<10) /* su=RW, user=RW */
/* page dir 1 ap0 */
#define AP0_SU_ONLY (1<<4) /* rw su only */
#define AP0_USR_RO (2<<4) /* sup=RW, user=RO */
#define AP0_RW (3<<4) /* su=RW, user=RW */
/* page dir 1 ap1 */
#define AP1_SU_ONLY (1<<6) /* rw su only */
#define AP1_USR_RO (2<<6) /* sup=RW, user=RO */
#define AP1_RW (3<<6) /* su=RW, user=RW */
/* page dir 1 ap2 */
#define AP2_SU_ONLY (1<<8) /* rw su only */
#define AP2_USR_RO (2<<8) /* sup=RW, user=RO */
#define AP2_RW (3<<8) /* su=RW, user=RW */
/* page dir 1 ap3 */
#define AP3_SU_ONLY (1<<10) /* rw su only */
#define AP3_USR_RO (2<<10) /* sup=RW, user=RO */
#define AP3_RW (3<<10) /* su=RW, user=RW */
#define RAM_START (0x30000000)
#define KERNEL_ENTRY (0x30300000) /* BANK 6 (3M) */
#define KERNEL_STACK (0x3001A000) /* BANK 6 (16K + 64K + 16K + 8K) (8k kernel stack) */
#define IRQ_STACK (0x3001B000) /* 4K IRQ STACK */
#define KERNEL_IMG_SIZE (0x20000)
#define IRQ_STACK (0x3001B000)
/* 16K aignment */
#define TTB_BASE (0x30000000)
#define PAGE_DIR0 (TTB_BASE)
#define TTB_FULL_SIZE (0x4000)
#define PAGE_DIR1 (TTB_BASE+TTB_FULL_SIZE)
#define PAGE_DIR0_SIZE (0x4000) /* 16k */
void _do_page_fault (void)
{
//
...........
//
// read the FSR && get the vaddr && type here
volatile unsigned *page_dir = (volatile unsigned*)(TTB_BASE);
unsigned index = vaddr >> 20,i = 0, j = 0;
unsigned page = 0;
if (!(page_dir[index] & ~(0x3FF) && (type == 0x0B))) { /* page_dir empty */
i = index & ~0x03;
if ( (page_dir[i+0] & ~(0x3FF)) || (page_dir [i+1] & ~(0x3FF))
|| (page_dir[i+2] & ~(0x3FF)) || (page_dir [i+3] & ~(0x3FF)) )
{
panic ( "page dir is bad !\n" ); /* 4 continuous page_dir must be 0 */
}
if (!(page = find_free_page ()))
panic ( "no more free page !\n" ); /* alloc a page page dir*/
page_dir[i+0] = (page + 0x000) | DOMAIN_USR | TTB0_COARSE ; /* small page 1st 1KB */
page_dir[i+1] = (page + 0x400) | DOMAIN_USR | TTB0_COARSE ; /* small page 2nd 1KB */
page_dir[i+2] = (page + 0x800) | DOMAIN_USR | TTB0_COARSE ; /* small page 3rd 1KB */
page_dir[i+3] = (page + 0xC00) | DOMAIN_USR | TTB0_COARSE ; /* small page 4th 1KB */
if (!(page = find_free_page ()))
panic ( "no more free page !\n" ); /* alloc a page page table*/
volatile unsigned *page_tbl = (volatile unsigned*) (page_dir[index] & ~(0x3FF));
*page_tbl = page|AP0_RW|AP1_RW|AP2_RW|AP3_RW| NCNB|TTB1_SPG;/* small page is used */
invalidate_icache ();
for (i = 0; i < 64; i++)
{
for (j = 0;j < 8;j ++)
clr_invalidate_dcache ( (i<<26)|(j<<5) );
}
invalidate_tlb ();
}
........
//
}
/* here is the macros */
#define invalidate_tlb() \
{\
__asm__ __volatile__ (\
"mov r0,#0\n"\
"mcr p15,0,r0,c8,c7,0\n"\
:::"r0" \
);\
}
#define clr_invalidate_dcache(index) \
{\
__asm__ __volatile__ (\
"mcr p15,0,%[i],c7,c14,2\n"\
:: [i]"r"(index)\
);\
}
#define invalidate_icache() \
{\
__asm__ __volatile__ (\
"mov r0,#0\n"\
"mcr p15,0,r0,c7,c5,0\n"\
::: "r0"\
);\
}
#define invalidate_dcache() \
{\
__asm__ __volatile__ (\
"mov r0,#0\n"\
"mcr p15,0,r0,c7,c6,0\n"\
::: "r0"\
);\
}
#define invalidate_idcache() \
{\
__asm__ __volatile__ (\
"mov r0,#0\n"\
"mcr p15,0,r0,c7,c7,0\n"\
:::"r0"\
);\
}\
Note: I assume TTB_BASE is the primary ARM L1 page table. If it is some shadow, you need to show more code as per unixsmurf. Here is my best guess...
Your page_dir is functioning as both the primary L1 entries and as the L2 fine page table. The TTB_BASE should only contain sections, super sections or pointers to sub-page tables. You need to allocate more physical memory for the L2 page tables.
I guess your page_dir[i+0], page_dir[i+1], etc are overwriting other L1 section entries and Your invalidate_tlb() make this concrete to the CPU. You should be using the L2 page_tbl pointer to set/index the small/fine pages. Perhaps your kernel code is in the 3G-4G space and your are over-writing some critical L1 mappings there; any number of strange things could happen. The current use of page_tbl is unclear.
You can not double use the primary L1 tables as they have meaning to hardware. I guess that this is just a mistake?
There are only three types of entries in the primary L1 page tables,
Sections - a 1MB memory mapping straight virt to phys, with no 2nd page table.
Super-sections - a 4MB memory mapping as per sections, but minimizing TLB pressure.
A 2nd page table. Entries can be 1k,4k,and 64k. Fine page tables are 4k in table size and are not in modern ARM designs. Each entry is 1k of address in a fine page table.
The primary page table must be on a physical address that is 16k aligned, which is also it's size. 16k/(4bytes/entry)*1MB gives a 4GB address range of the L1 tables. So each entry in the primary L1 page table always refers to a 1MB entry. Coarse page tables are the only option on newer ARMs and they refer to a 1K L2 table.
1K_L2_size * 4K_entry / (4bytes_per_entry) gives 1MB address space.
1K_L2_size * 64K_entry / (16bytes_per_entry) gives 1MB address space.
There are four entries of 1MB each in the primary L1 for a super-section. There are four entries each for a 64k large page in the L2 table. If you are using super-sections, you do not have L2 entries.
I think you may have Super-sections and large pages mixed up? For certain having improperly formatted page tables will only manifest on a TLB invalidate, so that MMU mappings are re-fetched from the tables via a walk.
Finally, you should flush the D cache and drain the write buffer to ensure consistency with memory. You may wish to have a memory barrier as well.
static inline void dcache_clean(void)
{
const int zero = 0;
asm volatile ("" ::: "memory"); /* barrier */
/* clean entire D cache -> push to external memory. */
asm volatile ("1: mrc p15, 0, r15, c7, c10, 3\n"
" bne 1b\n" ::: "cc");
/* drain the write buffer */
asm volatile ("mcr 15, 0, %0, c7, c10, 4"::"r" (zero));
}
There are also co-processor commands to invalidate single TLB entries as you are only changing a portion of the vaddr/paddr mappings in the data fault.
See also: ARM MMU tutorial, Virtual Memory structures, and your ARM Architecture Reference Manual.
I'm trying access the GPIO pins on Atmel's Arm9 9g20. My code below keeps getting failing at
gpio = mmap(0, getpagesize(), PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0xFFFFF400); // start of GPIOA
Could someone help me with my code and offer a bit of I/O example code to get me past this hump? Thanks.
// gpio.c
// compile arm-linux-gcc -o button button.c
//
#include<unistd.h>
#include<sys/types.h>
#include<sys/mman.h>
#include<stdio.h>
#include<fcntl.h>
#include<string.h>
// GPIO Registers
//http://www.atmel.com/dyn/resources/prod_documents/doc6384.pdf - page 374
#define PIO_PER 0x0000 // PIO Enable Register Write-only –
#define PIO_PDR 0x0004 // PIO Disable Register Write-only –
#define PIO_PSR 0x0008 // PIO Status Register Read-only
#define PIO_OER 0x0010 // Output Enable Register Write-only –
#define PIO_ODR 0x0014 // Output Disable Register Write-only –
#define PIO_OSR 0x0018 // Output Status Register Read-only. reset 0x0000 0000
//0x001C Reserved
#define PIO_IFER 0x0020 // Glitch Input Filter Enable Register Write-only –
#define PIO_IFDR 0x0024 // Glitch Input Filter Disable Register Write-only –
#define PIO_IFSR 0x0028 // Glitch Input Filter Status Register Read-only. Reset 0x0000 0000
//0x002C Reserved
#define PIO_SODR 0x0030 // Set Output Data Register Write-only –
#define PIO_CODR 0x0034 // Clear Output Data Register Write-only
#define PIO_ODSR 0x0038 // Output Data Status Register Read-only or Read-write
#define PIO_PDSR 0x003C // Pin Data Status Register Read-only
#define PIO_IER 0x0040 // Interrupt Enable Register Write-only –
#define PIO_IDR 0x0044 // Interrupt Disable Register Write-only –
#define PIO_IMR 0x0048 // Interrupt Mask Register Read-only. Reset 0x00000000
#define PIO_ISR 0x004C // Interrupt Status Register Read-only. Reset 0x00000000
#define PIO_MDER 0x0050 // Multi-driver Enable Register Write-only –
#define PIO_MDDR 0x0054 // Multi-driver Disable Register Write-only –
#define PIO_MDSR 0x0058 // Multi-driver Status Register Read-only. Reset 0x00000000
//0x005C Reserved
#define PIO_PUDR 0x0060 // Pull-up Disable Register Write-only –
#define PIO_PUER 0x0064 // Pull-up Enable Register Write-only –
#define PIO_PUSR 0x0068 // Pad Pull-up Status Register
#define PIO_ASR 0x0070 // Peripheral A Select Register Write-only –
#define PIO_BSR 0x0074 // Peripheral B Select Register Write-only –
#define PIO_ABSR 0x0078 // AB Status Register Read-only 0x00000000
//0x007C to 0x009C Reserved
#define PIO_OWER 0x00A0 // Output Write Enable Write-only –
#define PIO_OWDR 0x00A4 // Output Write Disable Write-only –
#define PIO_OWSR 0x00A8 // Output Write Status Register Read-only 0x00000000
/*******************************************************************************************************
* MAIN
*******************************************************************************************************/
int main(int argc, char **argv) {
volatile unsigned int *PADR, *PADDR, *PBDR, *PBDDR, *PCDR, *PCDDR;
unsigned long *gpio;
int fd = open("/dev/mem", O_RDWR|O_SYNC);
if (fd < 0){
fprintf(stderr, "Unable to open port\n\r");
exit(fd);
}
gpio = mmap(0, getpagesize(), PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0xFFFFF400); // start of GPIOA
if(gpio == (void *) -1) {
printf("Memory map failed.\n");
exit(0);
} else {
printf("Memory mapped at address %p.\n", gpio);
}
PADR = (unsigned int *)(gpio + 0x00); // port a
PADDR = (unsigned int *)(gpio + PIO_OER); // port a output enable
*PADDR = 0xff; // make all output
*PADR = 0xffff; // turn All of A Off
close(fd);
return 0;
}
Not sure what type of failings you are experiencing (they are not described) but operations with GPIO port and comments are not correct. First of all, register PIO_PER is IO enable register, setting bits is not making them output but enabling. On the other hand, PIO_OER is indeed for making them output and not turning all off. So, you should stick to the following sequence:
// initializing
*(unsigned int *) (gpio + PIO_PER) = 0xff; // enable
*(unsigned int *) (gpio + PIO_OER) = 0xff; // set output
// working
...
*(unsigned int *) (gpio + PIO_SODR) = 0xff; // set 1's
...
*(unsigned int *) (gpio + PIO_CODR) = 0xff; // set 0's
UPDATE
Since only whole pages can be mapped, you should take that into consideration:
#define MAP_SIZE 4096UL
#define MAP_MASK (MAP_SIZE - 1)
#define GPIOA_BASE 0xFFFFF400
...
/* Map one page */
map_base = mmap(0, MAP_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, GPIOA_BASE & & ~MAP_MASK);
...
gpio = map_base + (GPIOA_BASE & MAP_MASK);
...
Check the sources of well-known devmem tool: here
I've been searching everywhere finding a documentation that explains when to use each flags of kmalloc. I found this reference which fairly explains when to use some of the flags but I can't find the other flags like GFP_HIGHUSER_PAGECACHE, GFP_HIGHUSER_MOVABLE and other flags in gfp.h header file... Can somebody tell me when to use these other flags?
You want section Get Free Page (GFP) Flags of Understanding the Linux Virtual Memory Manager (pdf). It is for the 2.4 kernel but it should still apply.
original post:
From the 2.6.32 gfp.h:
/*
* Action modifiers - doesn't change the zoning
*
* __GFP_REPEAT: Try hard to allocate the memory, but the allocation attempt
* _might_ fail. This depends upon the particular VM implementation.
*
* __GFP_NOFAIL: The VM implementation _must_ retry infinitely: the caller
* cannot handle allocation failures.
*
* __GFP_NORETRY: The VM implementation must not retry indefinitely.
*
* __GFP_MOVABLE: Flag that this page will be movable by the page migration
* mechanism or reclaimed
*/
#define __GFP_WAIT ((__force gfp_t)0x10u) /* Can wait and reschedule? */
#define __GFP_ ((__force gfp_t)0x20u) /* Should access emergency pools? */
#define __GFP_IO ((__force gfp_t)0x40u) /* Can start physical IO? */
#define __GFP_FS ((__force gfp_t)0x80u) /* Can call down to low-level FS? */
#define __GFP_COLD ((__force gfp_t)0x100u) /* Cache-cold page required */
#define __GFP_NOWARN ((__force gfp_t)0x200u) /* Suppress page allocation failure warning */
#define __GFP_REPEAT ((__force gfp_t)0x400u) /* See above */
#define __GFP_NOFAIL ((__force gfp_t)0x800u) /* See above */
#define __GFP_NORETRY ((__force gfp_t)0x1000u)/* See above */
#define __GFP_COMP ((__force gfp_t)0x4000u)/* Add compound page metadata */
#define __GFP_ZERO ((__force gfp_t)0x8000u)/* Return zeroed page on success */
#define __GFP_NOMEMALLOC ((__force gfp_t)0x10000u) /* Don't use emergency reserves */
#define __GFP_HARDWALL ((__force gfp_t)0x20000u) /* Enforce hardwall cpuset memory allocs */
#define __GFP_THISNODE ((__force gfp_t)0x40000u)/* No fallback, no policies */
#define __GFP_RECLAIMABLE ((__force gfp_t)0x80000u) /* Page is reclaimable */
Also, from kernel archives:
To make code easier to read, a set of
three GFP flags are added called
GFP_PAGECACHE, GFP_NOFS_PAGECACHE and
GFP_HIGHUSER_PAGECACHE.
Looking at the diff source on that page shows the flags you were asking about are a combination of existing flags:
#define GFP_HIGHUSER_MOVABLE (__GFP_WAIT | __GFP_IO | __GFP_FS | \
__GFP_HARDWALL | __GFP_HIGHMEM | \
__GFP_MOVABLE)
+#define GFP_NOFS_PAGECACHE (__GFP_WAIT | __GFP_IO | __GFP_MOVABLE)
+#define GFP_USER_PAGECACHE (__GFP_WAIT | __GFP_IO | __GFP_FS | \
+ __GFP_HARDWALL | __GFP_MOVABLE)
+#define GFP_HIGHUSER_PAGECACHE (__GFP_WAIT | __GFP_IO | __GFP_FS | \
+ __GFP_HARDWALL | __GFP_HIGHMEM | \
+ __GFP_MOVABLE)
#ifdef CONFIG_NUMA
#define GFP_THISNODE (__GFP_THISNODE | __GFP_NOWARN | __GFP_NORETRY)