Skip to content

Commit f525a37

Browse files
committed
add configuration for SPI_MEM
CLOCKS: - SPI_MEM Core CLK: generic 0 (120MHz) - SPI_MEM Slow CLK: generic 3 (48MHz) - Sercom baud rate: 8MHz The MX25 module needs 80MHz for high performance mode and 8MHz in low power. Since the minimum divider for the baud rate generator is 4 (with BAUD reg set to 1, see 33.6.2.3 of SAM D5 datasheet), we need an input clock of 320MHz in high performance, which is not achievable with our mcu. We'll go with the low-power mode. I am not sure we actually need the low power clock. PORTS: Enabled SPI_MEM interface on SERCOM4 with the following pinout: - CLK -> PA12 - MOSI -> PA15 - MISO -> PA13 - CS -> PA14 - WP -> PB07 - HOLD -> PA20 The code has been originally generated using the Atmel start tool and adapted to the project.
1 parent 437261e commit f525a37

File tree

5 files changed

+329
-1
lines changed

5 files changed

+329
-1
lines changed

external/asf4-drivers/Config/peripheral_clk_config.h

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,86 @@
9595

9696
// <GCLK_PCHCTRL_GEN_GCLK11_Val"> Generic clock generator 11
9797

98+
// <i> Select the clock source for CORE.
99+
#ifndef CONF_GCLK_SERCOM4_CORE_SRC
100+
#define CONF_GCLK_SERCOM4_CORE_SRC GCLK_PCHCTRL_GEN_GCLK0_Val
101+
#endif
102+
103+
// <y> Slow Clock Source
104+
// <id> slow_gclk_selection
105+
106+
// <GCLK_PCHCTRL_GEN_GCLK0_Val"> Generic clock generator 0
107+
108+
// <GCLK_PCHCTRL_GEN_GCLK1_Val"> Generic clock generator 1
109+
110+
// <GCLK_PCHCTRL_GEN_GCLK2_Val"> Generic clock generator 2
111+
112+
// <GCLK_PCHCTRL_GEN_GCLK3_Val"> Generic clock generator 3
113+
114+
// <GCLK_PCHCTRL_GEN_GCLK4_Val"> Generic clock generator 4
115+
116+
// <GCLK_PCHCTRL_GEN_GCLK5_Val"> Generic clock generator 5
117+
118+
// <GCLK_PCHCTRL_GEN_GCLK6_Val"> Generic clock generator 6
119+
120+
// <GCLK_PCHCTRL_GEN_GCLK7_Val"> Generic clock generator 7
121+
122+
// <GCLK_PCHCTRL_GEN_GCLK8_Val"> Generic clock generator 8
123+
124+
// <GCLK_PCHCTRL_GEN_GCLK9_Val"> Generic clock generator 9
125+
126+
// <GCLK_PCHCTRL_GEN_GCLK10_Val"> Generic clock generator 10
127+
128+
// <GCLK_PCHCTRL_GEN_GCLK11_Val"> Generic clock generator 11
129+
130+
// <i> Select the slow clock source.
131+
#ifndef CONF_GCLK_SERCOM4_SLOW_SRC
132+
#define CONF_GCLK_SERCOM4_SLOW_SRC GCLK_PCHCTRL_GEN_GCLK3_Val
133+
#endif
134+
135+
/**
136+
* \def CONF_GCLK_SERCOM4_CORE_FREQUENCY
137+
* \brief SERCOM4's Core Clock frequency
138+
*/
139+
#ifndef CONF_GCLK_SERCOM4_CORE_FREQUENCY
140+
#define CONF_GCLK_SERCOM4_CORE_FREQUENCY 120000000
141+
#endif
142+
143+
/**
144+
* \def CONF_GCLK_SERCOM4_SLOW_FREQUENCY
145+
* \brief SERCOM4's Slow Clock frequency
146+
*/
147+
#ifndef CONF_GCLK_SERCOM4_SLOW_FREQUENCY
148+
#define CONF_GCLK_SERCOM4_SLOW_FREQUENCY 48000000
149+
#endif
150+
151+
// <y> Core Clock Source
152+
// <id> core_gclk_selection
153+
154+
// <GCLK_PCHCTRL_GEN_GCLK0_Val"> Generic clock generator 0
155+
156+
// <GCLK_PCHCTRL_GEN_GCLK1_Val"> Generic clock generator 1
157+
158+
// <GCLK_PCHCTRL_GEN_GCLK2_Val"> Generic clock generator 2
159+
160+
// <GCLK_PCHCTRL_GEN_GCLK3_Val"> Generic clock generator 3
161+
162+
// <GCLK_PCHCTRL_GEN_GCLK4_Val"> Generic clock generator 4
163+
164+
// <GCLK_PCHCTRL_GEN_GCLK5_Val"> Generic clock generator 5
165+
166+
// <GCLK_PCHCTRL_GEN_GCLK6_Val"> Generic clock generator 6
167+
168+
// <GCLK_PCHCTRL_GEN_GCLK7_Val"> Generic clock generator 7
169+
170+
// <GCLK_PCHCTRL_GEN_GCLK8_Val"> Generic clock generator 8
171+
172+
// <GCLK_PCHCTRL_GEN_GCLK9_Val"> Generic clock generator 9
173+
174+
// <GCLK_PCHCTRL_GEN_GCLK10_Val"> Generic clock generator 10
175+
176+
// <GCLK_PCHCTRL_GEN_GCLK11_Val"> Generic clock generator 11
177+
98178
// <i> Select the clock source for CORE.
99179
#ifndef CONF_GCLK_SERCOM3_CORE_SRC
100180
#define CONF_GCLK_SERCOM3_CORE_SRC GCLK_PCHCTRL_GEN_GCLK0_Val

