/** * \brief Configure output parameters of a group of pins * * Sets the output configuration and drive strength, of or a set of GPIO pins * for a set of GPIO pins in output mode. * * @param[in] gpioport GPIO block register address base @ref gpio_reg_base * @param[in] otype Output driver configuration (@ref gpio_output_type) \n * - GPIO_OTYPE_PP -- Configure pin driver as push-pull \n * - GPIO_OTYPE_OD -- Configure pin driver as open drain * @param[in] drive Pin drive strength (@ref gpio_drive_strength) \n * - GPIO_DRIVE_2MA -- 2mA drive \n * - GPIO_DRIVE_4MA -- 4mA drive \n * - GPIO_DRIVE_8MA -- 8mA drive \n * - GPIO_DRIVE_8MA_SLEW_CTL -- 8mA drive with slew rate * control * @param[in] gpios @ref gpio_pin_id. Any combination of pins may be specified * by OR'ing then together */ void gpio_set_output_config(uint32_t gpioport, enum gpio_output_type otype, enum gpio_drive_strength drive, uint8_t gpios) { if (otype == GPIO_OTYPE_OD) { GPIO_ODR(gpioport) |= gpios; } else { GPIO_ODR(gpioport) &= ~gpios; } /* * Setting a bit in the GPIO_DRxR register clears the corresponding bit * in the other GPIO_DRyR registers, and vice-versa. */ switch (drive) { case GPIO_DRIVE_8MA_SLEW_CTL: GPIO_DR8R(gpioport) |= gpios; GPIO_SLR(gpioport) |= gpios; break; case GPIO_DRIVE_8MA: GPIO_DR8R(gpioport) |= gpios; GPIO_SLR(gpioport) &= ~gpios; break; case GPIO_DRIVE_4MA: GPIO_DR4R(gpioport) |= gpios; break; case GPIO_DRIVE_2MA: /* Fall through */ default: GPIO_DR2R(gpioport) |= gpios; break; } }
void leds_arch_set(unsigned char leds) { u32 reg = GPIO_ODR(LED_DISCO_PORT); reg &= ~(LED_DISCO_PIN_GREEN | LED_DISCO_PIN_BLUE); if (leds & LEDS_GREEN) { reg |= LED_DISCO_PIN_GREEN; } if (leds & LEDS_BLUE) { reg |= LED_DISCO_PIN_BLUE; } GPIO_ODR(LED_DISCO_PORT) = reg; }
/** * Test end-switches & * @param num - motor number * @param curpos - end-switches data for motor * @return 0 if we can move further, 1 if there's the end */ uint8_t test_stages_endpos(uint8_t num, uint8_t curpos){ if(curpos == 0 || num < 3) return 0; // end-switches numbers for stages const uint8_t stage_plus[2] = {STAGE_CHECK(3, PLUS), STAGE_CHECK(4, PLUS)}; const uint8_t stage_minus[2] = {STAGE_CHECK(3, MINUS), STAGE_CHECK(4, MINUS)}; uint8_t negative_dir = 0; if((uint16_t)(GPIO_ODR(MOTOR_DIR_PORT) & MOTOR_DIR_PIN(num))){ // negative direction negative_dir = 1; } num -= 3; // convern num to index in arrays if(stage_plus[num] == curpos){ // we are on "+" end-switch if(!negative_dir){ // and wanna move to "+" ERR("End-switch +\n"); return 1; } }else if(stage_minus[num] == curpos){ // we are on "-" end-switch if(negative_dir){ // and wanna move to "-" ERR("End-switch -\n"); return 1; } }else{ // error: WTF is going up? curpos != 2 or 1 ERR("Wrong current position: "); if(mode == BYTE_MODE){ print_int(curpos, lastsendfun); lastsendfun('\n'); } return 1; } return 0; }
void jack_setup(const struct jack_t *jack, volatile struct jacks_machine_t *machine) { // turn on gpios and modes for the pins... gpio_set_mode(jack->en_port, GPIO_MODE_INPUT, GPIO_CNF_INPUT_FLOAT, jack->en_pin); // Explictly pull down. This burns ~66uA per jack! // FIXME - make sure this all works properly! GPIO_ODR(jack->en_port) &= ~(jack->en_pin); gpio_set_mode(jack->power_port, GPIO_MODE_OUTPUT_2_MHZ, GPIO_CNF_OUTPUT_PUSHPULL, jack->power_pin); gpio_set_mode(jack->val_port, GPIO_MODE_INPUT, GPIO_CNF_INPUT_ANALOG, jack->val_pin); machine->step = jack_machine_step_off; machine->last_read_millis = 0; machine->step_entry_millis = 0; machine->jack = jack; }
int main(void){ uint8_t *string; // string from UART2 & pointer to last full GPS answer uint8_t lastGPSans[UART_BUF_DATA_SIZE] = {0}; int i; rcc_clock_setup_in_hse_8mhz_out_72mhz(); // init systick (1ms) systick_set_clocksource(STK_CSR_CLKSOURCE_AHB_DIV8); // Systyck: 72/8=9MHz systick_set_reload(STK_RVR_DEFAULT_VAL); // 9000 pulses: 1kHz systick_interrupt_enable(); systick_counter_enable(); GPIO_init(); /* // if PC11 connected to usb 1.5kOhm pull-up through transistor rcc_periph_clock_enable(RCC_GPIOC); gpio_set(GPIOC, GPIO11); gpio_set_mode(GPIOC, GPIO_MODE_OUTPUT_2_MHZ, GPIO_CNF_OUTPUT_PUSHPULL, GPIO11); */ usb_disconnect(); // turn off USB while initializing all usbkeybrd_setup(); UART_init(USART2); // init GPS UART #ifdef ULTRASONIC tim2_init(); // ultrasonic timer #endif //tim4_init(); // beeper timer /* for (i = 0; i < 0x80000; i++) __asm__("nop"); */ usb_connect(); // turn on USB GPS_send_start_seq(); init_adc_sensor(); // time (in milliseconds from MCU start) for trigger, adc & power LED status; power LED blink interval // blink time: (1000ms - powerLEDblink) - LED ON // GPSstatus_tm - timer for blinking by GPS LED if there's no GPS after timer is good // powerLEDblink - LED blinking time (depends on power level) uint32_t usbkbrdtm = 0, trigrtm = 0, powerLEDtm = 0, GPSstatus_tm = 0, powerLEDblink = 1; // istriggered == 1 after ANY trigger's event (set it to 1 at start to prevent false events) // GPSLEDblink - GPS LED blinking uint8_t istriggered = 1, GPSLEDblink = 0; iwdg_set_period_ms(50); // set watchdog timeout to 50ms iwdg_start(); while(1){ if(Timer == 500) // turn off PPS LED after 500ms gpio_set(LEDS_Y_PORT, LEDS_Y2_PIN); poll_usbkeybrd(); if(usbkbrdtm != msctr){ // process USB not frequently than once per 1ms process_usbkbrd(); usbkbrdtm = msctr; } #ifdef ULTRASONIC poll_ultrasonic(); #endif poll_ADC(); if((string = check_UART2())){ memcpy(lastGPSans, string, UART_BUF_DATA_SIZE); GPS_parse_answer(string); } /* if(msctr - trigrtm > 3000){ trigrtm = msctr; for(i = 0; i < 3; ++i){ // IR or Laser P("ADC"); put_char_to_buf('0' + i); P(" val: "); print_int(ADC_value[i]); newline(); } }*/ if(istriggered){ // there was any trigger event if(msctr - trigrtm > TRIGGER_DELAY || trigrtm > msctr){ // turn off LED & beeper istriggered = 0; gpio_set(LEDS_Y_PORT, LEDS_Y1_PIN); gpio_set(BEEPER_PORT, BEEPER_PIN); trigger_ms = DIDNT_TRIGGERED; adc_ms[0] = DIDNT_TRIGGERED; adc_ms[1] = DIDNT_TRIGGERED; #ifdef ULTRASONIC ultrasonic_ms = DIDNT_TRIGGERED; #endif } }else{ if(trigger_ms != DIDNT_TRIGGERED){ // Control Button pressed trigrtm = msctr; istriggered = 1; P("Button time: "); print_time(&trigger_time, trigger_ms); if(*lastGPSans){ P("GPS last message: "); send_msg((char*)lastGPSans); newline(); } } for(i = 0; i < 2; ++i){ // IR or Laser uint32_t adcms = adc_ms[i]; if(adcms == DIDNT_TRIGGERED) continue; int32_t timediff = Timer - adcms; if(timediff < 0) timediff += 1000; // pause for noice removal if(timediff > ADC_NOICE_TIMEOUT && !istriggered){ trigrtm = msctr; istriggered = 1; if(i == 0) P("Infrared"); else P("Laser"); /* P(" trig val: "); print_int(ADC_trig_val[i]);*/ put_char_to_buf(' '); //P(" time: "); print_time(&adc_time[i], adcms); } } #ifdef ULTRASONIC if(ultrasonic_ms != DIDNT_TRIGGERED && !istriggered){ trigrtm = msctr; istriggered = 1; P("Ultrasonic time: "); print_time(&ultrasonic_time, ultrasonic_ms); } #endif if(istriggered){ // turn on Y1 LED gpio_clear(LEDS_Y_PORT, LEDS_Y1_PIN); //beep(); // turn on beeper gpio_clear(BEEPER_PORT, BEEPER_PIN); } } // check 12V power level (once per 1ms) if(powerLEDtm != msctr){ uint16_t _12V = ADC_value[2]; if(_12V < GOOD_POWER_LEVEL){ // insufficient power? - blink LED R2 // calculate blink time only if there's [was] too low level if(_12V < POWER_ALRM_LEVEL || powerLEDblink){ powerLEDblink = GOOD_POWER_LEVEL - _12V; // critical level: power LED is almost OFF if(_12V < POWER_CRITICAL_LEVEL) powerLEDblink = 990; //if(powerLEDblink > 990) powerLEDblink = 990; // shadow LED not more than 0.99s } }else{ // power restored - LED R2 shines if(powerLEDblink){ gpio_clear(LEDS_R_PORT, LEDS_R2_PIN); powerLEDblink = 0; } powerLEDtm = msctr; } if(powerLEDblink){ if(GPIO_ODR(LEDS_R_PORT) & LEDS_R2_PIN){ // LED is OFF if(msctr - powerLEDtm > powerLEDblink || msctr < powerLEDtm){ // turn LED ON powerLEDtm = msctr; gpio_clear(LEDS_R_PORT, LEDS_R2_PIN); } }else{ if(msctr - powerLEDtm > (1000 - powerLEDblink) || msctr < powerLEDtm){ // turn LED OFF powerLEDtm = msctr; gpio_set(LEDS_R_PORT, LEDS_R2_PIN); } } } } // check GPS status to turn on/off GPS LED if(current_time.H < 24){ // timer OK if((GPS_status != GPS_VALID) || need_sync){ GPSLEDblink = 1; }else{ GPSLEDblink = 0; if((GPIO_ODR(LEDS_G_PORT) & LEDS_G1_PIN) == 0) gpio_clear(LEDS_G_PORT, LEDS_G1_PIN); // turn ON G1 LED } if(GPSLEDblink){ if(msctr - GPSstatus_tm > 500 || msctr < GPSstatus_tm){ GPSstatus_tm = msctr; if(GPIO_ODR(LEDS_G_PORT) & LEDS_G1_PIN){ // LED is OFF gpio_clear(LEDS_G_PORT, LEDS_G1_PIN); }else{ gpio_set(LEDS_G_PORT, LEDS_G1_PIN); } } } }else{ // something bad with timer - turn OFF G1 LED if(!(GPIO_ODR(LEDS_G_PORT) & LEDS_G1_PIN)){ gpio_set(LEDS_G_PORT, LEDS_G1_PIN); } } iwdg_reset(); // reset watchdog } }
/* On rare occassions, the I2C device will get confused, either because we missed * a timing requirement, or it is just stupid. Regardless, it holds SDA low waiting * for some unknown action from the master. This keeps the bus BUSY and prevents * any further communication. This condition is fixed by manually clocking SCL * until SDA is released by the slave. As far as it is concerned, we just completed * a normal transaction. */ static int i2c_force_clear_busy(struct i2c_dev *i2c) { if (!i2c) { return -1; } int count = 10000; switch (i2c->port) { case 1: /* Set pins to output/input */ gpio_moder(GPIOB, I2C1_SCL, GPIO_MODER_OUT); gpio_moder(GPIOB, I2C1_SDA, GPIO_MODER_IN); /* Toggle clock until bus no longer busy */ while (!(*GPIO_IDR(GPIOB) & GPIO_IDR_PIN(I2C1_SDA))) { if (!count--) { /* Out of time, perhaps the last ditch effort will save us. */ break; } /* Toggle clock */ *GPIO_ODR(GPIOB) ^= GPIO_ODR_PIN(I2C1_SCL); for (volatile int delay = 100; delay > 0; delay--); } gpio_moder(GPIOB, I2C1_SCL, GPIO_MODER_ALT); gpio_moder(GPIOB, I2C1_SDA, GPIO_MODER_ALT); for (volatile int delay = 100; delay > 0; delay--); break; case 2: /* Set pins to output/input */ gpio_moder(GPIOB, I2C2_SCL, GPIO_MODER_OUT); gpio_moder(GPIOB, I2C2_SDA, GPIO_MODER_IN); /* Toggle clock until SDA raised */ while (!(*GPIO_IDR(GPIOB) & GPIO_IDR_PIN(I2C2_SDA))) { if (!count--) { /* Out of time, perhaps the last ditch effort will save us. */ break; } /* Toggle clock */ *GPIO_ODR(GPIOB) ^= GPIO_ODR_PIN(I2C2_SCL); for (volatile int delay = 100; delay > 0; delay--); } gpio_moder(GPIOB, I2C2_SCL, GPIO_MODER_ALT); gpio_moder(GPIOB, I2C2_SDA, GPIO_MODER_ALT); for (volatile int delay = 100; delay > 0; delay--); break; default: return -1; } /* Make sure the peripheral recognizes that the bus is now free */ if (*I2C_SR2(i2c->port) & I2C_SR2_BUSY) { /* Last ditch effort */ if (i2c_reset(i2c) || (*I2C_SR2(i2c->port) & I2C_SR2_BUSY)) { /* Failed to reset */ printk("I2C: BUSY flag failed to clear.\r\nI2C: I have tried everything I know :(. At this point, reset is your best option.\r\n"); return -1; } } return 0; }
/** @brief Write to a Port Write a value to the given GPIO port. @param[in] gpioport Unsigned int32. Port identifier @ref gpio_port_id @param[in] data Unsigned int16. The value to be written to the GPIO port. */ void gpio_port_write(u32 gpioport, u16 data) { GPIO_ODR(gpioport) = data; }
/** @brief Toggle a Group of Pins Toggle one or more pins of the given GPIO port. This is not an atomic operation. @param[in] gpioport Unsigned int32. Port identifier @ref gpio_port_id @param[in] gpios Unsigned int16. Pin identifiers @ref gpio_pin_id If multiple pins are to be changed, use logical OR '|' to separate them. */ void gpio_toggle(u32 gpioport, u16 gpios) { GPIO_ODR(gpioport) ^= gpios; }
void tim2_isr ( void ) { //TIM2_SR &= ~TIM_SR_UIF; //clearing update interrupt flag TIM_SR(TIM2) &= ~TIM_SR_UIF; /* Clear interrrupt flag. */ /* ISR HAS TO DO SOMRTHING A LITTLE HEAVY // https://my.st.com/public/STe2ecommunities/mcu/Lists/cortex_mx_stm32/Flat.aspx?RootFolder=/public/STe2ecommunities/mcu/Lists/cortex_mx_stm32/Problem%20with%20DMA-USART%20Rx%20on%20STM32F407VG&FolderCTID=0x01200200770978C69A1141439FE559EB459D7580009C4E14902C3CDE46A77F0FFD06506F5B¤tviews=148 // ie: after setting SR, you need to pause read/writes // ie: if the ISR is too quick, there may be a spurious re-invocation (tail chain), so you need to do a little something to avoid cpu race condition // -- another way to do it, is to do a SR read (which blocks until its 'set' finishes), thus stalling until the ISR is 'done': //void SPI2_IRQHandler(void) //{ // volatile unsigned int dummy; // ... some code... // SPI2_CR2 &= ~SPI_CR2_RXNEIE; // Turn off RXE interrupt enable // ...some code... // dummy = SPI2_SR; // Prevent tail-chaining. // return; //} */ // VGA line logic // // line1 // line2 // .. // line600 // front porch blank 1 line // vsync pulse 4 lines // back porch blank 23 lines // \__> back to top // // handle vblank stuff // - front porch, leads to // - vsync, leads to // - back porch // vsync is normally HIGH, but goes to LOW during pulse done_sync = 0; if ( front_porch_togo ) { front_porch_togo --; vblank_active(); if ( ! front_porch_togo ) { // on exit front porch, start vsync pulse vsync_go_low(); vsync_togo = 2; } done_sync = 1; goto hsync; //return; // do nothing.. } if ( vsync_togo ) { vsync_togo --; if ( ! vsync_togo ) { // on exit vsync pulse, start back porch vsync_go_high(); back_porch_togo = 33; } done_sync = 1; goto hsync; //return; } if ( back_porch_togo ) { back_porch_togo --; if ( ! back_porch_togo ) { line_count = 1; vblank_inactive(); } done_sync = 1; goto hsync; //return; // do nothing.. } hsync: // hsync period.. // should use timer/interupt to 'end the line' and go hsync? // /* horiz Front Porch */ i = 16; while ( i-- ) { __asm__("nop"); } /* Horizontal Sync pulse (low) */ hsync_go_low(); i = 103; while ( i-- ) { __asm__("nop"); } /* horiz Back Porch */ hsync_go_high(); i = 50; while ( i-- ) { __asm__("nop"); } if ( done_sync ) { return; } // center horizontally; burn some time so image isn't fully on left #ifndef VGA_DMA i = 40; while ( i-- ) { __asm__("nop"); } #endif // actual line data // // line data on/off/on/off.. // off for hsync/porch business! #if RENDER_ATALL // pull from array // center vertically .. dma seems blurry with this so only for non-DMA #if 1 if ( line_count < 40 ) { goto scanline_done; } i = (line_count-40)/2; #else i = (line_count)/2; #endif // done? if ( i >= FBHEIGHT ) { goto scanline_done; } #ifdef VGA_DMA uint8_t *p = fb_active + ( i * FBWIDTH ); dma_memcpy ( p, (unsigned char*) &(GPIO_ODR(GPIOC)) /*&GPIOC->ODR*/, FBWIDTH, DMA_MEMCPY_INCSRC ); scanline_done: #else #define OLD_EMIT_PIXEL() \ GPIO_ODR(GPIOC) = *p++; \ __asm__("nop"); \ __asm__("nop"); \ __asm__("nop"); \ __asm__("nop"); \ __asm__("nop"); \ __asm__("nop"); \ __asm__("nop"); \ __asm__("nop"); \ __asm__("nop"); \ __asm__("nop"); \ __asm__("nop"); // 11 NOP's is pretty ideal unsigned char c; #define EMIT_PIXEL() \ c = *p++; \ GPIO_ODR(GPIOC) = c; \ GPIO_ODR(GPIOC) = c; \ GPIO_ODR(GPIOC) = c; \ GPIO_ODR(GPIOC) = c; \ GPIO_ODR(GPIOC) = c; \ GPIO_ODR(GPIOC) = c; \ GPIO_ODR(GPIOC) = c; \ GPIO_ODR(GPIOC) = c; \ GPIO_ODR(GPIOC) = c; \ GPIO_ODR(GPIOC) = c; \ GPIO_ODR(GPIOC) = c; // paint the image uint8_t *p = fb_active + ( i * FBWIDTH ); i = (FBWIDTH) / 16; while ( i-- ) { EMIT_PIXEL(); EMIT_PIXEL(); EMIT_PIXEL(); EMIT_PIXEL(); EMIT_PIXEL(); EMIT_PIXEL(); EMIT_PIXEL(); EMIT_PIXEL(); // 8 EMIT_PIXEL(); EMIT_PIXEL(); EMIT_PIXEL(); EMIT_PIXEL(); EMIT_PIXEL(); EMIT_PIXEL(); EMIT_PIXEL(); EMIT_PIXEL(); // 8 } // disable all colour pins (dma does it itself in its isr) //GPIO_BSRR(GPIOC) = 0x00; scanline_done: gpio_clear ( GPIOC, GPIO0 | GPIO1 | GPIO2 | GPIO3 | GPIO4 | GPIO5 ); #endif // DMA? #endif // entering vblank period? // if ( line_count > VISIBLE_ROWS ) { front_porch_togo = 10; _vblank_count++; // entering vblank return; // entering front porch } line_count++; }
void gpio_port_write(uint32_t gpioport, uint16_t data) { GPIO_ODR(gpioport) = data; }
void gpio_toggle(uint32_t gpioport, uint16_t gpios) { GPIO_ODR(gpioport) ^= gpios; }
static void cs_low(void) { *GPIO_ODR(GPIOB) &= ~(GPIO_ODR_PIN(0)); }
static void cs_high(void) { *GPIO_ODR(GPIOB) |= GPIO_ODR_PIN(0); }