Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Peripheral.cpp
00001 //#include "mbed.h" 00002 #include "BCM2835.h" 00003 #include "Thread.h" 00004 #include "ThisThread.h" 00005 #include "Peripheral.h" 00006 00007 struct bcm2835_peripheral bsc_rev1 = { BCM2835_PERI_BASE + 0X205000, 0, 0, 0 }; 00008 struct bcm2835_peripheral bsc_rev2 = { BCM2835_PERI_BASE + 0X804000, 0, 0, 0 }; 00009 struct bcm2835_peripheral bsc0; 00010 struct bcm2835_peripheral gpio = { BCM2835_PERI_BASE + 0x200000, 0, 0, 0 }; 00011 00012 timeval start_program, end_point; 00013 00014 off_t bcm2835_peripherals_base = BCM2835_PERI_BASE; 00015 size_t bcm2835_peripherals_size = BCM2835_PERI_SIZE; 00016 volatile uint32_t* bcm2835_peripherals; 00017 volatile uint32_t* bcm2835_pwm = (uint32_t *)MAP_FAILED; 00018 volatile uint32_t* bcm2835_clk = (uint32_t *)MAP_FAILED; 00019 volatile uint32_t* bcm2835_bsc1 = (uint32_t *)MAP_FAILED; 00020 volatile uint32_t* bcm2835_spi0 = (uint32_t *)MAP_FAILED; 00021 volatile uint32_t* bcm2835_st = (uint32_t *)MAP_FAILED; 00022 00023 00024 //Constructor 00025 Peripheral::Peripheral() 00026 { 00027 REV = getBoardRev(); 00028 if (map_peripheral(&gpio) == -1) { 00029 printf("Failed to map the physical GPIO registers into the virtual memory space.\n"); 00030 } 00031 00032 memfd = -1; 00033 00034 // Open the master /dev/memory device 00035 if ((memfd = open("/dev/mem", O_RDWR | O_SYNC)) < 0) { 00036 fprintf(stderr, "bcm2835_init: Unable to open /dev/mem: %s\n", strerror(errno)); 00037 exit(1); 00038 } 00039 00040 bcm2835_peripherals = mapmem("gpio", bcm2835_peripherals_size, memfd, bcm2835_peripherals_base); 00041 if (bcm2835_peripherals == MAP_FAILED) 00042 exit(1); 00043 00044 /* Now compute the base addresses of various peripherals, 00045 // which are at fixed offsets within the mapped peripherals block 00046 // Caution: bcm2835_peripherals is uint32_t*, so divide offsets by 4 00047 */ 00048 bcm2835_pwm = bcm2835_peripherals + BCM2835_GPIO_PWM/4; 00049 bcm2835_clk = bcm2835_peripherals + BCM2835_CLOCK_BASE/4; 00050 bcm2835_spi0 = bcm2835_peripherals + BCM2835_SPI0_BASE/4; 00051 bcm2835_bsc1 = bcm2835_peripherals + BCM2835_BSC1_BASE/4; /* I2C */ 00052 bcm2835_st = bcm2835_peripherals + BCM2835_ST_BASE/4; 00053 00054 // start timer 00055 gettimeofday(&start_program, NULL); 00056 } 00057 00058 //Destructor 00059 Peripheral::~Peripheral() 00060 { 00061 unmap_peripheral(&gpio); 00062 00063 bcm2835_pwm = (uint32_t *)MAP_FAILED; 00064 bcm2835_clk = (uint32_t *)MAP_FAILED; 00065 bcm2835_spi0 = (uint32_t *)MAP_FAILED; 00066 bcm2835_bsc1 = (uint32_t *)MAP_FAILED; 00067 } 00068 00069 /******************* 00070 * Private methods * 00071 *******************/ 00072 00073 // Exposes the physical address defined in the passed structure using mmap on /dev/mem 00074 int Peripheral::map_peripheral(struct bcm2835_peripheral* p) 00075 { 00076 // Open /dev/mem 00077 00078 if ((p->mem_fd = open("/dev/mem", O_RDWR | O_SYNC)) < 0) { 00079 printf("Failed to open /dev/mem, try checking permissions.\n"); 00080 return -1; 00081 } 00082 00083 p->map = mmap 00084 ( 00085 NULL, 00086 BLOCK_SIZE, 00087 PROT_READ | PROT_WRITE, 00088 MAP_SHARED, 00089 p->mem_fd, // File descriptor to physical memory virtual file '/dev/mem' 00090 p->addr_p // Address in physical map that we want this memory block to expose 00091 ); 00092 00093 if (p->map == MAP_FAILED) { 00094 perror("mmap"); 00095 return -1; 00096 } 00097 00098 p->addr = (volatile unsigned int*)p->map; 00099 00100 return 0; 00101 } 00102 00103 /** 00104 * @brief 00105 * @note 00106 * @param 00107 * @retval 00108 */ 00109 void Peripheral::unmap_peripheral(struct bcm2835_peripheral* p) 00110 { 00111 munmap(p->map, BLOCK_SIZE); 00112 unistd::close(p->mem_fd); 00113 } 00114 00115 // 00116 // Low level convenience functions 00117 // 00118 00119 /** 00120 * @brief 00121 * @note 00122 * @param 00123 * @retval 00124 */ 00125 uint32_t* mapmem(const char* msg, size_t size, int fd, off_t off) 00126 { 00127 uint32_t* map = (uint32_t*)mmap(NULL, size, (PROT_READ | PROT_WRITE), MAP_SHARED, fd, off); 00128 if (MAP_FAILED == map) 00129 fprintf(stderr, "bcm2835_init: %s mmap failed: %s\n", msg, strerror(errno)); 00130 return map; 00131 } 00132 00133 // safe read from peripheral 00134 uint32_t bcm2835_peri_read(volatile uint32_t* paddr) 00135 { 00136 uint32_t ret = *paddr; 00137 ret = *paddr; 00138 return ret; 00139 } 00140 00141 // read from peripheral without the read barrier 00142 uint32_t bcm2835_peri_read_nb(volatile uint32_t* paddr) 00143 { 00144 return *paddr; 00145 } 00146 00147 // safe write to peripheral 00148 void bcm2835_peri_write(volatile uint32_t* paddr, uint32_t value) 00149 { 00150 *paddr = value; 00151 *paddr = value; 00152 } 00153 00154 // write to peripheral without the write barrier 00155 void bcm2835_peri_write_nb(volatile uint32_t* paddr, uint32_t value) 00156 { 00157 *paddr = value; 00158 } 00159 00160 // Set/clear only the bits in value covered by the mask 00161 void bcm2835_peri_set_bits(volatile uint32_t* paddr, uint32_t value, uint32_t mask) 00162 { 00163 uint32_t v = bcm2835_peri_read(paddr); 00164 v = (v &~mask) | (value & mask); 00165 bcm2835_peri_write(paddr, v); 00166 } 00167 00168 /** 00169 * @brief 00170 * @note 00171 * @param 00172 * @retval 00173 */ 00174 int getBoardRev() 00175 { 00176 FILE* cpu_info; 00177 char line[120]; 00178 char* c, finalChar; 00179 //static int rev = 0; 00180 00181 if (REV != 0) 00182 return REV; 00183 00184 if ((cpu_info = fopen("/proc/cpuinfo", "r")) == NULL) { 00185 fprintf(stderr, "Unable to open /proc/cpuinfo. Cannot determine board reivision.\n"); 00186 exit(1); 00187 } 00188 00189 while (fgets(line, 120, cpu_info) != NULL) { 00190 if (strncmp(line, "Revision", 8) == 0) 00191 break; 00192 } 00193 00194 fclose(cpu_info); 00195 00196 if (line == NULL) { 00197 fprintf(stderr, "Unable to determine board revision from /proc/cpuinfo.\n"); 00198 exit(1); 00199 } 00200 00201 for (c = line; *c; ++c) 00202 if (isdigit(*c)) 00203 break; 00204 00205 if (!isdigit(*c)) { 00206 fprintf(stderr, "Unable to determine board revision from /proc/cpuinfo\n"); 00207 fprintf(stderr, " (Info not found in: %s\n", line); 00208 exit(1); 00209 } 00210 00211 finalChar = c[strlen(c) - 2]; 00212 00213 if ((finalChar == '2') || (finalChar == '3')) { 00214 bsc0 = bsc_rev1; 00215 return 1; 00216 } 00217 else { 00218 bsc0 = bsc_rev2; 00219 return 2; 00220 } 00221 } 00222 00223 /** 00224 * @brief 00225 * @note 00226 * @param 00227 * @retval 00228 */ 00229 void attachInterrupt(PinName p, void (*f) (), Digivalue m) 00230 { 00231 int GPIOPin = p; 00232 pthread_t* threadId = getThreadIdFromPin(p); 00233 struct ThreadArg* threadArgs = (ThreadArg*)malloc(sizeof(ThreadArg)); 00234 threadArgs->func = f; 00235 threadArgs->pin = GPIOPin; 00236 00237 //Export pin for interrupt 00238 FILE* fp = fopen("/sys/class/gpio/export", "w"); 00239 if (fp == NULL) { 00240 fprintf(stderr, "Unable to export pin %d for interrupt\n", p); 00241 exit(1); 00242 } 00243 else { 00244 fprintf(fp, "%d", GPIOPin); 00245 } 00246 00247 fclose(fp); 00248 00249 //The system to create the file /sys/class/gpio/gpio<GPIO number> 00250 //So we wait a bit 00251 ThisThread::sleep_for_ms(1); 00252 00253 char* interruptFile = NULL; 00254 asprintf(&interruptFile, "/sys/class/gpio/gpio%d/edge", GPIOPin); 00255 00256 //Set detection condition 00257 fp = fopen(interruptFile, "w"); 00258 if (fp == NULL) { 00259 fprintf(stderr, "Unable to set detection type on pin %d\n", p); 00260 exit(1); 00261 } 00262 else { 00263 switch (m) { 00264 case RISING: 00265 fprintf(fp, "rising"); 00266 break; 00267 00268 case FALLING: 00269 fprintf(fp, "falling"); 00270 break; 00271 00272 default: 00273 fprintf(fp, "both"); 00274 break; 00275 } 00276 } 00277 00278 fclose(fp); 00279 00280 if (*threadId == 0) { 00281 00282 //Create a thread passing the pin and function 00283 pthread_create(threadId, NULL, threadFunction, (void*)threadArgs); 00284 } 00285 else { 00286 00287 //First cancel the existing thread for that pin 00288 pthread_cancel(*threadId); 00289 00290 //Create a thread passing the pin, function and mode 00291 pthread_create(threadId, NULL, threadFunction, (void*)threadArgs); 00292 } 00293 } 00294 00295 /** 00296 * @brief 00297 * @note 00298 * @param 00299 * @retval 00300 */ 00301 void detachInterrupt(PinName p) 00302 { 00303 int GPIOPin = p; 00304 00305 FILE* fp = fopen("/sys/class/gpio/unexport", "w"); 00306 if (fp == NULL) { 00307 fprintf(stderr, "Unable to unexport pin %d for interrupt\n", p); 00308 exit(1); 00309 } 00310 else { 00311 fprintf(fp, "%d", GPIOPin); 00312 } 00313 00314 fclose(fp); 00315 00316 pthread_t* threadId = getThreadIdFromPin(p); 00317 pthread_cancel(*threadId); 00318 } 00319 00320 Peripheral peripheral = Peripheral(); 00321 00322
Generated on Tue Dec 20 2022 12:16:32 by
1.7.2