Răsfoiți Sursa

Slow down hw/sw SPI.

Vladimir N. Shilov 3 ani în urmă
părinte
comite
b1477e6d09
2 a modificat fișierele cu 58 adăugiri și 13 ștergeri
  1. 1 0
      inc/board.h
  2. 57 13
      src/board.c

+ 1 - 0
inc/board.h

@@ -30,6 +30,7 @@ void display_BlinkState(dis_en_t state);
 void display_LedState(dis_en_t state);
 void EXTI4_15_IRQHandler(void);
 void DMA1_Channel2_3_IRQHandler(void);
+void I2C1_IRQHandler(void);
 void display_test(void);
 
 #endif /* _BOARD_H_ */

+ 57 - 13
src/board.c

@@ -28,6 +28,7 @@ static void GPIO_SPI_HW(void);
 //static void TIM17_Init(void);
 //static void USART1_UART_Init(void);
 static void _display_WriteBits(uint16_t data, uint16_t nbits);
+static void _delay_c(uint32_t cycle);
 
 /* Board perephireal Configuration  */
 void Board_Init(void)
@@ -203,16 +204,19 @@ static void GPIO_SPI_HW(void) {
   */
 static void I2C1_Init(void)
 {
+  /* I2C1 DMA Ch2 for I2C1_TX Init */
+  // DMA_CCR_CIRC
+  DMA1_Channel2->CCR = (DMA_CCR_DIR | DMA_CCR_PL_0 | DMA_CCR_MINC | DMA_CCR_TCIE | DMA_CCR_TEIE);
+
   /* I2C1 interrupt Init */
   NVIC_SetPriority(I2C1_IRQn, 0);
   NVIC_EnableIRQ(I2C1_IRQn);
 
   /** I2C Initialization: I2C_Fast */
-  I2C1->CR1 = 0x0;
-  I2C1->CR2 = 0x0;
-  I2C1->TIMINGR = 0x2010091A; // 0x00901850 ? 
-  I2C1->CR1 = I2C_CR1_PE;
+  I2C1->CR1 = (I2C_CR1_TXDMAEN | I2C_CR1_RXIE); //  | I2C_CR1_ERRIE
+  I2C1->TIMINGR = 0x00701850; // 400 kHz / 48 MHz / 50 ns / 50 ns
   I2C1->CR2 = I2C_CR2_AUTOEND;
+  I2C1->CR1 |= I2C_CR1_PE;
 }
 
 /**
@@ -231,8 +235,8 @@ static void SPI1_Init(void)
   NVIC_SetPriority(SPI1_IRQn, 0);
   NVIC_EnableIRQ(SPI1_IRQn);
 
-  /* SPI1 parameter configuration: master mode, data 8 bit, divider = 2, TX DMA */
-  SPI1->CR1 = (SPI_CR1_MSTR | SPI_CR1_SSM | SPI_CR1_SSI | SPI_CR1_CPOL | SPI_CR1_CPHA | SPI_CR1_LSBFIRST);
+  /* SPI1 parameter configuration: master mode, data 8 bit, divider = 64, TX DMA */
+  SPI1->CR1 = (SPI_CR1_BR_2 | SPI_CR1_BR_0 | SPI_CR1_MSTR | SPI_CR1_SSM | SPI_CR1_SSI | SPI_CR1_CPOL | SPI_CR1_CPHA | SPI_CR1_LSBFIRST);
   SPI1->CR2 = (SPI_CR2_DS_2 | SPI_CR2_DS_1 | SPI_CR2_DS_0 | SPI_CR2_TXDMAEN);
 }
 
@@ -321,12 +325,23 @@ void display_LedState(dis_en_t state) {
   GPIO_SPI_HW();
 }
 