external/asf4-drivers/hpl/spi/spi_lite.c

Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,129 @@
3535
#include "spi_lite.h"
3636
#include <utils_assert.h>
3737

38+
/**
39+
* \brief Initialize SPI interface
40+
*/
41+
int8_t SPI_MEM_init(void)
42+
{
43+
if (!hri_sercomspi_is_syncing(SERCOM4, SERCOM_SPI_SYNCBUSY_SWRST)) {
44+
uint32_t mode = SERCOM_SPI_CTRLA_MODE(3);
45+
if (hri_sercomspi_get_CTRLA_reg(SERCOM4, SERCOM_SPI_CTRLA_ENABLE)) {
46+
hri_sercomspi_clear_CTRLA_ENABLE_bit(SERCOM4);
47+
hri_sercomspi_wait_for_sync(SERCOM4, SERCOM_SPI_SYNCBUSY_ENABLE);
48+
}
49+
hri_sercomspi_write_CTRLA_reg(SERCOM4, SERCOM_SPI_CTRLA_SWRST | mode);
50+
}
51+
hri_sercomspi_wait_for_sync(SERCOM4, SERCOM_SPI_SYNCBUSY_SWRST);
52+
53+
hri_sercomspi_write_CTRLA_reg(
54+
SERCOM4,
55+
0 << SERCOM_SPI_CTRLA_DORD_Pos /* Data Order: disabled */
56+
| 0 << SERCOM_SPI_CTRLA_CPOL_Pos /* Clock Polarity: disabled */
57+
| 0 << SERCOM_SPI_CTRLA_CPHA_Pos /* Clock Phase: disabled */
58+
| 0 << SERCOM_SPI_CTRLA_FORM_Pos /* Frame Format: 0 */
59+
| 0 << SERCOM_SPI_CTRLA_IBON_Pos /* Immediate Buffer Overflow Notification: disabled */
60+
| 0 << SERCOM_SPI_CTRLA_RUNSTDBY_Pos /* Run In Standby: disabled */
61+
| 3 << SERCOM_SPI_CTRLA_MODE_Pos); /* Operating Mode: 3 */
62+
63+
hri_sercomspi_write_CTRLA_DOPO_bf(SERCOM4, SERCOM4_TXPO);
64+
hri_sercomspi_write_CTRLA_DIPO_bf(SERCOM4, SERCOM4_RXPO);
65+
66+
hri_sercomspi_write_CTRLB_reg(SERCOM4,
67+
1 << SERCOM_SPI_CTRLB_RXEN_Pos /* Receiver Enable: enabled */
68+
| 0 << SERCOM_SPI_CTRLB_MSSEN_Pos /* Master Slave Select Enabl: disabled */
69+
| 0 << SERCOM_SPI_CTRLB_AMODE_Pos /* Address Mode: 0 */
70+
| 0 << SERCOM_SPI_CTRLB_SSDE_Pos /* Slave Select Low Detect Enable: disabled */
71+
| 0 << SERCOM_SPI_CTRLB_PLOADEN_Pos /* Slave Data Preload Enable: disabled */
72+
| 0); /* Character Size: 0 */
73+
74+
hri_sercomspi_write_BAUD_reg(SERCOM4, SERCOM4_BAUD_RATE);
75+
76+
// hri_sercomspi_write_DBGCTRL_reg(SERCOM4,0 << SERCOM_SPI_DBGCTRL_DBGSTOP_Pos); /* Debug Stop Mode: disabled */
77+
78+
// hri_sercomspi_write_INTEN_reg(SERCOM4,0 << SERCOM_SPI_INTENSET_ERROR_Pos /* Error Interrupt Enable: disabled */
79+
// | 0 << SERCOM_SPI_INTENSET_SSL_Pos /* Slave Select Low Interrupt Enable: disabled */
80+
// | 0 << SERCOM_SPI_INTENSET_RXC_Pos /* Receive Complete Interrupt Enable: disabled */
81+
// | 0 << SERCOM_SPI_INTENSET_TXC_Pos /* Transmit Complete Interrupt Enable: disabled */
82+
// | 0 << SERCOM_SPI_INTENSET_DRE_Pos); /* Data Register Empty Interrupt Enable: disabled */
83+
84+
hri_sercomspi_write_CTRLA_ENABLE_bit(SERCOM4, 1 << SERCOM_SPI_CTRLA_ENABLE_Pos); /* Enable: enabled */
85+
86+
return 0;
87+
}
88+
89+
/**
90+
* \brief Enable SPI module
91+
*/
92+
void SPI_MEM_enable(void)
93+
{
94+
hri_sercomspi_set_CTRLA_ENABLE_bit(SERCOM4);
95+
}
96+
97+
/**
98+
* \brief Disable SPI module
99+
*/
100+
void SPI_MEM_disable(void)
101+
{
102+
hri_sercomspi_clear_CTRLA_ENABLE_bit(SERCOM4);
103+
}
104+
105+
/**
106+
* \brief Exchange_byte in SPI module
107+
*/
108+
uint32_t SPI_MEM_exchange_data(uint32_t data)
109+
{
110+
/* If settings are not applied (pending), we can not go on */
111+
if (hri_sercomspi_is_syncing(
112+
SERCOM4, (SERCOM_SPI_SYNCBUSY_SWRST | SERCOM_SPI_SYNCBUSY_ENABLE | SERCOM_SPI_SYNCBUSY_CTRLB))) {
113+
return ERR_BUSY;
114+
}
115+
116+
hri_sercomspi_write_DATA_reg(SERCOM4, data);
117+
while (!(hri_sercomspi_read_INTFLAG_reg(SERCOM4) & SERCOM_SPI_INTFLAG_RXC))
118+
;
119+
return hri_sercomspi_read_DATA_reg(SERCOM4);
120+
}
121+
122+
void SPI_MEM_exchange_block(void *block, uint8_t size)
123+
{
124+
125+
uint8_t *b = (uint8_t *)block;
126+
127+
while (size--) {
128+
hri_sercomspi_write_DATA_reg(SERCOM4, *b);
129+
while (!(hri_sercomspi_read_INTFLAG_reg(SERCOM4) & SERCOM_SPI_INTFLAG_RXC))
130+
;
131+
*b = hri_sercomspi_read_DATA_reg(SERCOM4);
132+
b++;
133+
}
134+
}
135+
136+
void SPI_MEM_write_block(void *block, uint8_t size)
137+
{
138+
139+
uint8_t *b = (uint8_t *)block;
140+
while (size--) {
141+
hri_sercomspi_write_DATA_reg(SERCOM4, *b);
142+
while (!(hri_sercomspi_read_INTFLAG_reg(SERCOM4) & SERCOM_SPI_INTFLAG_RXC))
143+
;
144+
b++;
145+
}
146+
}
147+
148+
void SPI_MEM_read_block(void *block, uint8_t size)
149+
{
150+
151+
uint8_t *b = (uint8_t *)block;
152+
while (size--) {
153+
hri_sercomspi_write_DATA_reg(SERCOM4, 0);
154+
while (!(hri_sercomspi_read_INTFLAG_reg(SERCOM4) & SERCOM_SPI_INTFLAG_RXC))
155+
;
156+
*b = hri_sercomspi_read_DATA_reg(SERCOM4);
157+
b++;
158+
}
159+
}
160+
38161
/**
39162
* \brief Initialize SPI interface
40163
*/

