Hanna
Sourcecode Batteriemanagementsystem
spi_master.c
gehe zur Dokumentation dieser Datei
1 
45 #include "spi_master.h"
46 #include "sysclk.h"
47 
48 
59 int8_t spi_xmega_set_baud_div(SPI_t *spi, uint32_t baudrate, uint32_t clkper_hz)
60 {
61  uint32_t divisor;
62  uint8_t divisor_8bit;
63  uint8_t ctrl;
64 
65  // Sanity check, requested baudrate is lower than system clock
66  Assert(clkper_hz > baudrate);
67 
68  /*
69  * Get wanted divisor rounded up so we don't get speed higher than
70  * requested baudrate.
71  */
72  divisor = (clkper_hz + baudrate - 1) / baudrate;
73 
74  if (divisor > 128) {
75  /*
76  * Highest possible divisor is 128 so fail since we can't get
77  * low enough baudrate.
78  */
79  return -1;
80  }
81 
82  /*
83  * We now know that the divisor is 128 or lower so move it into a 8-bit
84  * variable to make sure the following comparison is more optimized.
85  */
86  divisor_8bit = divisor;
87 
88  /*
89  * For divisor values between the possible ones round up to the closest
90  * higher one to avoid higher baudrate than requested.
91  */
92  if (divisor_8bit > 64) {
93  ctrl = SPI_PRESCALER_DIV128_gc;
94  }
95  else if (divisor_8bit > 32) {
96  ctrl = SPI_PRESCALER_DIV64_gc;
97  }
98  else if (divisor_8bit > 16) {
99  ctrl = SPI_CLK2X_bm | SPI_PRESCALER_DIV64_gc;
100  }
101  else if (divisor_8bit > 8) {
102  ctrl = SPI_PRESCALER_DIV16_gc;
103  }
104  else if (divisor_8bit > 4) {
105  ctrl = SPI_CLK2X_bm | SPI_PRESCALER_DIV16_gc;
106  }
107  else if (divisor_8bit > 2) {
108  ctrl = SPI_PRESCALER_DIV4_gc;
109  }
110  else {
111  ctrl = SPI_CLK2X_bm | SPI_PRESCALER_DIV4_gc;
112  }
113 
114  // Update register and make sure to clear out any leftover bits
115  spi->CTRL = (spi->CTRL & ~(SPI_CLK2X_bm | SPI_PRESCALER_gm)) | ctrl;
116 
117  return 1;
118 }
119 
120 
126 void spi_master_init(SPI_t *spi)
127 {
128 #ifdef SPIA
129  if ((uint16_t)spi == (uint16_t)&SPIA) {
131  }
132 #endif
133 #ifdef SPIB
134  if ((uint16_t)spi == (uint16_t)&SPIB) {
136  }
137 #endif
138 #ifdef SPIC
139  if ((uint16_t)spi == (uint16_t)&SPIC) {
141  }
142 #endif
143 #ifdef SPID
144  if ((uint16_t)spi == (uint16_t)&SPID) {
146  }
147 #endif
148 #ifdef SPIE
149  if ((uint16_t)spi == (uint16_t)&SPIE) {
151  }
152 #endif
153 #ifdef SPIF
154  if ((uint16_t)spi == (uint16_t)&SPIF) {
156  }
157 #endif
159 }
160 
175 void spi_master_setup_device(SPI_t *spi, struct spi_device *device,
176  spi_flags_t flags, uint32_t baud_rate,
177  board_spi_select_id_t sel_id)
178 {
179  if (spi_xmega_set_baud_div(spi, baud_rate, sysclk_get_cpu_hz()) < 0) {
180  Assert(false);
181  return;
182  }
183 
184  /* Clear any set SPI mode flags and set them to the user-specified mode */
185  spi->CTRL = (spi->CTRL & ~SPI_MODE_gm) |
186  ((flags << SPI_MODE_gp) & SPI_MODE_gm);
187 }
188 
200 status_code_t spi_write_packet(SPI_t *spi, const uint8_t *data, size_t len)
201 {
202  while (len--) {
203  spi_write_single(spi, *data++);
204 
205  while (!spi_is_rx_full(spi)) {
206  }
207  }
208 
209  return STATUS_OK;
210 }
211 
223 status_code_t spi_read_packet(SPI_t *spi, uint8_t *data, size_t len)
224 {
225  while (len--) {
226  spi_write_single(spi,CONFIG_SPI_MASTER_DUMMY); //Dummy write
227 
228  while (!spi_is_rx_full(spi)) {
229  }
230 
231  spi_read_single(spi, data);
232  data++;
233  }
234 
235  return STATUS_OK;
236 }
237 
247 void spi_select_device(SPI_t *spi, struct spi_device *device)
248 {
249 }
250 
261 void spi_deselect_device(SPI_t *spi, struct spi_device *device)
262 {
263 }
static bool spi_is_rx_full(SPI_t *spi)
Tests if the SPI contains a received character.
Definition: spi_master.h:409
static uint32_t sysclk_get_cpu_hz(void)
Return the current rate in Hz of the CPU clock.
Definition: sysclk.h:356
static void spi_enable_master_mode(SPI_t *spi)
Activate SPI master mode of a SPI peripheral.
Definition: spi_master.h:180
Polled SPI device definition.
Definition: spi_master.h:250
#define Assert(expr)
This macro is used to test fatal errors.
Definition: compiler.h:46
static void spi_read_single(SPI_t *spi, uint8_t *data)
Receive one byte from a SPI device.
Definition: spi_master.h:359
void spi_master_setup_device(SPI_t *spi, struct spi_device *device, spi_flags_t flags, uint32_t baud_rate, board_spi_select_id_t sel_id)
Setup a SPI device.
Definition: spi_master.c:175
void spi_master_init(SPI_t *spi)
Initializes the SPI in master mode.
Definition: spi_master.c:126
Devices on PORTB.
Definition: sysclk.h:128
int8_t spi_xmega_set_baud_div(SPI_t *spi, uint32_t baudrate, uint32_t clkper_hz)
Calculates the SPI baudrate divider.
Definition: spi_master.c:59
Success.
Definition: spi_master.h:63
Devices on PORTA.
Definition: sysclk.h:127
status_code_t spi_read_packet(SPI_t *spi, uint8_t *data, size_t len)
Receive a sequence of bytes from a SPI device.
Definition: spi_master.c:223
static __always_inline void spi_write_single(SPI_t *spi, uint8_t data)
Write one byte to a SPI device.
Definition: spi_master.h:334
Devices on PORTD.
Definition: sysclk.h:130
Devices on PORTE.
Definition: sysclk.h:131
Devices on PORTC.
Definition: sysclk.h:129
void spi_select_device(SPI_t *spi, struct spi_device *device)
Select given device on the SPI bus.
Definition: spi_master.c:247
void sysclk_enable_module(enum sysclk_port_id port, uint8_t id)
Enable the clock to peripheral id on port port.
Definition: sysclk.c:176
#define CONFIG_SPI_MASTER_DUMMY
Default Config Spi Master Dummy Field.
Definition: spi_master.h:215
Chip-specific system clock management functions.
SPI Master driver header file.
Devices on PORTF.
Definition: sysclk.h:132
void spi_deselect_device(SPI_t *spi, struct spi_device *device)
Deselect given device on the SPI bus.
Definition: spi_master.c:261
status_code_t spi_write_packet(SPI_t *spi, const uint8_t *data, size_t len)
Send a sequence of bytes to a SPI device.
Definition: spi_master.c:200