Skip to content

Commit 79c0f36

Browse files
committed
[beken-72xx] Add draft SPI TX support
1 parent 2e20512 commit 79c0f36

File tree

4 files changed

+343
-0
lines changed

4 files changed

+343
-0
lines changed
Lines changed: 198 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,198 @@
1+
/* Copyright (c) Kuba Szczodrzyński 2024-03-15. */
2+
3+
#include "SPIPrivate.h"
4+
5+
#define SPI_PERI_CLK_26M (26 * 1000 * 1000)
6+
#define SPI_PERI_CLK_DCO (80 * 1000 * 1000)
7+
8+
bool SPIClass::beginPrivate() {
9+
if (!this->data)
10+
return false;
11+
uint32_t param;
12+
13+
REG_SPI0->ctrl = 0;
14+
15+
intc_service_change_handler(IRQ_SPI, (FUNCPTR)SPIClass::isrHandlerStatic);
16+
// bk_spi_configure()
17+
REG_SPI0->BIT_WIDTH = 0;
18+
REG_SPI0->MSTEN = true;
19+
// disable hardware CS - issues with per-byte data transfer otherwise
20+
#if LT_BK7231N
21+
REG_SPI0->WIRE3_EN = true;
22+
#else
23+
REG_SPI0->NSSMD = 3;
24+
#endif
25+
// spi_init_msten(0)
26+
REG_SPI0->TX_FIFO_INT_LEVEL = 0;
27+
REG_SPI0->TX_FIFO_INT_LEVEL = 0;
28+
REG_SPI0->TX_UDF_INT_EN = true;
29+
REG_SPI0->RX_OVF_INT_EN = true;
30+
// spi_active(1)
31+
REG_SPI0->SPIEN = true;
32+
// spi_icu_configuration(1)
33+
param = PWD_SPI_CLK_BIT;
34+
icu_ctrl(CMD_CLK_PWR_UP, &param);
35+
param = IRQ_SPI_BIT;
36+
icu_ctrl(CMD_ICU_INT_ENABLE, &param);
37+
// spi_gpio_configuration()
38+
param = GFUNC_MODE_SPI;
39+
gpio_ctrl(CMD_GPIO_ENABLE_SECOND, &param);
40+
41+
return true;
42+
}
43+
44+
bool SPIClass::endPrivate() {
45+
if (!this->data)
46+
return true;
47+
uint32_t param;
48+
49+
param = IRQ_SPI_BIT;
50+
icu_ctrl(CMD_ICU_INT_DISABLE, &param);
51+
param = PWD_SPI_CLK_BIT;
52+
icu_ctrl(CMD_CLK_PWR_DOWN, &param);
53+
54+
REG_SPI0->ctrl = 0;
55+
56+
return true;
57+
}
58+
59+
void SPIClass::setFrequency(uint32_t frequency) {
60+
if (!this->data)
61+
return;
62+
uint32_t param;
63+
uint32_t maxFrequency = 30000000;
64+
uint32_t sourceClk;
65+
uint32_t clockDiv;
66+
67+
REG_SPI0->SPIEN = false;
68+
this->settings._clock = frequency;
69+
70+
if (frequency == 26000000 || frequency == 13000000 || frequency == 6500000 || frequency <= 4333000) {
71+
#if CFG_XTAL_FREQUENCE
72+
sourceClk = CFG_XTAL_FREQUENCE;
73+
#else
74+
sourceClk = SPI_PERI_CLK_26M;
75+
#endif
76+
param = PCLK_POSI_SPI;
77+
icu_ctrl(CMD_CONF_PCLK_26M, &param);
78+
} else {
79+
if (frequency > maxFrequency) {
80+
LT_WM(SPI, "Clock freq too high! %lu > %lu", frequency, maxFrequency);
81+
frequency = maxFrequency;
82+
}
83+
sourceClk = SPI_PERI_CLK_DCO;
84+
param = PWD_SPI_CLK_BIT;
85+
icu_ctrl(CMD_CLK_PWR_DOWN, &param);
86+
param = PCLK_POSI_SPI;
87+
icu_ctrl(CMD_CONF_PCLK_DCO, &param);
88+
param = PWD_SPI_CLK_BIT;
89+
icu_ctrl(CMD_CLK_PWR_UP, &param);
90+
}
91+
92+
if (frequency == 26000000 || frequency == 13000000 || frequency == 6500000) {
93+
clockDiv = sourceClk / frequency - 1;
94+
} else {
95+
clockDiv = ((sourceClk >> 1) / frequency);
96+
if (clockDiv < 2)
97+
clockDiv = 2;
98+
else if (clockDiv >= 255)
99+
clockDiv = 255;
100+
}
101+
102+
REG_SPI0->SPI_CKR = clockDiv;
103+
REG_SPI0->SPIEN = true;
104+
}
105+
106+
void SPIClass::setBitOrder(uint8_t bitOrder) {
107+
if (!this->data)
108+
return;
109+
this->settings._bitOrder = bitOrder;
110+
#if LT_BK7231N
111+
REG_SPI0->LSB_FIRST = bitOrder == SPI_LSBFIRST;
112+
#endif
113+
}
114+
115+
void SPIClass::setDataMode(uint8_t dataMode) {
116+
if (!this->data)
117+
return;
118+
this->settings._dataMode = dataMode;
119+
REG_SPI0->CKPOL = (dataMode >> 1) & 0b1;
120+
REG_SPI0->CKPHA = (dataMode >> 0) & 0b1;
121+
}
122+
123+
void SPIClass::commitTransaction() {
124+
if (this->txLen != 0) {
125+
REG_SPI0->TX_FIFO_CLR = true;
126+
REG_SPI0->TX_TRANS_LEN = this->txLen * 8;
127+
REG_SPI0->TX_FIFO_INT_EN = false;
128+
REG_SPI0->TX_EN = true;
129+
while (this->txLen--) {
130+
while (REG_SPI0->TX_FIFO_WR_READY == false) {}
131+
uint32_t data = *this->txBuf++;
132+
// LT_I("<- TX: %02x", data);
133+
REG_SPI0->SPI_DAT = data;
134+
}
135+
REG_SPI0->TX_FIFO_INT_EN = false;
136+
REG_SPI0->TX_EN = false;
137+
}
138+
if (this->rxLen != 0) {
139+
// REG_SPI0->RX_FIFO_CLR = true;
140+
// REG_SPI0->RX_TRANS_LEN = this->rxLen * 8;
141+
// REG_SPI0->RX_FIFO_INT_EN = false;
142+
// REG_SPI0->RX_FINISH_INT_EN = false;
143+
// REG_SPI0->RX_EN = true;
144+
// while (this->rxLen--) {
145+
// while (REG_SPI0->RX_FIFO_RD_READY == false) {}
146+
// uint32_t data = REG_SPI0->SPI_DAT;
147+
// // LT_I("-> RX: %02x", data);
148+
// *this->rxBuf++ = data;
149+
// }
150+
// REG_SPI0->RX_EN = false;
151+
// REG_SPI0->TX_FIFO_INT_EN = false;
152+
// REG_SPI0->RX_FIFO_INT_EN = false;
153+
}
154+
}
155+
156+
void SPIClass::isrHandlerStatic(void *param) {
157+
SPI.isrHandler(param);
158+
}
159+
160+
void SPIClass::isrHandler(void *param) {
161+
if (REG_SPI0->RX_FIFO_INT) {
162+
LT_I("RX_FIFO_INT, rxLen=%d", this->rxLen);
163+
while (this->rxLen != 0 && REG_SPI0->RX_FIFO_RD_READY == true) {
164+
uint8_t data = REG_SPI0->SPI_DAT;
165+
LT_I("RX data in ISR #1 %02x", data);
166+
*this->rxBuf++ = data;
167+
this->rxLen--;
168+
}
169+
if (this->rxLen == 0) {
170+
REG_SPI0->RX_EN = false;
171+
REG_SPI0->TX_FIFO_INT_EN = false;
172+
REG_SPI0->RX_FIFO_INT_EN = false;
173+
}
174+
REG_SPI0->RX_FIFO_INT = true;
175+
}
176+
if (REG_SPI0->RX_FINISH_INT) {
177+
LT_I("RX_FINISH_INT, rxLen=%d", this->rxLen);
178+
while (this->rxLen != 0 && REG_SPI0->RX_FIFO_RD_READY == true) {
179+
uint8_t data = REG_SPI0->SPI_DAT;
180+
LT_I("RX data in ISR #2 %02x", data);
181+
*this->rxBuf++ = data;
182+
this->rxLen--;
183+
}
184+
REG_SPI0->RX_EN = false;
185+
REG_SPI0->TX_FIFO_INT_EN = false;
186+
REG_SPI0->RX_FIFO_INT_EN = false;
187+
REG_SPI0->RX_FINISH_INT = true;
188+
}
189+
190+
if (REG_SPI0->TX_UDF_INT) {
191+
LT_W("TX underflow");
192+
REG_SPI0->TX_UDF_INT = true;
193+
}
194+
if (REG_SPI0->RX_OVF_INT) {
195+
LT_W("RX overflow");
196+
REG_SPI0->RX_OVF_INT = true;
197+
}
198+
}
Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
/* Copyright (c) Kuba Szczodrzyński 2024-03-15. */
2+
3+
#pragma once
4+
5+
#include <ArduinoPrivate.h>
6+
#include <SPI.h>
7+
8+
struct SPIData {};
9+
10+
// Register structures based on:
11+
// - https://github.com/bekencorp/armino/blob/main/middleware/soc/bk7231n/soc/spi_struct.h
12+
// - https://wiki.bekencorp.com/pages/viewpage.action?pageId=23692278
13+
// - BDK beken378/driver/spi/*.h
14+
15+
typedef volatile struct {
16+
union {
17+
struct {
18+
uint32_t TX_FIFO_INT_LEVEL : 2; //!< TX FIFO interrupt generation condition (1/16/32/48) [RW] (0x0[0:1])
19+
uint32_t RX_FIFO_INT_LEVEL : 2; //!< RX FIFO interrupt generation condition (1/16/32/48) [RW] (0x0[2:3])
20+
uint32_t TX_UDF_INT_EN : 1; //!< TX FIFO underflow interrupt enable [RW] (0x0[4])
21+
uint32_t RX_OVF_INT_EN : 1; //!< RX FIFO overflow interrupt enable [RW] (0x0[5])
22+
uint32_t TX_FIFO_INT_EN : 1; //!< TX FIFO interrupt enable [RW] (0x0[6])
23+
uint32_t RX_FIFO_INT_EN : 1; //!< RX FIFO interrupt enable [RW] (0x0[7])
24+
uint32_t SPI_CKR : 8; //!< Prescaler factor [RW] (0x0[8:15])
25+
#if LT_BK7231N || LT_BK7271
26+
uint32_t SLV_RELEASE_INT_EN : 1; //!< Slave release interrupt enable (four-wire slave mode) [RW] (0x0[16])
27+
uint32_t WIRE3_EN : 1; //!< Three-wire mode (no CSN signal) [RW] (0x0[17])
28+
#else
29+
uint32_t NSSMD : 2; //!< (0x0[16:17])
30+
#endif
31+
uint32_t BIT_WIDTH : 1; //!< Data bit width (0: 8-bit, 1: 16-bit) [RW] (0x0[18])
32+
#if LT_BK7231N || LT_BK7271
33+
uint32_t LSB_FIRST : 1; //!< Data frame format (0: MSB-first, 1: LSB-first) [RW] (0x0[19])
34+
#else
35+
uint32_t _reserved0 : 1; //!< (0x0[19])
36+
#endif
37+
uint32_t CKPOL : 1; //!< SPI clock polarity [RW] (0x0[20])
38+
uint32_t CKPHA : 1; //!< SPI clock phase [RW] (0x0[21])
39+
uint32_t MSTEN : 1; //!< Master mode enable [RW] (0x0[22])
40+
uint32_t SPIEN : 1; //!< SPI enable [RW] (0x0[23])
41+
#if LT_BK7231N || LT_BK7271
42+
uint32_t BYTE_INTLVAL : 8; //!< SCK interval between data units (master) [RW] (0x0[24:31])
43+
#else
44+
uint32_t _reserved1 : 8; //!< (0x0[24:31])
45+
#endif
46+
};
47+
48+
uint32_t ctrl;
49+
};
50+
51+
#if LT_BK7231N || LT_BK7271
52+
union {
53+
struct {
54+
uint32_t TX_EN : 1; //!< TX enable [RW] (0x1[0])
55+
uint32_t RX_EN : 1; //!< RX enable [RW] (0x1[1])
56+
uint32_t TX_FINISH_INT_EN : 1; //!< TX_TRANS_LEN completed interrupt enabled [RW] (0x1[2])
57+
uint32_t RX_FINISH_INT_EN : 1; //!< RX_TRANS_LEN completed interrupt enable [RW] (0x1[3])
58+
uint32_t _reserved2 : 4; //!< (0x1[4:7])
59+
uint32_t TX_TRANS_LEN : 12; //!< TX data length (bits), 0: unlimited [RW] (0x1[8:19])
60+
uint32_t RX_TRANS_LEN : 12; //!< RX data length (bits), 0: unlimited [RW] (0x1[20:31])
61+
};
62+
63+
uint32_t config;
64+
};
65+
#endif
66+
67+
#if LT_BK7231N || LT_BK7271
68+
union {
69+
struct {
70+
uint32_t _reserved3 : 1; //!< (0x2[0])
71+
uint32_t TX_FIFO_WR_READY : 1; //!< TX FIFO write allowed [R] (0x2[1])
72+
uint32_t RX_FIFO_RD_READY : 1; //!< RX FIFO read allowed [R] (0x2[2])
73+
uint32_t _reserved4 : 1; //!< (0x2[3])
74+
uint32_t _reserved5 : 4; //!< (0x2[4:7])
75+
uint32_t TX_FIFO_INT : 1; //!< TX FIFO interrupt (1: clear) [RW] (0x2[8])
76+
uint32_t RX_FIFO_INT : 1; //!< RX FIFO interrupt (1: clear) [RW] (0x2[9])
77+
uint32_t SLV_RELEASE_INT : 1; //!< Slave release interrupt (1: clear) [RW] (0x2[10])
78+
uint32_t TX_UDF_INT : 1; //!< TX FIFO underflow interrupt (1: clear) [RW] (0x2[11])
79+
uint32_t RX_OVF_INT : 1; //!< RX FIFO overflow interrupt (1: clear) [RW] (0x2[12])
80+
uint32_t TX_FINISH_INT : 1; //!< TX_TRANS_LEN completed interrupt [R] (0x2[13])
81+
uint32_t RX_FINISH_INT : 1; //!< RX_TRANS_LEN completed interrupt [R] (0x2[14])
82+
uint32_t _reserved6 : 1; //!< (0x2[15])
83+
uint32_t TX_FIFO_CLR : 1; //!< TX FIFO clear enable [W] (0x2[16])
84+
uint32_t RX_FIFO_CLR : 1; //!< RX FIFO clear enable [W] (0x2[17])
85+
uint32_t _reserved7 : 14; //!< (0x2[18:31])
86+
};
87+
88+
uint32_t status;
89+
};
90+
#else
91+
union {
92+
struct {
93+
uint32_t TX_FIFO_EMPTY : 1; //!< (0x1[0])
94+
uint32_t TX_FIFO_FULL : 1; //!< (0x1[1])
95+
uint32_t RX_FIFO_EMPTY : 1; //!< (0x1[2])
96+
uint32_t RX_FIFO_FULL : 1; //!< (0x1[3])
97+
uint32_t _reserved8 : 4; //!< (0x2[4:7])
98+
uint32_t TX_FIFO_INT : 1; //!< TX FIFO interrupt (1: clear) [RW] (0x2[8])
99+
uint32_t RX_FIFO_INT : 1; //!< RX FIFO interrupt (1: clear) [RW] (0x2[9])
100+
uint32_t MODF : 1; //!< (0x1[10])
101+
uint32_t TX_UDF_INT : 1; //!< TX FIFO underflow interrupt (1: clear) [RW] (0x2[11])
102+
uint32_t RX_OVF_INT : 1; //!< RX FIFO overflow interrupt (1: clear) [RW] (0x2[12])
103+
uint32_t _reserved9 : 1; //!< (0x1[13])
104+
uint32_t SLVSEL : 1; //!< (0x1[14])
105+
uint32_t SPIBUSY : 1; //!< (0x1[15])
106+
uint32_t _reserved10 : 16; //!< (0x1[16:31])
107+
};
108+
109+
uint32_t status;
110+
};
111+
#endif
112+
113+
union {
114+
struct {
115+
uint32_t SPI_DAT : 16; //!< FIFO read/write operation [RW] (0x2[0:15])
116+
uint32_t _reserved11 : 16; //!< (0x2[16:31])
117+
};
118+
119+
uint32_t data;
120+
};
121+
122+
#if !(LT_BK7231N || LT_BK7271)
123+
union {
124+
struct {
125+
uint32_t _reserved12 : 1; //!< (0x3[0])
126+
uint32_t S_CS_UP_INT_EN : 1; //!< (0x3[1])
127+
uint32_t _reserved13 : 2; //!< (0x3[2:3])
128+
uint32_t S_CS_UP_INT_STATUS : 1; //!< (0x3[4])
129+
uint32_t _reserved14 : 27; //!< (0x3[5:31])
130+
};
131+
132+
uint32_t slave_ctrl;
133+
};
134+
#endif
135+
} spi_hw_t;
136+
137+
#if LT_BK7271
138+
#define REG_SPI0 ((spi_hw_t *)0x00802500)
139+
#define REG_SPI1 ((spi_hw_t *)0x00802540)
140+
#define REG_SPI2 ((spi_hw_t *)0x00802580)
141+
#else
142+
#define REG_SPI0 ((spi_hw_t *)0x00802700)
143+
#endif

cores/beken-72xx/arduino/src/lt_defs.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,6 @@
44

55
#define LT_ARD_HAS_WIFI 1
66
#define LT_ARD_HAS_SERIAL 1
7+
#define LT_ARD_HAS_SPI 1
78
#define LT_ARD_HAS_WIRE 1
89
#define LT_ARD_MD5_HOSTAPD 1

cores/beken-72xx/base/sdk_private.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ extern "C" {
2424
#include <pwm_pub.h>
2525
#include <rtos_pub.h>
2626
#include <saradc_pub.h>
27+
#include <spi_pub.h>
2728
#include <start_type_pub.h>
2829
#include <sys_ctrl.h>
2930
#include <sys_rtos.h>

0 commit comments

Comments
 (0)