external/asf4-drivers/hpl/spi/spi_lite.h

Lines changed: 51 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,9 +51,59 @@
5151
extern "C" {
5252
#endif
5353

54+
// Calculate baud register value from requested baudrate value
55+
#ifndef SERCOM4_BAUD_RATE
56+
#define SERCOM4_BAUD_RATE ((float)CONF_GCLK_SERCOM4_CORE_FREQUENCY / (float)(2 * 8000000)) - 1
57+
#endif
58+
59+
#ifndef SERCOM4_RXPO
60+
#define SERCOM4_RXPO 0
61+
#endif
62+
63+
#ifndef SERCOM4_TXPO
64+
#define SERCOM4_TXPO 2
65+
#endif
66+
67+
/**
68+
* \brief Initialize usart interface
69+
*
70+
* \return Initialization status.
71+
*/
72+
int8_t SPI_MEM_init(void);
73+
74+
/**
75+
* \brief Enable SPI module
76+
*/
77+
void SPI_MEM_enable(void);
78+
79+
/**
80+
* \brief Disable SPI module
81+
*/
82+
void SPI_MEM_disable(void);
83+
84+
/**
85+
* \brief Exchange byte in SPI module
86+
*/
87+
uint32_t SPI_MEM_exchange_data(uint32_t data);
88+
89+
/**
90+
* \brief Exchange block in SPI module
91+
*/
92+
void SPI_MEM_exchange_block(void *block, uint8_t size);
93+
94+
/**
95+
* \brief Write block in SPI module
96+
*/
97+
void SPI_MEM_write_block(void *block, uint8_t size);
98+
99+
/**
100+
* \brief Read block in SPI module
101+
*/
102+
void SPI_MEM_read_block(void *block, uint8_t size);
103+
54104
// Calculate baud register value from requested baudrate value
55105
#ifndef SERCOM3_BAUD_RATE
56-
#define SERCOM3_BAUD_RATE ((float)CONF_GCLK_SERCOM3_CORE_FREQUENCY / (float)(2 * 3000000)) - 1
106+
#define SERCOM3_BAUD_RATE (((float)CONF_GCLK_SERCOM3_CORE_FREQUENCY / (float)(2 * 3000000)) - 1)
57107
#endif
58108

59109
#ifndef SERCOM3_RXPO

src/platform/bitbox02_pins.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,12 @@
2828
#define PIN_SPI_MOSI GPIO(GPIO_PORTA, 17)
2929
#define PIN_SPI_MISO GPIO(GPIO_PORTA, 18)
3030
#define PIN_OLED_CS GPIO(GPIO_PORTA, 19)
31+
#define PIN_MEM_CLK GPIO(GPIO_PORTA, 12)
32+
#define PIN_MEM_MOSI GPIO(GPIO_PORTA, 15)
33+
#define PIN_MEM_MISO GPIO(GPIO_PORTA, 13)
34+
#define PIN_MEM_CS GPIO(GPIO_PORTA, 14)
35+
#define PIN_MEM_HOLD GPIO(GPIO_PORTA, 20)
36+
#define PIN_MEM_WP GPIO(GPIO_PORTB, 7)
3137
#define PIN_I2C_SCL GPIO(GPIO_PORTA, 22)
3238
#define PIN_I2C_SDA GPIO(GPIO_PORTA, 23)
3339
#define PIN_USB_DM GPIO(GPIO_PORTA, 24)

src/platform/driver_init.c

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,12 @@
1515
// THIS IS A GENERATED FILE, MODIFY AS LITTLE AS POSSIBLE
1616

1717
#include "driver_init.h"
18+
#include "bitbox02_pins.h"
19+
#include "memory/memory_shared.h"
20+
#include "util.h"
21+
#include <compiler.h>
22+
#include <hal_sleep.h>
23+
#include <stdint.h>
1824
#include <utils.h>
1925

2026
#define PIN_HIGH 1
@@ -115,6 +121,57 @@ static void _spi_init(void)
115121
SPI_OLED_enable();
116122
}
117123

