Machine-Oriented Programming C-Programming part 3 Pedro Trancoso ppedro@chalmers.se Original slides by Ulf Assarsson
Objectives • Pointers to struct • Port addressing with structs • Function pointer • Structs with function pointers • Dynamic memory allocation • Linked lists • File operations 3/29/19 Chalmers 2
Pointers to struct / arrow notation Course mop; Course *pmop; // Pointer to struct pmop = &mop; (*pmop).name = … // Or easier: pmop->name = … The arrow notation simplifies the code, as it is common to have pointers for structs 3/29/19 Chalmers 3
Pointer to struct In Java: public class Course { #include <stdio.h> String name; #include <stdlib.h> float credits; int numberOfParticipants; char* coursename = "Machine Oriented Programming"; } typedef struct { char* name; Course mop = new Course(); float credits; mop.name = … int numberOfParticipants; mop.credits = 7.5; } Course; … int main() { Course *pmop; // Pointer to struct // or pmop = (Course*) malloc (sizeof(Course)); Course mop, *pmop; pmop = &mop; //(*pmop).name = coursename; // and of course without free() pmop->name = coursename; pmop->credits = 7.5; Access to members (fields) via -> operator pmop->numberOfParticipants = 110; free (pmop); return 0; } 3/29/19 Chalmers 4
Port addressing with structs GPIO General Purpose Input Output GPIO A: 0x40020000 Instead of: GPIO B: 0x40020400 #defineportModer ((volatile unsigned int *) (PORT_DISPLAY_BASE)) GPIO C: 0x40020800 #defineportOtyper ((volatile unsigned short *)(PORT_DISPLAY_BASE+0x4)) GPIO D: 0x40020C00 #defineportOspeedr ((volatile unsigned int *) (PORT_DISPLAY_BASE+0x8)) GPIO E; 0x40021000 #defineportPupdr ((volatile unsigned int *) (PORT_DISPLAY_BASE+0xC)) #defineportIdrLow ((volatile unsigned char *) (PORT_DISPLAY_BASE+0x10)) #defineportIdrHigh ((volatile unsigned char *) (PORT_DISPLAY_BASE+0x11)) #defineportOdrLow ((volatile unsigned char *) (PORT_DISPLAY_BASE+0x14)) #defineportOdrHigh ((volatile unsigned char *) (PORT_DISPLAY_BASE+0x14+1)) Then we can use structs by writing : typedef struct { uint32_t moder; #define GPIO_D (*((volatile GPIO*) 0x40020c00)) uint16_t otyper; // +0x4 #define GPIO_E (*((volatile GPIO*) 0x40021000)) uint16_t otReserved; // uint32_t ospeedr; // +0x8 Example: uint32_t pupdr; // +0xc (12) GPIO_E.moder = 0x55555555; uint8_t idrLow; // +0x10 uint8_t idrHigh; // +0x11 GPIO_E.otyper = 0x00000000; uint16_t idrReserved; GPIO_E.ospeedr = 0x55555555; uint8_t odrLow; // +0x14 GPIO_E.pupdr &= 0x55550000; uint8_t odrHigh; // +0x15 uint16_t odrReserved; } GPIO; 3/29/19 Chalmers 5
Port addressing – individual bytes We defined idrLow and idrHigh as bytes and idrReserved as 16-bit. But we could instead have defined all these three as just uint32_t idr; i.e. 4 bytes and then address individual bytes uint8_t x = *(uint8_t*)&GPIO_E.idr; // idrLow uint8_t y = *((uint8_t*)&GPIO_E.idr + 1); // idrHigh uint16_t z = *((uint16_t*)&GPIO_E.idr + 1); // idrReserved typedef struct { typedef struct _gpio { uint32_t moder; uint32_t moder; uint16_t otyper; // +0x4 uint32_t otyper; // +0x4 uint16_t otReserved; uint32_t ospeedr; // +0x8 uint32_t ospeedr; // +0x8 uint32_t pupdr; // +0xc uint32_t pupdr; // +0xc uint32_t idr; // +0x10 uint8_t idrLow; // +0x10 uint32_t odr; // +0x14 uint8_t idrHigh; // +0x11 } GPIO; uint16_t idrReserved; uint8_t odrLow; // +0x14 typedef volatile GPIO* gpioptr; uint8_t odrHigh; // +0x15 #define GPIO_E (*((gpioptr) 0x40021000)) uint16_t odrReserved; } GPIO; typedef volatile GPIO* gpioptr; #define GPIO_E (*((gpioptr) 0x40021000)) 3/29/19 Chalmers 6
Port addressing with structs Example: typedef struct tag_usart while (( (*USART).sr & 0x80) == 0) { volatile unsigned short sr; ; // wait until it is ok to write (*USART1).dr = (unsigned short) 'a'; volatile unsigned short Unused0; volatile unsigned short dr; volatile unsigned short Unused1; Or with the arrow notation: volatile unsigned short brr; volatile unsigned short Unused2; while (( USART->sr & 0x80)==0) volatile unsigned short cr1; ; volatile unsigned short Unused3; USART1->dr = (unsigned short) 'a‘; volatile unsigned short cr2; USART volatile unsigned short Unused4; Universal synchronous asynchronous receiver transmitter volatile unsigned short cr3; USART1: 0x40011000 volatile unsigned short Unused5; USART2: 0x40004400 volatile unsigned short gtpr; } USART; #define USART1 ((USART *) 0x40011000) 3/29/19 Chalmers 7 USART_SR Statusregister (0x00C0)
Function pointer #include <stdio.h> int square(int x) { return x*x; } int main() A function pointer { int (*fp)(int); fp = square; fp(5)=25 printf("fp(5)=%i \n", fp(5)); return 0; } 3/29/19 Chalmers 8
Function pointer int (*fp)(int); A Function pointer type is defined by: Question: • Return type. What is the definition for a • Number of arguments and their types. function pointer that points to function foo char *foo( int *x, int y) {…} The value of a function pointer is an address. LDR R4, =fp LDR R4, =foo BLX R4 BLX R4 3/29/19 Chalmers 9
Structs with function pointers Programming object-oriented style in a non-object-oriented language! ! Arbetsbok pg 109-111 typedef struct tObj { PGEOMETRY geo; int dirx, diry; int posx, posy; void (*draw)(struct tObj *); What are ”draw”, void (*clear)(struct tObj *); ”clear”, ”move”, ”set_speed”? void (*move)(struct tObj *); void (*set_speed)(struct tObj *, int, int); } OBJECT, *POBJECT; 3/29/19 Chalmers 10
Structs with function pointers How do you initialize them? Programming object-oriented style in a non-object-oriented language! static OBJECT ball = { ! Arbetsbok pg 109-111 &ball_geometry, 0, 0, typedef struct tObj { 1, 1, draw_object, PGEOMETRY geo; clear_object, int dirx, diry; move_object, int posx, posy; set_object_speed }; void (*draw)(struct tObj *); void (*clear)(struct tObj *); How do you use them? void (*move)(struct tObj *); POBJECT p = &ball; void (*set_speed)(struct tObj *, int, int); . . . } OBJECT, *POBJECT; p->set_speed(p,4,1); . . . p_>move(p); 3/29/19 Chalmers 11
Dynamic Memory Allocation What happens if we do not call free? Allocate memory • malloc() De-allocate (free) memory • free() Do you need to use some sort of free also Function prototypes available in: in Java? Why? #include <stdlib.h> 3/29/19 Chalmers 12
Dynamic Memory Allocation #include <stdlib.h> char s1[] = "This is a long string. It is even more than one sentence."; Can you guess the int main() After malloc ALWAYS do: prototype for malloc? { if( !p ) { char* p; printf(”ERROR: Could not allocate p\n”); exit(-1); } // allocate memory dynamically p = (char*)malloc(sizeof(s1)); Number of bytes we want to allocate // make something with the memory that we have reserved // free the memory space OUT OF MEMORY free(p); virtual address space is divided into pages swapped to the secondary return 0; storage (e.g. hard disk). Even this may end -> crash. } 3/29/19 Chalmers 13
Address Space of a Program • All programs as they execute, have some associated memory, which is typically divided into: • Code Segment • Data Segment (Holds Global Data) • Stack (where the local variables and other temporary information is stored) • Heap The Stack grows Stack downwards Increasing The Heap grows Heap addresses upwards Data Segment Code Segment 3/29/19 Chalmers 14
Dynamic Memory Allocation Example // Copy from s1 to the allocated memory pointed by p. #include <stdio.h> #include <stdlib.h> char s1[] = "This is a long string. It is even more than one sentence."; int main() { char* p; Do I need to do something int i; between allocation and use? // allocate memory dynamically p = (char*)malloc(sizeof(s1)); // make something with the memory that is allocated for( i=0; i<sizeof(s1); i++) *(p+i) = s1[i]; What happens if I do *(p+1000) = 1024 printf("%s", p); // free memory Why does free(p) not need free(p); information about its size? return 0; } 3/29/19 Chalmers 15
Dynamic Memory Allocation – other types #include <stdio.h> x = (int*) malloc( sizeof(int)*100 ); #include <stdlib.h> if( !x ) exit(-1); typedef struct { char *name; int number; y = (char*) malloc( sizeof(char)*100 ); } xyz; if( !y ) exit(-1); int main() { int *x; char *y; z = (double*) malloc( sizeof(double)*100 ); double *z; if( !z ) exit(-1); xyz *u; //allocate 100 int, char, double and xyz u = (xyz*) malloc( sizeof(xyz)*100 ); } if( !u ) exit(-1); 3/29/19 Chalmers 16
Other dynamic memory allocation functions… ptr = (int*) calloc(n, sizeof(int)); ptr = (int*) malloc(n1 * sizeof(int)); . . . ptr = realloc(ptr, n2 * sizeof(int)); 3/29/19 Chalmers 17
Recommend
More recommend