1 | void mcu_spi_spc_init_slave(void (*xfer_done)(uint8_t* data, uint32_t dlen))
|
2 | {
|
3 | spi2_xfer_done = xfer_done;
|
4 |
|
5 | for (int c=0;c<128;c++)
|
6 | {
|
7 | spi2_tx_buffer[c] = 0;
|
8 | spi2_rx_buffer[c] = 0;
|
9 | }
|
10 |
|
11 | // Enable the SPI2 peripheral clock
|
12 | RCC->APB1ENR |= RCC_APB1ENR_SPI2EN;
|
13 |
|
14 | // Enable port B Clock
|
15 | RCC->AHB1ENR |= (1<<1);
|
16 |
|
17 | // Enable DMA1 Clock
|
18 | RCC->AHB1ENR |= RCC_AHB1ENR_DMA1EN;
|
19 |
|
20 | // Reset the SPI2 peripheral to initial state
|
21 | RCC->APB1RSTR |= RCC_APB1RSTR_SPI2RST;
|
22 | RCC->APB1RSTR &= ~RCC_APB1RSTR_SPI2RST;
|
23 |
|
24 | /*
|
25 | * SPC SPI2 SS: Pin33 PB12
|
26 | * SPC SPI2 SCK: Pin34 PB13
|
27 | * SPC SPI2 MISO: Pin35 PB14
|
28 | * SPC SPI2 MOSI: Pin36 PB15
|
29 | */
|
30 |
|
31 | // Configure the SPI2 GPIO pins
|
32 | GPIOB->MODER |= (2<<24) | (2<<26) | (2<<28) | (2<<30);
|
33 | GPIOB->PUPDR |= (02<<26) | (2<<28) | (2<<30);
|
34 | GPIOB->OSPEEDR |= (3<<24) | (3<<26) | (3<<28) | (3<<30); // "very High speed"
|
35 | GPIOB->AFR[1] |= (5<<16) | (5<<20) | (5<<24) | (5<<28); // Alternate function 5 (SPI2)
|
36 |
|
37 | //-------------------------------------------------------
|
38 |
|
39 | // Clock Phase and Polarity = 0
|
40 | // CR1 = LSByte to MSByte, MSBit first
|
41 | // DFF = 8bit
|
42 | // 6 MHz Clock (48MHz / 8)
|
43 | spi_spc->CR1 = (7<<3) | (0<<2) | (0<<1) | (0<<0) // 0:CPHA, 1:CPOL, 2:MASTER, 3:CLOCK_DIVIDER
|
44 | | (0<<7) | (0<<11); // 7:LSB first, 11:DFF(8Bit)
|
45 |
|
46 | spi_spc->CR2 = (0<<2) | (1<<0); // 2:SSOE, 0:Enable RX DMA IRQ
|
47 |
|
48 | // DMA config (Stream3:RX p2mem, Stream4:TX mem2p
|
49 | // DMA for RX Stream 3 Channel 0
|
50 | DMA1_Stream3->CR &= ~(1<<0); // EN = 0: disable and reset
|
51 | while((DMA1_Stream3->CR & (1<<0)) != 0); // Wait
|
52 |
|
53 | DMA1_Stream4->CR &= ~(1<<0); // EN = 0: disable and reset
|
54 | while((DMA1_Stream4->CR & (1<<0)) != 0); // Wait
|
55 |
|
56 | DMA1->LIFCR = (0x3D<<22); // clear all ISRs related to Stream 3
|
57 | DMA1->HIFCR = (0x3D<< 0); // clear all ISRs related to Stream 4
|
58 |
|
59 | DMA1_Stream3->PAR = (uint32_t) (&(spi_spc->DR)); // Peripheral addresse
|
60 | DMA1_Stream3->M0AR = spi2_rx_buffer; // Memory addresse
|
61 |
|
62 | DMA1_Stream3->NDTR = 0xFFFF; // Datenmenge zum Empfangen
|
63 |
|
64 | DMA1_Stream3->FCR &= ~(1<<2); // ENABLE Direct mode by CLEARING Bit 2
|
65 | DMA1_Stream3->CR = (0<<25) | // 25:Channel selection(0)
|
66 | (1<<10) | // 10:increment mem_ptr,
|
67 | (0<<9) | // 9: Do not increment periph ptr
|
68 | (0<<6); // 6: Dir(P -> Mem)
|
69 |
|
70 | // DMA for TX Stream 4 Channel 0
|
71 | DMA1_Stream4->PAR = (uint32_t) (&(spi_spc->DR)); // Peripheral addresse
|
72 | DMA1_Stream4->M0AR = spi2_tx_buffer; // Memory addresse
|
73 |
|
74 | DMA1_Stream4->NDTR = 1; // Datenmenge zum Empfangen
|
75 |
|
76 | DMA1_Stream4->FCR &= ~(1<<2); // ENABLE Direct mode by CLEARING Bit 2
|
77 | DMA1_Stream4->CR = (0<<25) | // 25:Channel selection(0)
|
78 | (1<<10) | // 10:increment mem_ptr,
|
79 | (0<<9) | // 9: Do not increment periph ptr
|
80 | (1<<6) | // 6: Dir(Mem -> P)
|
81 | (1<<4);
|
82 |
|
83 | // Setup the NVIC to enable interrupts.
|
84 | // Use 4 bits for 'priority' and 0 bits for 'subpriority'.
|
85 | NVIC_SetPriorityGrouping( 0 );
|
86 |
|
87 | uint32_t pri_encoding = NVIC_EncodePriority( 0, 1, 0 );
|
88 | NVIC_SetPriority( DMA1_Stream4_IRQn, pri_encoding );
|
89 | NVIC_EnableIRQ( DMA1_Stream4_IRQn );
|
90 |
|
91 | DMA1_Stream3->CR |= (1<<1); // Enable DMA1_Stream3 (RX)
|
92 | spi_spc->CR1 |= (1<<6); // 6:EnableSPI
|
93 |
|
94 | }
|