+/**
+ * @brief Primitive delay
+ */
+static void _delay_c(uint32_t cycle) {
+  while (cycle) {
+    __NOP();
+    cycle --;
+  }
+}
+
 /**
  * @brief Write <nbits> bit of data to selected HT1632Cs
  * @param data words to write
  * @param nbits num of bits (1<<(num-1))
  */
 void _display_WriteBits(const uint16_t data, uint16_t nbits) {
+  _delay_c(2);
   do {
     HT1632C_WR_LOW;
 
@@ -335,9 +350,9 @@ void _display_WriteBits(const uint16_t data, uint16_t nbits) {
     } else {
       HT1632C_DATA_0;
     }
-
+    _delay_c(5);
     HT1632C_WR_HGH;
-
+    _delay_c(5);
   } while (nbits >>= 1);
 }
 
@@ -349,6 +364,9 @@ void _display_WriteBits(const uint16_t data, uint16_t nbits) {
  */
 void display_WriteData(const uint8_t * data, uint8_t addr, uint8_t len) {
   /* check given values */
+  if (len == 0) {
+    return;
+  }
   if (addr >= DISPLAY_COLUMNS) {
     addr = DISPLAY_COLUMNS - 1;
   }
@@ -358,10 +376,10 @@ void display_WriteData(const uint8_t * data, uint8_t addr, uint8_t len) {
 
 #ifdef FRAMEBUFFER_ROTATE
   /* Copy given data to framebuffer */
-  int i;
+  int i, a;
   for (i=0; i<len; i++) {
-    addr += i;
-    display_Buffer[addr] = data[addr];
+    a = addr + i;
+    display_Buffer[addr] = data[a];
   }
   display_WriteBuffer();
 #else
@@ -435,10 +453,10 @@ void display_WriteBuffer(void) {
   }
 
   /* DMA Source addr: Address of the SPI buffer. */
-  DMA1_Channel3->CMAR = (uint32_t)&spi_buf;
+  DMA1_Channel3->CMAR = (uint32_t)&spi_buf[0];
 #else
   /* DMA Source addr: Address of the SPI buffer. */
-  DMA1_Channel3->CMAR = (uint32_t)&display_Buffer;
+  DMA1_Channel3->CMAR = (uint32_t)&display_Buffer[0];
 #endif /* FRAMEBUFFER_ROTATE */
 
   /* Set DMA data transfer length (SPI buffer length). */
@@ -474,6 +492,7 @@ void EXTI4_15_IRQHandler(void)
   * @brief This function handles DMA1 channel 2 and 3 interrupts.
   */
 void DMA1_Channel2_3_IRQHandler(void) {
+  /* SPI Transmit Channel */
   if ((DMA1->ISR & DMA_ISR_TCIF3) != 0) {
     // clear interrupt flag
     DMA1->IFCR = DMA_IFCR_CTCIF3;
@@ -485,4 +504,29 @@ void DMA1_Channel2_3_IRQHandler(void) {
     // deselect chip
     HT1632C_CS_OFF;
   }
+
+  /* I2C Transmit Channel */
+  if ((DMA1->ISR & DMA_ISR_TCIF2) != 0) {
+    // clear interrupt flag
+    DMA1->IFCR = DMA_IFCR_CTCIF2;
+    // Disable DMA channels for I2C TX
+    DMA1_Channel2->CCR &= ~(DMA_CCR_EN);
+    //Flag.I2C_TX_End = 1;
+  }
+  // I2C Transmit Error
+  if ((DMA1->ISR & DMA_ISR_TEIF2) != 0) {
+    DMA1->IFCR = DMA_IFCR_CTEIF2;
+    DMA1_Channel2->CCR &= ~(DMA_CCR_EN);
+    //Flag.I2C_RX_End = 1;
+    //Flag.I2C_RX_Err = 1;
+  }
+}
+
+/**
+  * @brief This function handles I2C1 global interrupt.
+  */
+void I2C1_IRQHandler(void) {
+  if ((I2C1->ISR & I2C_ISR_RXNE) != 0) {
+    I2C1->RXDR;
+  }
 }