embkernel
 All Classes Functions Variables Typedefs Groups Pages
DrvSpi.cpp
1 //------------------------------------------------------------------------------
2 //This file is part of embKernel.
3 //See license.txt for the full license governing this code.
4 //------------------------------------------------------------------------------
5 
6 #include "DrvSpi.hpp"
7 #include "DrvCfg.hpp"
8 #include "RtosInclude.hpp"
9 
10 DrvSpi* DrvSpi::sInstances[2];
11 
12 DrvSpi::DrvSpi() :
13  mSema(1, 1) {
14 }
15 
16 void DrvSpi::init(DrvTypes::SPI port, DrvGpio* cs, int baudrate, bool invertPhase, bool invertPolarity) {
17  IRQn_Type irqType;
18 
19  mCs = cs;
20 
21  switch (port) {
22  case DrvTypes::DRV_SPI1:
23  mSpi = SPI1;
24  irqType = SPI1_IRQn;
25  break;
26  case DrvTypes::DRV_SPI2:
27  irqType = SPI2_IRQn;
28  mSpi = SPI2;
29  break;
30  default:
31  return;
32  }
33 
34  sInstances[port - 1] = this;
35 
36  NVIC ->IP[irqType] = RTOS_INT_PRI;
37  NVIC_EnableIRQ(irqType);
38  setBaudrate(baudrate);
39  mSpi->CR2 = SPI_CR2_RXNEIE;
40  mSpi->CR1 |= SPI_CR1_MSTR | SPI_CR1_SSI | SPI_CR1_SSM;
41  if (invertPhase) {
42  mSpi->CR1 |= SPI_CR1_CPHA;
43  }
44  if (invertPolarity) {
45  mSpi->CR1 |= SPI_CR1_CPOL;
46  }
47  mSpi->CR1 |= SPI_CR1_SPE;
48 }
49 
50 void DrvSpi::setBaudrate(int baudrate) {
51  int clk;
52  if (mSpi == SPI1 ) {
53  clk = DRV_CFG_PCLK2_FREQ;
54  }
55  else {
56  clk = DRV_CFG_PCLK1_FREQ;
57  }
58  int br = 0;
59  while (baudrate <= clk) {
60  br++;
61  baudrate *= 2;
62  }
63  mSpi->CR1 &= ~(7 << 3);
64  mSpi->CR1 |= ((br & 7) << 3);
65 }
66 
67 void DrvSpi::select() {
68  *mCs = false;
69 }
70 
71 void DrvSpi::deselect() {
72  *mCs = true;
73 }
74 
75 uint8_t DrvSpi::readWrite(const uint8_t value) {
76  mSpi->DR = value;
77  mSema.take(Rtos::TICK_INFINITE);
78  return mDr;
79 }
80 
81 void DrvSpi::readWrite(const uint8_t* src, int srcLen, uint8_t* dst, int dstLen) {
82  int bigger = (srcLen > dstLen) ? srcLen : dstLen;
83  uint8_t value;
84  for (int i = 0; i < bigger; i++) {
85  if (i < srcLen) {
86  value = readWrite(src[i]);
87  }
88  else {
89  value = readWrite(0xFF);
90  }
91  if (i < dstLen) {
92  dst[i] = value;
93  }
94  }
95 }
96 
97 void DrvSpi::onInterrupt() {
98  mDr = mSpi->DR;
99  mSema.giveFromInt();
100 }
101 
102 void RtosInterrupt::IRQ_SPI1() {
103  DrvSpi::sInstances[0]->onInterrupt();
104 }
105 
106 void RtosInterrupt::IRQ_SPI2() {
107  DrvSpi::sInstances[1]->onInterrupt();
108 }