int main (int argc, char **argv) { int opt, flag, n_pin, n_alt; flag=0; while ((opt = getopt (argc, argv, "hp:f:")) != -1) { switch (opt) { case 'h': break; case 'p': n_pin = atoi(optarg); flag |= 0b0001; break; case 'f': n_alt = atoi(optarg); flag |= 0b0010; break; case '?': // getopt() prints error messages, so don't need to repeat them here return 1; default: abort (); } } if (flag != 0b0011) { fprintf (stderr, "Usage:\n$ gpio_alt -p PIN_NUM -f FUNC_NUM\n"); return 1; } setup_io(); // Set up gpi pointer for direct register access INP_GPIO(n_pin); // Always use INP_GPIO(x) before using SET_GPIO_ALT(x,y) SET_GPIO_ALT(n_pin, n_alt); printf("Set pin %i to alternative-function %i\n", n_pin, n_alt); return 0; }
int initGPIO() { // Map the GPIO and Aux memory mGPIO = mapMem ( GPIO_BASE, 0x1000 ); // UART1 = Mini-UART, UART0 - PL011 // Set GPIO15 and 16 for UART1 to ALT5 Mini-Uart INP_GPIO ( kBufferDirectionPin ); OUT_GPIO ( kBufferDirectionPin ); INP_GPIO ( kScopeTriggerPin ); OUT_GPIO ( kScopeTriggerPin ); INP_GPIO ( kUART1TxPin ); SET_GPIO_ALT ( kUART1TxPin, 5 ); INP_GPIO ( kUART1RxPin ); SET_GPIO_ALT ( kUART1RxPin, 5 ); INP_GPIO ( kUART1RTSPin); SET_GPIO_ALT ( kUART1RTSPin, 5 ); }
/** * init_module() - This function is called when the module is loaded * * Return: On succes the function retuns a 0 (SUCCES). Otherwise a * negative number is returned. */ int init_module(void) { Major = register_chrdev(0, DEVICE_NAME, &fops); if (Major < 0) { printk(KERN_ALERT "Registering char device failed with %d\n", Major); return Major; } printk(KERN_INFO "I was assigned major number %d. To talk to\n", Major); printk(KERN_INFO "the driver, create a device file with\n"); printk(KERN_INFO "'mknod /dev/%s c %d 0'.\n", DEVICE_NAME, Major); printk(KERN_INFO "Try various minor numbers. Try to echo to\n"); printk(KERN_INFO "the device file.\n"); printk(KERN_INFO "Remove the device file and module when done.\n"); gpio = (volatile unsigned int *)ioremap(GPIO_BASE, 1024); pwm = (volatile unsigned int *)ioremap(PWM_BASE, 1024); clk = (volatile unsigned int *)ioremap(CLOCK_BASE, 1024); // Set pin directions for the output INP_GPIO(GPIO_OUTP); OUT_GPIO(GPIO_OUTP); // PWM and clock settings SET_GPIO_ALT(GPIO_PWM1, GPIO_ALT); // stop clock and waiting for busy flag doesn't work, so kill clock *(clk + CLK_CTL) = CLK_PASSWD | CLK_CTL_KILL; udelay(10); // Set clock divider *(clk + CLK_DIV) = CLK_PASSWD | CLK_DIV_DIVI(96); // source=osc and enable clock *(clk + CLK_CTL) = CLK_PASSWD | CLK_CTL_ENAB | CLK_CTL_SRC(CLK_CTL_SRC_OSC); // disable PWM and start with a clean register *(pwm + PWM_CTL) = 0; // needs some time until the PWM module gets disabled, without the delay the PWM module crashes udelay(10); // Set the PWM range *(pwm + PWM_RNG2) = 4000; // Initialize with a 50% dutycycle setServo(50); // start PWM in M/S transmission mode *(pwm + PWM_CTL) = PWM_CTL_MSEN2 | PWM_CTL_PWEN2; interrupt_config(); return SUCCESS; }
void init_uart() { // Disable UART0. UART0_CR = ZERO; // Setup the GPIO pin 14 && 15 (Alternate Function 0). SET_GPIO_ALT(14, 0); SET_GPIO_ALT(15, 0); // Disable pull up/down for all GPIO pins & delay for 150 cy GPIO_PULL = ZERO; short_wait_150(); // Disable pull up/down for pin 14,15 & delay for 150 cycles. GPIO_PULLCLK0 = ((1 << 14)|(1 << 15)); short_wait_150(); // Write 0 to GPPUDCLK0 to make it take effect. GPIO_PULLCLK0 = ZERO; // Clear pending interrupts. p.192 0x7ff binär 11 einser, gesamtes interrupt clear register gesetzt UART0_ICR = 0x7FF; // Set integer & fractional part of baud (= übertragunsrate; symbole/sekunde) rate. // Divider = UART_CLOCK/(16 * Baud) // Fraction part register = (Fractional part * 64) + 0.5 // UART_CLOCK = 3000000; Baud = 115200. // Divider = 3000000/(16 * 115200) = 1.627 = ~1. // Fractional part register = (.627 * 64) + 0.5 = 40.6 = ~40. UART0_IBRD = 1; UART0_FBRD = 40; // Enable FIFO & 8 bit data transmissio (1 stop bit, no parity) p.184. UART0_LCRH = ((1 << 4)|(1 << 5)|(1 << 6)); // Mask all interrupts p.188/189. UART0_IMSC = ((1 << 1) | (1 << 4) | (1 << 5) | (1 << 6) | (1 << 7) | (1 << 8) | (1 << 9) | (1 << 10)); // Enable UART0, receive & transfer part of UART p.186/187. UART0_CR = ((1 << 0) | (1 << 8) | (1 << 9)); } // Initialisation finished/ UART0 ready.
int init() { if ( setup_io() == 0 ) { return -1; } // activate SPI bus pins INP_GPIO(8); SET_GPIO_ALT(8,0); INP_GPIO(9); SET_GPIO_ALT(9,0); INP_GPIO(10); SET_GPIO_ALT(10,0); INP_GPIO(11); SET_GPIO_ALT(11,0); // Setup SPI bus setup_spi(); return 0; }
static void audio_init(void) { /* Values read from raspbian: */ /* PWMCLK_CNTL = 148 = 10010100 PWMCLK_DIV = 16384 PWM_CONTROL=9509 = 10010100100101 PWM0_RANGE=1024 PWM1_RANGE=1024 */ unsigned int range = 0x400; unsigned int idiv = 2; /* unsigned int pwmFrequency = (19200000 / idiv) / range; */ SET_GPIO_ALT(40, 0); SET_GPIO_ALT(45, 0); pause(2); *(clk + BCM2835_PWMCLK_CNTL) = PM_PASSWORD | (1 << 5); // stop clock *(clk + BCM2835_PWMCLK_DIV) = PM_PASSWORD | (idiv<<12); // set divisor *(clk + BCM2835_PWMCLK_CNTL) = PM_PASSWORD | 16 | 1; // enable + oscillator (raspbian has this as plla) pause(2); // disable PWM *(pwm + BCM2835_PWM_CONTROL) = 0; pause(2); *(pwm+BCM2835_PWM0_RANGE) = range; *(pwm+BCM2835_PWM1_RANGE) = range; *(pwm+BCM2835_PWM_CONTROL) = BCM2835_PWM1_USEFIFO | // Use FIFO and not PWM mode // BCM2835_PWM1_REPEATFF | BCM2835_PWM1_ENABLE | // enable channel 1 BCM2835_PWM0_USEFIFO | // use FIFO and not PWM mode // BCM2835_PWM0_REPEATFF | */ 1<<6 | // clear FIFO BCM2835_PWM0_ENABLE; // enable channel 0 pause(2); }
void init_pwm() { INP_GPIO(18); SET_GPIO_ALT(18, 5); // enable PWM on GPIO 18 PWM_CTL &= 1; PWM_DATA = 512; PWM_RANGE = 1024; //OUT_GPIO(18); //GPIO_SET = 1 << 18; }
// // Set GPIO pins to the right mode // DEMO GPIO mapping: // Function Mode // GPIO0= LED Output // GPIO1= LED Output // GPIO4= PWM channel-B Output // GPIO7= SPI chip select B Funct. 0 // GPIO8= SPI chip select A Funct. 0 // GPIO9= SPI MISO Funct. 0 // GPIO10= SPI MOSI Funct. 0 // GPIO11= SPI CLK Funct. 0 // GPIO14= UART TXD (Funct. 0) // GPIO15= UART RXD (Funct. 0) // GPIO17= LED Output // GPIO18= PWM channel-A Funct. 5 // GPIO21= LED Output // GPIO22= LED Output // GPIO23= LED Output // GPIO24= Pushbutton Input // GPIO25= Pushbutton Input // // Always call INP_GPIO(x) first // as that is how the macros work void setup_gpio() { INP_GPIO(0); OUT_GPIO(0); INP_GPIO(1); OUT_GPIO(1); INP_GPIO(4); OUT_GPIO(4); INP_GPIO(7); SET_GPIO_ALT(7,0); INP_GPIO(8); SET_GPIO_ALT(8,0); INP_GPIO(9); SET_GPIO_ALT(9,0); INP_GPIO(10); SET_GPIO_ALT(10,0); INP_GPIO(11); SET_GPIO_ALT(11,0); // 14 and 15 are already set to UART mode // by Linux. Best if we don't touch them // INP_GPIO(14); SET_GPIO_ALT(14,0); // INP_GPIO(54); SET_GPIO_ALT(15,0); INP_GPIO(17); OUT_GPIO(17); INP_GPIO(18); SET_GPIO_ALT(18,5); INP_GPIO(21); OUT_GPIO(21); INP_GPIO(22); OUT_GPIO(22); INP_GPIO(23); OUT_GPIO(23); INP_GPIO(24); INP_GPIO(25); // enable pull-up on GPIO24&25 GPIO_PULL = 2; short_wait(); // clock on GPIO 24 & 25 (bit 24 & 25 set) GPIO_PULLCLK0 = 0x03000000; short_wait(); GPIO_PULL = 0; GPIO_PULLCLK0 = 0; } // setup_gpio
/* * Establish the PWM frequency: */ static int pwm_frequency(float freq) { const double clock_rate = 19200000.0; long idiv; int rc = 0; /* * Kill the clock: */ ugclk[PWMCLK_CNTL] = 0x5A000020; /* Kill clock */ pwm_ctl->PWEN1 = 0; /* Disable PWM */ usleep(10); /* * Compute and set the divisor : */ idiv = (long) ( clock_rate / (double) freq ); if ( idiv < 1 ) { idiv = 1; /* Lowest divisor */ rc = -1; } else if ( idiv >= 0x1000 ) { idiv = 0xFFF; /* Highest divisor */ rc = +1; } ugclk[PWMCLK_DIV] = 0x5A000000 | ( idiv << 12 ); /* * Set source to oscillator and enable clock: */ ugclk[PWMCLK_CNTL] = 0x5A000011; /* * GPIO 18 is PWM, when set to Alt Func 5 : */ INP_GPIO(18); /* Set ALT = 0 */ SET_GPIO_ALT(18,5); /* Or in '5' */ pwm_ctl->MODE1 = 0; /* PWM mode */ pwm_ctl->RPTL1 = 0; pwm_ctl->SBIT1 = 0; pwm_ctl->POLA1 = 0; pwm_ctl->USEF1 = 0; pwm_ctl->MSEN1 = 0; /* PWM mode */ pwm_ctl->CLRF1 = 1; return rc; }
int pwm_init () { int mem_fd; mem_fd = open_memory(); if ( mem_fd < 0) { debug("[%s] Can't open /dev/mem.\n", __func__); return -1; } // FIXME: Check return values? gpio = map_register(mem_fd, GPIO_BASE); clk = map_register(mem_fd, CLOCK_BASE); pwm = map_register(mem_fd, PWM_BASE); /* GPIO18= PWM channel-A Funct. 5 Setup GPIO18 as PWM output */ INP_GPIO(18); SET_GPIO_ALT(18, 5); /* Derive PWM clock direct from X-tal thus any system auto-slow-down-clock-to-save-power does not effect it The values below depends on the X-tal frequency! */ PWMCLK_DIV = 0x5A000000 | (32 << 12);/* set pwm div to 32 (19.2/3 = 600KHz) */ PWMCLK_CNTL = 0x5A000011; /* Source=osc and enable */ /* Make sure it is off and that the B driver (GPIO4) is low */ GPIO_CLR0 = 1 << 4; /* Set GPIO 4 LOW */ PWM_CONTROL = 0; usleep(100); /* I use 1024 steps for the PWM (Just a nice value which I happen to like) */ PWM0_RANGE = PWM_MAX; usleep(100); PWM_CONTROL = PWM0_ENABLE; usleep(100); return 1; }
static void spi_init_pinmode(void) { #define INP_GPIO(g) *(gpio+((g)/10)) &= ~(7<<(((g)%10)*3)) #define SET_GPIO_ALT(g,a) *(gpio+(((g)/10))) |= (((a)<=3?(a)+4:(a)==4?3:2)<<(((g)%10)*3)) int pin; u32 *gpio = ioremap(GPIO_BASE, SZ_16K); for (pin = 7; pin <= 11; pin++) { INP_GPIO(pin); SET_GPIO_ALT(pin, 0); } iounmap(gpio); #undef INP_GPIO #undef SET_GPIO_ALT }
static void spi_init_pinmode(void) { #define INP_GPIO(g) *(gpio+((g)/10)) &= ~(7<<(((g)%10)*3)) #define SET_GPIO_ALT(g,a) *(gpio+(((g)/10))) |= (((a)<=3?(a)+4:(a)==4?3:2)<<(((g)%10)*3)) int pin; u32 *gpio = ioremap(GPIO_BASE, SZ_16K); /* SPI is on GPIO 7..11 */ for (pin = 7; pin <= 11; pin++) { INP_GPIO(pin); /* set mode to GPIO input first */ SET_GPIO_ALT(pin, 0); /* set mode to ALT 0 */ } iounmap(gpio); #undef INP_GPIO #undef SET_GPIO_ALT }
// init hardware void initHardware() { // mmap register space setupRegisterMemoryMappings(); // set PWM alternate function for GPIO18 SET_GPIO_ALT(12, 0); // stop clock and waiting for busy flag doesn't work, so kill clock *(clk + PWMCLK_CNTL) = 0x5A000000 | (1 << 5); usleep(10); // set frequency // DIVI is the integer part of the divisor // the fractional part (DIVF) drops clock cycles to get the output frequency, bad for servo motors // 320 bits for one cycle of 20 milliseconds = 62.5 us per bit = 16 kHz int idiv = (int) (19200000.0f / 16000.0f); if (idiv < 1 || idiv > 0x1000) { printf("idiv out of range: %x\n", idiv); exit(-1); } *(clk + PWMCLK_DIV) = 0x5A000000 | (idiv<<12); // source=osc and enable clock *(clk + PWMCLK_CNTL) = 0x5A000011; // disable PWM *(pwm + PWM_CTL) = 0; // needs some time until the PWM module gets disabled, without the delay the PWM module crashs usleep(10); // filled with 0 for 20 milliseconds = 320 bits *(pwm + PWM_RNG1) = 320; // 32 bits = 2 milliseconds, init with 1 millisecond setServo(0); // start PWM1 in serializer mode *(pwm + PWM_CTL) = 3; }
void domex_setup(void) { //int rep; signal(SIGINT, sig_handler); signal(SIGALRM, sig_handler); // Set up gpi pointer for direct register access setup_io(); // GPIO23 - NTX2 enable INP_GPIO(23); // must use INP_GPIO before we can use OUT_GPIO OUT_GPIO(23); // GPIO40 and GPIO45 are audio and also support PWM Connect to analogue audio circitury via R21 and R27 // GPIO18 - NTX2 Data // Set GPIO18 to PWM Function INP_GPIO(18); // must use INP_GPIO before we can use OUT_GPIO or SET_GPIO_ALT //OUT_GPIO(18); // For BitBang SET_GPIO_ALT(18, 5); // For PWM delayMicrosecs(110); SetupPWM(); /* // Setup timer struct itimerval new,old; new.it_interval.tv_usec = 0; new.it_interval.tv_sec = 0; new.it_value.tv_usec = 10; new.it_value.tv_sec = 0; setitimer (ITIMER_REAL, &new, &old); */ }
int32_t audio_init(void) { buf = new_ringbuffer(256); // Set up the pwm clock // vals read from raspbian: // PWMCLK_CNTL = 148 = 10010100 - 100 is allegedly 'plla' but I can't make that work // PWMCLK_DIV = 16384 // PWM_CONTROL=9509 = 10010100100101 // PWM0_RANGE=1024 // PWM1_RANGE=1024 uint32_t range = 0x400; uint32_t idiv = 12; SET_GPIO_ALT(40, 0); // set pins 40/45 (aka phone jack) to pwm function SET_GPIO_ALT(45, 0); usleep(10); // I don't know if all these usleeps are really necessary PUT32(CLOCK_BASE + 4*BCM2835_PWMCLK_CNTL, PM_PASSWORD | BCM2835_PWMCLK_CNTL_KILL); PUT32(PWM_BASE + 4*BCM2835_PWM_CONTROL, 0); // In theory this should be divided by 2 again for the two channels, but // that seems to lead to the wrong rate. TODO: investigate uint32_t samplerate = 500000000.0 / idiv / range; PUT32(CLOCK_BASE + 4*BCM2835_PWMCLK_DIV, PM_PASSWORD | (idiv<<12)); PUT32(CLOCK_BASE + 4*BCM2835_PWMCLK_CNTL, PM_PASSWORD | BCM2835_PWMCLK_CNTL_ENABLE | BCM2835_PWMCLK_CNTL_PLLD); usleep(1); PUT32(PWM_BASE + 4*BCM2835_PWM0_RANGE, range); PUT32(PWM_BASE + 4*BCM2835_PWM1_RANGE, range); usleep(1); buf->dma_cb->info = BCM2708_DMA_S_INC | BCM2708_DMA_WAIT_RESP | BCM2708_DMA_D_DREQ | BCM2708_DMA_PER_MAP(5); buf->dma_cb->src = (uint32_t)(buf->buffer); buf->dma_cb->dst = ((PWM_BASE+4*BCM2835_PWM_FIFO) & 0x00ffffff) | 0x7e000000; // physical address of fifo buf->dma_cb->length = sizeof(uint32_t) * buf->buffer_sz; buf->dma_cb->next = (uint32_t)buf->dma_cb; usleep(1); PUT32(PWM_BASE + 4*BCM2835_PWM_DMAC, PWMDMAC_ENAB | PWMDMAC_THRSHLD); usleep(1); PUT32(PWM_BASE + 4*BCM2835_PWM_CONTROL, PWMCTL_CLRF); usleep(1); PUT32(PWM_BASE + 4*BCM2835_PWM_CONTROL, BCM2835_PWM1_USEFIFO | // BCM2835_PWM1_REPEATFF | BCM2835_PWM1_ENABLE | BCM2835_PWM0_USEFIFO | // BCM2835_PWM0_REPEATFF | BCM2835_PWM0_ENABLE | 1<<6); PUT32(DMA5_CNTL_BASE + BCM2708_DMA_CS, BCM2708_DMA_RESET); usleep(10); PUT32(DMA5_CNTL_BASE + BCM2708_DMA_CS, BCM2708_DMA_INT | BCM2708_DMA_END); PUT32(DMA5_CNTL_BASE + BCM2708_DMA_ADDR, (uint32_t)buf->dma_cb); PUT32(DMA5_CNTL_BASE + BCM2708_DMA_DEBUG, 7); // clear debug error flags usleep(10); PUT32(DMA5_CNTL_BASE + BCM2708_DMA_CS, 0x10880001); // go, mid priority, wait for outstanding writes // printf("audio init done\r\n"); usleep(1); return samplerate; }
void intHandler(int dummy) { GPIO_CLR = 1 << 7; // turn it off SET_GPIO_ALT(18, 0); GPIO_CLR = 1 << 18; exit(1); }
modbus_t* modbus_new_rtu(const char *device, int baud, char parity, int data_bit, int stop_bit) { modbus_t *ctx; modbus_rtu_t *ctx_rtu; /* Check device argument */ if (device == NULL || (*device) == 0) { fprintf(stderr, "The device string is empty\n"); errno = EINVAL; return NULL; } /* Check baud argument */ if (baud == 0) { fprintf(stderr, "The baud rate value must not be zero\n"); errno = EINVAL; return NULL; } /* Prepare GPIO on Raspberry Pi */ if (rpi_setup_gpio() == -1) { fprintf(stderr, "GPIO ERROR: %s", rpi_gpio_error); return NULL; } /* Configure GPIO17 (p1-11),and GPIO24 (p1-18) as OUT */ /*INP_GPIO(17); OUT_GPIO(17);*/ INP_GPIO(24); OUT_GPIO(24); /* Configure GPIO pin 11 (GPIO17) as ALT function 3 (RTS) */ INP_GPIO(17); SET_GPIO_ALT(17, 3); ctx = (modbus_t *) malloc(sizeof(modbus_t)); _modbus_init_common(ctx); ctx->backend = &_modbus_rtu_backend; ctx->backend_data = (modbus_rtu_t *) malloc(sizeof(modbus_rtu_t)); ctx_rtu = (modbus_rtu_t *)ctx->backend_data; ctx_rtu->device = NULL; /* Device name and \0 */ ctx_rtu->device = (char *) malloc((strlen(device) + 1) * sizeof(char)); strcpy(ctx_rtu->device, device); ctx_rtu->baud = baud; if (parity == 'N' || parity == 'E' || parity == 'O') { ctx_rtu->parity = parity; } else { modbus_free(ctx); errno = EINVAL; return NULL; } ctx_rtu->data_bit = data_bit; ctx_rtu->stop_bit = stop_bit; #if HAVE_DECL_TIOCSRS485 /* The RS232 mode has been set by default */ ctx_rtu->serial_mode = MODBUS_RTU_RS232; #endif #if HAVE_DECL_TIOCM_RTS /* The RTS use has been set by default */ ctx_rtu->rts = MODBUS_RTU_RTS_NONE; /* Calculate estimated time in micro second to send one byte */ ctx_rtu->onebyte_time = (1000 * 1000) * (1 + data_bit + (parity == 'N' ? 0 : 1) + stop_bit) / baud; #endif ctx_rtu->confirmation_to_ignore = FALSE; return ctx; }
void QGpio::setAlt (int bit, int func) { SET_GPIO_ALT (bit,func); }