124+
static void _spi_mem_clock_init(void)
125+
{
126+
hri_gclk_write_PCHCTRL_reg(
127+
GCLK, SERCOM4_GCLK_ID_CORE, CONF_GCLK_SERCOM4_CORE_SRC | (1 << GCLK_PCHCTRL_CHEN_Pos));
128+
hri_gclk_write_PCHCTRL_reg(
129+
GCLK, SERCOM4_GCLK_ID_SLOW, CONF_GCLK_SERCOM4_SLOW_SRC | (1 << GCLK_PCHCTRL_CHEN_Pos));
130+
131+
hri_mclk_set_APBDMASK_SERCOM4_bit(MCLK);
132+
}
133+
134+
static void _spi_mem_port_init(void)
135+
{
136+
// CS
137+
gpio_set_pin_level(PIN_MEM_CS, PIN_LOW);
138+
gpio_set_pin_direction(PIN_MEM_CS, GPIO_DIRECTION_OUT);
139+
gpio_set_pin_function(PIN_MEM_CS, GPIO_PIN_FUNCTION_OFF);
140+
141+
// MISO
142+
gpio_set_pin_direction(PIN_MEM_MISO, GPIO_DIRECTION_IN);
143+
gpio_set_pin_pull_mode(PIN_MEM_MISO, GPIO_PULL_OFF);
144+
gpio_set_pin_function(PIN_MEM_MISO, PINMUX_PA13D_SERCOM4_PAD0);
145+
146+
// CLK
147+
gpio_set_pin_level(PIN_MEM_CLK, PIN_LOW);
148+
gpio_set_pin_direction(PIN_MEM_CLK, GPIO_DIRECTION_OUT);
149+
gpio_set_pin_function(PIN_MEM_CLK, PINMUX_PA12D_SERCOM4_PAD1);
150+
151+
// MOSI
152+
gpio_set_pin_level(PIN_MEM_MOSI, PIN_LOW);
153+
gpio_set_pin_direction(PIN_MEM_MOSI, GPIO_DIRECTION_OUT);
154+
gpio_set_pin_function(PIN_MEM_MOSI, PINMUX_PA15D_SERCOM4_PAD3);
155+
156+
// HOLD
157+
gpio_set_pin_level(PIN_MEM_HOLD, PIN_HIGH);
158+
gpio_set_pin_direction(PIN_MEM_HOLD, GPIO_DIRECTION_OUT);
159+
160+
// WP
161+
gpio_set_pin_level(PIN_MEM_WP, PIN_HIGH);
162+
gpio_set_pin_direction(PIN_MEM_WP, GPIO_DIRECTION_OUT);
163+
}
164+
165+
/**
166+
* Initialize SPI 1 peripheral
167+
*/
168+
static void _spi_mem_init(void)
169+
{
170+
_spi_mem_clock_init();
171+
SPI_MEM_init();
172+
_spi_mem_port_init();
173+
}
174+
118175
/**
119176
* Set pins for I2C peripheral
120177
*/
@@ -300,6 +357,12 @@ void system_init(void)
300357
_flash_memory_init();
301358
// USB
302359
_usb_init();
360+
361+
if (memory_get_platform() == MEMORY_PLATFORM_BITBOX02_PLUS) {
362+
// External MX25 flash memory
363+
_spi_mem_init();
364+
}
365+
303366
_is_initialized = true;
304367
}
305368

@@ -325,6 +388,12 @@ void bootloader_init(void)
325388
_flash_memory_init();
326389
// USB
327390
_usb_init();
391+
392+
if (memory_get_platform() == MEMORY_PLATFORM_BITBOX02_PLUS) {
393+
// External MX25 flash memory
394+
_spi_mem_init();
395+
}
396+
328397
_is_initialized = true;
329398
}
330399

0 commit comments

Comments
 (0)