/* Receive data using DMA. */ void rx_spi(void *data, uint16_t size){ if(DmaCleanupNeeded)cleanup_dma_spi(); /* This byte is sent continuously when rx_spi() receives data. */ static const uint8_t RxSpiDummyByte = 0x00; spi_enable_rx_dma(SPI3); dma_channel_reset(DMA1, DMA_CHANNEL2); dma_disable_channel(DMA1, DMA_CHANNEL2); dma_set_peripheral_address(DMA1, DMA_CHANNEL2, (uint32_t) &(SPI_DR(SPI3))); dma_set_memory_address(DMA1, DMA_CHANNEL2, (uint32_t) data); dma_set_number_of_data(DMA1, DMA_CHANNEL2, size); dma_set_priority(DMA1, DMA_CHANNEL2, DMA_CCR_PL_HIGH); dma_set_memory_size(DMA1, DMA_CHANNEL2, DMA_CCR_MSIZE_8BIT); dma_set_peripheral_size(DMA1, DMA_CHANNEL2, DMA_CCR_PSIZE_8BIT); dma_enable_memory_increment_mode(DMA1, DMA_CHANNEL2); dma_disable_peripheral_increment_mode(DMA1, DMA_CHANNEL2); dma_set_read_from_peripheral(DMA1, DMA_CHANNEL2); dma_enable_channel(DMA1, DMA_CHANNEL2); /* The SPI peripheral is driven by transmitted bytes, so dummy bytes * must be sent in order to receive data. This is accomplished with DMA * by simply not incrementing the memory address. */ dma_channel_reset(DMA1, DMA_CHANNEL3); dma_disable_channel(DMA1, DMA_CHANNEL3); dma_set_peripheral_address(DMA1, DMA_CHANNEL3, (uint32_t) &(SPI_DR(SPI3))); dma_set_memory_address(DMA1, DMA_CHANNEL3, (uint32_t) &RxSpiDummyByte); dma_set_number_of_data(DMA1, DMA_CHANNEL3, size); dma_set_priority(DMA1, DMA_CHANNEL3, DMA_CCR_PL_HIGH); dma_set_memory_size(DMA1, DMA_CHANNEL3, DMA_CCR_MSIZE_8BIT); dma_set_peripheral_size(DMA1, DMA_CHANNEL3, DMA_CCR_PSIZE_8BIT); dma_disable_memory_increment_mode(DMA1, DMA_CHANNEL3); dma_disable_peripheral_increment_mode(DMA1, DMA_CHANNEL3); dma_set_read_from_memory(DMA1, DMA_CHANNEL3); dma_enable_channel(DMA1, DMA_CHANNEL3); spi_enable_tx_dma(SPI3); spi_enable(SPI3); DmaCleanupNeeded = true; }
/* Simultaneously transmit and receive data using DMA. */ void rxtx_spi(void *rxdata, const void *txdata, uint16_t size){ if(DmaCleanupNeeded)cleanup_dma_spi(); spi_enable_rx_dma(SPI3); dma_channel_reset(DMA1, DMA_CHANNEL2); dma_disable_channel(DMA1, DMA_CHANNEL2); dma_set_peripheral_address(DMA1, DMA_CHANNEL2, (uint32_t) &(SPI_DR(SPI3))); dma_set_memory_address(DMA1, DMA_CHANNEL2, (uint32_t) rxdata); dma_set_number_of_data(DMA1, DMA_CHANNEL2, size); dma_set_priority(DMA1, DMA_CHANNEL2, DMA_CCR_PL_HIGH); dma_set_memory_size(DMA1, DMA_CHANNEL2, DMA_CCR_MSIZE_8BIT); dma_set_peripheral_size(DMA1, DMA_CHANNEL2, DMA_CCR_PSIZE_8BIT); dma_enable_memory_increment_mode(DMA1, DMA_CHANNEL2); dma_disable_peripheral_increment_mode(DMA1, DMA_CHANNEL2); dma_set_read_from_peripheral(DMA1, DMA_CHANNEL2); dma_enable_channel(DMA1, DMA_CHANNEL2); dma_channel_reset(DMA1, DMA_CHANNEL3); dma_disable_channel(DMA1, DMA_CHANNEL3); dma_set_peripheral_address(DMA1, DMA_CHANNEL3, (uint32_t) &(SPI_DR(SPI3))); dma_set_memory_address(DMA1, DMA_CHANNEL3, (uint32_t) txdata); dma_set_number_of_data(DMA1, DMA_CHANNEL3, size); dma_set_priority(DMA1, DMA_CHANNEL3, DMA_CCR_PL_HIGH); dma_set_memory_size(DMA1, DMA_CHANNEL3, DMA_CCR_MSIZE_8BIT); dma_set_peripheral_size(DMA1, DMA_CHANNEL3, DMA_CCR_PSIZE_8BIT); dma_enable_memory_increment_mode(DMA1, DMA_CHANNEL3); dma_disable_peripheral_increment_mode(DMA1, DMA_CHANNEL3); dma_set_read_from_memory(DMA1, DMA_CHANNEL3); dma_enable_channel(DMA1, DMA_CHANNEL3); spi_enable_tx_dma(SPI3); spi_enable(SPI3); DmaCleanupNeeded = true; }
void dma_transmit_setup(void) { dma_channel_reset(DMA1, DMA_CHANNEL4); nvic_enable_irq(NVIC_DMA1_CHANNEL4_5_IRQ); dma_set_peripheral_address(DMA1, DMA_CHANNEL4, (uint32_t) &USART2_TDR); dma_set_read_from_memory(DMA1, DMA_CHANNEL4); dma_set_peripheral_size(DMA1, DMA_CHANNEL4, DMA_CCR_PSIZE_8BIT); dma_set_memory_size(DMA1, DMA_CHANNEL4, DMA_CCR_MSIZE_8BIT); dma_set_priority(DMA1, DMA_CHANNEL4, DMA_CCR_PL_VERY_HIGH); dma_disable_peripheral_increment_mode(DMA1, DMA_CHANNEL4); dma_enable_memory_increment_mode(DMA1, DMA_CHANNEL4); dma_disable_transfer_error_interrupt(DMA1, DMA_CHANNEL4); dma_disable_half_transfer_interrupt(DMA1, DMA_CHANNEL4); dma_enable_transfer_complete_interrupt(DMA1, DMA_CHANNEL4); }
void ws2812_init( void ) { uint32_t i,j; for( i = 0; i < WS2812_BUFFERSIZE; i++ ) { bitframe_pattern[i] = 0; bitframe_pattern_draw[i] = 0; } for( i=0; i < (3*NR_OF_LEDS_PER_CH*NR_OF_ROWS); i++) { frame_pattern[i] = 0; } /* configure the GPIOs */ /* Enable GPIOC clock */ rcc_periph_clock_enable(RCC_GPIOB); /* Setup GPIO pin GPIO8/9 on GPIO port C for LEDs. */ gpio_mode_setup(GPIOB, GPIO_MODE_OUTPUT, GPIO_PUPD_PULLDOWN, GPIO0); gpio_set_output_options( GPIOB, GPIO_OTYPE_PP, GPIO_OSPEED_HIGH, GPIO0); /* configure the DMA */ rcc_periph_clock_enable(RCC_DMA); /* configure DMA for sending high constant pattern to port on begin of cycle * send unrolled bitframe on Timer OC1 event * send low on Timer OC3 event */ dma_channel_reset( DMA1, DMA_CHANNEL3); dma_set_peripheral_address( DMA1, DMA_CHANNEL3, (uint32_t)&GPIOB_ODR); dma_set_memory_address( DMA1, DMA_CHANNEL3, (uint32_t)&high_pattern); dma_set_peripheral_size( DMA1, DMA_CHANNEL3, DMA_CCR_PSIZE_8BIT); dma_set_memory_size( DMA1, DMA_CHANNEL3, DMA_CCR_MSIZE_8BIT); dma_disable_peripheral_increment_mode( DMA1, DMA_CHANNEL3 ); dma_disable_memory_increment_mode( DMA1, DMA_CHANNEL3 ); dma_set_priority( DMA1, DMA_CHANNEL3, DMA_CCR_PL_HIGH); dma_set_read_from_memory(DMA1, DMA_CHANNEL3); dma_channel_reset( DMA1, DMA_CHANNEL4); dma_set_peripheral_address( DMA1, DMA_CHANNEL4, (uint32_t)&GPIOB_ODR); dma_set_memory_address( DMA1, DMA_CHANNEL4, (uint32_t)actual_bitframe); dma_set_peripheral_size( DMA1, DMA_CHANNEL4, DMA_CCR_PSIZE_8BIT); dma_set_memory_size( DMA1, DMA_CHANNEL4, DMA_CCR_MSIZE_8BIT); dma_disable_peripheral_increment_mode( DMA1, DMA_CHANNEL4 ); dma_enable_memory_increment_mode( DMA1, DMA_CHANNEL4 ); dma_set_priority( DMA1, DMA_CHANNEL4, DMA_CCR_PL_HIGH); dma_set_read_from_memory(DMA1, DMA_CHANNEL4); dma_channel_reset( DMA1, DMA_CHANNEL2); dma_set_peripheral_address( DMA1, DMA_CHANNEL2, (uint32_t)&GPIOB_ODR); dma_set_memory_address( DMA1, DMA_CHANNEL2, (uint32_t)&low_pattern); dma_set_peripheral_size( DMA1, DMA_CHANNEL2, DMA_CCR_PSIZE_8BIT); dma_set_memory_size( DMA1, DMA_CHANNEL2, DMA_CCR_MSIZE_8BIT); dma_disable_peripheral_increment_mode( DMA1, DMA_CHANNEL2 ); dma_disable_memory_increment_mode( DMA1, DMA_CHANNEL2 ); dma_set_priority( DMA1, DMA_CHANNEL2, DMA_CCR_PL_HIGH); dma_set_read_from_memory(DMA1, DMA_CHANNEL2); nvic_set_priority(NVIC_DMA1_CHANNEL2_3_IRQ, 0); nvic_enable_irq(NVIC_DMA1_CHANNEL2_3_IRQ); dma_enable_transfer_complete_interrupt( DMA1, DMA_CHANNEL2); /* configure timer */ rcc_periph_clock_enable(RCC_TIM3); /* configure the timer for 800kHz overall frequency */ timer_reset( TIM3 ); timer_set_mode( TIM3, TIM_CR1_CKD_CK_INT, TIM_CR1_CMS_EDGE, TIM_CR1_DIR_UP); timer_set_period( TIM3, 60); timer_set_repetition_counter( TIM3, 0); timer_disable_preload( TIM3 ); /* timer compare section 1 for low coding */ timer_set_oc_mode( TIM3, TIM_OC1,TIM_OCM_FROZEN); timer_set_oc_value( TIM3, TIM_OC1, 19); timer_disable_oc_preload( TIM3, TIM_OC1); /* timer compare section 3 for high coding */ timer_set_oc_mode( TIM3, TIM_OC3,TIM_OCM_FROZEN); timer_set_oc_value( TIM3, TIM_OC3, 41); timer_disable_oc_preload( TIM3, TIM_OC3); nvic_set_priority( NVIC_TIM3_IRQ,1); nvic_set_priority( NVIC_PENDSV_IRQ, 2); nvic_enable_irq(NVIC_TIM3_IRQ); nvic_enable_irq(NVIC_PENDSV_IRQ); /* start the sending process */ ws2812_send(); }
static void setup_i2c_port(enum I2C_FREQ I2C_speed) { // Disable I2C if it happens to be enabled i2c_peripheral_disable(I2C_PORT); dma_channel_reset(I2C_TX_DMA, I2C_TX_DMA_CHANNEL); i2c_disable_interrupt(I2C_PORT, (I2C_CR2_ITEVTEN | I2C_CR2_ITERREN)); DISABLE_I2C_INTERRUPT(); reset_i2c_pins(); // set: Source, Destination, and Amount (DMA channel must be disabled) dma_set_peripheral_address(I2C_TX_DMA, I2C_TX_DMA_CHANNEL, (uint32_t)&I2C_DR(I2C_PORT)); dma_set_memory_address(I2C_TX_DMA, I2C_TX_DMA_CHANNEL, 0); dma_set_number_of_data(I2C_TX_DMA, I2C_TX_DMA_CHANNEL, 0); // set the DMA Configuration (DMA_CCRx) // (BIT 14) mem2mem_mode disabled dma_set_priority(I2C_TX_DMA, I2C_TX_DMA_CHANNEL, DMA_CCR_PL_HIGH); // (BIT 12:13) dma_set_memory_size(I2C_TX_DMA, I2C_TX_DMA_CHANNEL, DMA_CCR_MSIZE_8BIT); // (BIT 10:11) dma_set_peripheral_size(I2C_TX_DMA, I2C_TX_DMA_CHANNEL, DMA_CCR_PSIZE_8BIT); // (BIT 8:9) dma_enable_memory_increment_mode(I2C_TX_DMA, I2C_TX_DMA_CHANNEL); // (BIT 7) dma_disable_peripheral_increment_mode(I2C_TX_DMA, I2C_TX_DMA_CHANNEL); // (BIT 6) // (BIT 5) Circular mode is disabled dma_set_read_from_memory(I2C_TX_DMA, I2C_TX_DMA_CHANNEL); // (BIT 4) dma_enable_transfer_error_interrupt(I2C_TX_DMA, I2C_TX_DMA_CHANNEL); // (BIT 3) dma_disable_half_transfer_interrupt(I2C_TX_DMA, I2C_TX_DMA_CHANNEL); // (BIT 2) dma_enable_transfer_complete_interrupt(I2C_TX_DMA, I2C_TX_DMA_CHANNEL); // (BIT 1) // This is the slave address when not transmitting data i2c_set_own_7bit_slave_address(I2C_PORT, 0x32); // do not respond to the specified slave address i2c_disable_ack(I2C_PORT); // Use DMA to send I2C data i2c_enable_dma(I2C_PORT); // set which interrupts I2C uses i2c_enable_interrupt(I2C_PORT, (I2C_CR2_ITEVTEN | I2C_CR2_ITERREN)); // APB1 is running at 36MHz = T(PCLK1) = 1/36000000 sec. i2c_set_clock_frequency(I2C_PORT, I2C_CR2_FREQ_36MHZ); // Set up the hardware for the particular speed switch (I2C_speed) { // Values found on Internet for the I2C standard // STANDARD : SCL max rise time = 1000ns = 1000/1000000000 sec // FAST : SCL max rise time = 300ns = 300/1000000000 sec // // DATASHEET Function: // TRISE = (T(MAX_SCL_RISE) / T(PCLK1)) + 1 // // DATASHEET Functions: // STANDARD : // T(high) = CCR * T(PCLK1) // T(low) = CCR * T(PCLK1) // FAST (DUTY=I2C_CCR_DUTY_DIV2) // T(high) = CCR * T(PCLK1) // T(low) = 2 * CCR * T(PCLK1) // FAST (DUTY=I2C_CCR_DUTY_16_DIV_9) [To reach 400KHz] // T(high) = 9 * CCR * T(PCLK1) // T(low) = 16 * CCR * T(PCLK1) // // I2C PERIOD: // STANDARD // PERIOD = T(high) + T(low) = (2 * CCR * T(PCLK1)) // FAST (DUTY=I2C_CCR_DUTY_DIV2) // PERIOD = T(high) + T(low) = (3 * CCR * T(PCLK1)) // FAST (DUTY=I2C_CCR_DUTY_16_DIV_9) // PERIOD = T(high) + T(low) = (25 * CCR * T(PCLK1)) case I2C_400KHz: // I2C PERIOD: 400KHz = 400000Hz = 1/400000 sec. i2c_set_fast_mode(I2C_PORT); // I2C_CCR_DUTY_DIV2 or I2C_CCR_DUTY_16_DIV_9 i2c_set_dutycycle(I2C_PORT, I2C_CCR_DUTY_16_DIV_9); // CCR = PERIOD / (25 * T(PCLK1)) // CCR = (1/400000) / (25/36000000) = 18/5 = 3.6 // CCR = 4 => I2C PERIOD = 360kHz // CCR = 3 => I2C PERIOD = 480kHz i2c_set_ccr(I2C_PORT, 4); // Only fast mode can have a value less than 0x04 // TRISE = ( (300/1000000000) / (1/36000000) ) + 1 = 59/5 = 11.8 // TRISE = 12 => SCL max rise time ~= 305.555ns // TRISE = 11 => SCL max rise time ~= 277.777ns i2c_set_trise(I2C_PORT, 11); break; case I2C_100KHz: // I2C PERIOD: 100KHz = 100000Hz = 1/100000 sec. i2c_set_standard_mode(I2C_PORT); // I2C_CCR_DUTY_DIV2 or I2C_CCR_DUTY_16_DIV_9 i2c_set_dutycycle(I2C_PORT, I2C_CCR_DUTY_DIV2); // CCR = PERIOD / (2 * T(PCLK1)) // CCR = (1/100000) / (2/36000000) = 180 i2c_set_ccr(I2C_PORT, 180); // TRISE = ( (1000/1000000000) / (1/36000000) ) + 1 = 37 i2c_set_trise(I2C_PORT, 37); break; case I2C_53KHz: // ~= 52.91kHz is the slowest I could get to work // CCR value of 341 works but not 342 or higher case I2C_50KHz: default: // I2C PERIOD: 50KHz = 50000Hz = 1/50000 sec. i2c_set_standard_mode(I2C_PORT); // I2C_CCR_DUTY_DIV2 or I2C_CCR_DUTY_16_DIV_9 i2c_set_dutycycle(I2C_PORT, I2C_CCR_DUTY_DIV2); // CCR = PERIOD / (2 * T(PCLK1)) // CCR = (1/50000) / (2/36000000) = 360 // (341 works but not 342 or higher) i2c_set_ccr(I2C_PORT, 341); // TRISE = ( (1000/1000000000) / (1/36000000) ) + 1 = 37 i2c_set_trise(I2C_PORT, 37); break; } i2c_peripheral_enable(I2C_PORT); // set the priorities for the interrupts nvic_set_priority(I2C_EV_IRQ, IRQ_PRI_I2C); nvic_set_priority(I2C_ER_IRQ, IRQ_PRI_ER_I2C); nvic_set_priority(I2C_DMA_IRQ, IRQ_PRI_DMA_I2C); }