Skip to content

Commit 0fc2b13

Browse files
- SPI is now supported on ls2k1000 platform.
- Multi-Port & Adjustable Buadrate of UART controller feature added.
1 parent 11132bc commit 0fc2b13

File tree

4 files changed

+373
-9
lines changed

4 files changed

+373
-9
lines changed

bsp/ls2kdev/drivers/board.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ void rt_hw_board_init(void)
9090
/* init hardware UART device */
9191
rt_hw_uart_init();
9292
/* set console device */
93-
rt_console_set_device("uart");
93+
rt_console_set_device("uart0");
9494
#endif
9595

9696
#ifdef RT_USING_HEAP

bsp/ls2kdev/drivers/drv_spi.c

Lines changed: 269 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,269 @@
1+
#include <stdio.h>
2+
#include <stdlib.h>
3+
#include <ctype.h>
4+
5+
#include <rtthread.h>
6+
#include <drivers/spi.h>
7+
8+
#include "drv_spi.h"
9+
10+
#ifdef RT_USING_SPI
11+
12+
13+
14+
static void spi_init(uint8_t spre_spr,uint8_t copl,uint8_t cpha)
15+
{
16+
//rt_kprintf("SPI initiating with spre_spr:%2X ,copl:%2X ,cpha:%2X\n",spre_spr,copl,cpha);
17+
int d;
18+
SET_SPI(SPSR, 0xc0|(spre_spr&0b00000011));
19+
SET_SPI(PARAM, 0x40);
20+
SET_SPI(PARAM2,0x01);
21+
SET_SPI(SPER, (spre_spr&0b00001100)>>2);
22+
SET_SPI(SPCR, 0x50|copl<<3|cpha<<2);
23+
SET_SPI(SOFTCS,0xff);
24+
}
25+
26+
27+
static void spi_set_csn(uint8_t val) //old method
28+
{
29+
SET_SPI(SOFTCS,val);
30+
}
31+
// #define RT_USING_SPI_GPIOCS
32+
33+
#ifdef RT_USING_SPI_GPIOCS
34+
#include <drivers/pin.h>
35+
#endif
36+
static void spi_set_cs(unsigned char cs, int new_status)
37+
{
38+
39+
if(cs<4){
40+
unsigned char val = 0;
41+
42+
val = GET_SPI(SOFTCS);
43+
val |= 0x01 << cs ; // csen=1
44+
if (new_status) // cs = 1
45+
{
46+
val |= (0x10 << cs); // csn=1
47+
}
48+
else // cs = 0
49+
{
50+
val &= ~(0x10 << cs); // csn=0
51+
}
52+
SET_SPI(SOFTCS,val);
53+
54+
return ;
55+
}
56+
#ifdef RT_USING_SPI_GPIOCS
57+
else{
58+
//rt_kprintf("[Warnning] GPIOCS is an experimental feature: \n ");
59+
//rt_kprintf("[Warnning] GPIO%d will be set to OUTPUT with value %d \n ",cs,new_status);
60+
rt_pin_mode(cs,PIN_MODE_OUTPUT);
61+
rt_pin_write(cs,new_status);
62+
}
63+
#endif
64+
}
65+
66+
static uint8_t spi_write_for_response(uint8_t data)
67+
{
68+
uint8_t val;
69+
SET_SPI(TXFIFO,data);
70+
while((GET_SPI(SPSR))&RFEMPTY);//wait for echo
71+
val = GET_SPI(RXFIFO);
72+
return val;
73+
}
74+
75+
76+
77+
static int cmd_spi_init(int argc,char* argv[])
78+
{
79+
uint8_t spre_spr,cpol,cpha;
80+
switch (argc)
81+
{
82+
case 2:
83+
84+
spre_spr=strtoul(argv[1], NULL, 0);
85+
spi_init(spre_spr,0,0);
86+
break;
87+
case 4:
88+
89+
spre_spr=strtoul(argv[1], NULL, 0);
90+
cpol=strtoul(argv[2], NULL, 0);
91+
cpha=strtoul(argv[3], NULL, 0);
92+
spi_init(spre_spr,0,0);
93+
break;
94+
95+
default:
96+
printf("\nusage : cmd_spi_init spre_spr <cpol> <cpha>\n(cmd_spi_init 0x4 0x0 0x0)\n0x4:div8 0xb:div4096\n");
97+
break;
98+
}
99+
}
100+
MSH_CMD_EXPORT(cmd_spi_init,cmd_spi_init);
101+
102+
static int cmd_spi_set_csn(int argc,char* argv[])
103+
{
104+
uint8_t val,csn;
105+
switch (argc)
106+
{
107+
case 3:
108+
csn=strtoul(argv[1], NULL, 0);
109+
val=strtoul(argv[2], NULL, 0);
110+
spi_set_cs(csn,val);
111+
break;
112+
113+
default:
114+
printf("usage:cmd_spi_set_csn csn val\n(0xbf for csn1 enable,0xff for csn1 disable)\n");
115+
break;
116+
}
117+
}
118+
MSH_CMD_EXPORT(cmd_spi_set_csn,cmd_spi_set_csn);
119+
120+
static int cmd_spi_write(int argc,char* argv[])
121+
{
122+
uint8_t data,resp;
123+
switch (argc)
124+
{
125+
case 2:
126+
127+
data=strtoul(argv[1], NULL, 0);
128+
resp=spi_write_for_response(data);
129+
printf("resp:%2X\n",resp);
130+
break;
131+
132+
default:
133+
printf("usage:cmd_spi_write data\n");
134+
break;
135+
}
136+
}
137+
MSH_CMD_EXPORT(cmd_spi_write,cmd_spi_write);
138+
139+
140+
static rt_err_t configure(struct rt_spi_device *device, struct rt_spi_configuration *configuration);
141+
static rt_uint32_t xfer(struct rt_spi_device *device, struct rt_spi_message *message);
142+
143+
const static unsigned char SPI_DIV_TABLE[]={0b0000,0b0001,0b0100,0b0010,0b0011,0b0101,0b0110,0b0111,0b1000,0b1001,0b1010,0b1011};
144+
// 2 4 8 16 32 64 128 256 512 1024 2048 4096
145+
static rt_err_t configure(struct rt_spi_device *device,
146+
struct rt_spi_configuration *configuration)
147+
{
148+
149+
150+
unsigned char cpol = 0;
151+
unsigned char cpha = 0;
152+
153+
154+
RT_ASSERT(NULL != device);
155+
RT_ASSERT(NULL != configuration);
156+
157+
158+
// baudrate
159+
if (configuration->mode & RT_SPI_CPOL) // cpol
160+
{
161+
cpol = 1;
162+
}
163+
else
164+
{
165+
cpol = 0;
166+
}
167+
if (configuration->mode & RT_SPI_CPHA) // cpha
168+
{
169+
cpha = 1;
170+
}
171+
else
172+
{
173+
cpha = 0;
174+
}
175+
//rt_kprintf("configure: cpol:%d cpha:%d\n",cpol,cpha);
176+
177+
178+
float spi_max_speed=((float)APB_MAX_SPEED)/(8.0/(float)APB_FREQSCALE);
179+
//rt_kprintf("spi max speed: %ld\n",(unsigned long)spi_max_speed);
180+
181+
182+
uint64_t div=(uint64_t)(spi_max_speed/(float)configuration->max_hz);
183+
//rt_kprintf("require speed: %ld\n",configuration->max_hz);
184+
int ctr=0;
185+
while(div!=1 && ctr<12){
186+
ctr++;
187+
div=div>>1;
188+
}
189+
//rt_kprintf("spi speed set to: %ld\n",(unsigned long)((spi_max_speed)/(float)(1<<ctr)));
190+
spi_init(SPI_DIV_TABLE[ctr],cpol,cpha);
191+
192+
193+
return RT_EOK;
194+
}
195+
196+
static rt_uint32_t xfer(struct rt_spi_device *device,
197+
struct rt_spi_message *message)
198+
{
199+
200+
201+
//rt_kprintf("xfer:\n");
202+
unsigned char cs = 0;
203+
rt_uint32_t size = 0;
204+
const rt_uint8_t *send_ptr = NULL;
205+
rt_uint8_t *recv_ptr = NULL;
206+
rt_uint8_t data = 0;
207+
208+
RT_ASSERT(NULL != device);
209+
RT_ASSERT(NULL != message);
210+
211+
cs =(unsigned char )(device->parent.user_data);
212+
size = message->length;
213+
214+
//rt_kprintf("[%s] cs=%d\n", __FUNCTION__, cs);
215+
216+
// take cs
217+
if (message->cs_take)
218+
{
219+
spi_set_cs(cs, 0);
220+
}
221+
222+
// send data
223+
send_ptr = message->send_buf;
224+
recv_ptr = message->recv_buf;
225+
while (size--)
226+
{
227+
data = 0xFF;
228+
if (NULL != send_ptr)
229+
{
230+
data = *send_ptr++;
231+
}
232+
233+
if (NULL != recv_ptr)
234+
{
235+
*recv_ptr++ = spi_write_for_response(data);
236+
}
237+
else
238+
{
239+
spi_write_for_response(data);
240+
}
241+
}
242+
243+
// release cs
244+
if (message->cs_release)
245+
{
246+
spi_set_cs(cs, 1);
247+
}
248+
249+
return message->length;
250+
}
251+
252+
static struct rt_spi_ops loongson_spi_ops =
253+
{
254+
.configure = configure,
255+
.xfer = xfer
256+
};
257+
258+
static struct rt_spi_bus loongson_spi;
259+
260+
static int loongson_spi_init()
261+
{
262+
//rt_kprintf("spi_init\n");
263+
return rt_spi_bus_register(&loongson_spi,"spi",&loongson_spi_ops);
264+
}
265+
266+
INIT_BOARD_EXPORT(loongson_spi_init);
267+
268+
269+
#endif

bsp/ls2kdev/drivers/drv_spi.h

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
#ifndef DRV_SPI_H
2+
#define DRV_SPI_H
3+
4+
#include <rtthread.h>
5+
#include <rthw.h>
6+
7+
8+
9+
#define RFEMPTY 1
10+
#define KSEG1_STORE8(addr,val) *(volatile char *)(0xffffffffa0000000 | addr) = val
11+
#define KSEG1_LOAD8(addr) *(volatile char *)(0xffffffffa0000000 | addr)
12+
13+
#define APB_MAX_SPEED 125000000U
14+
#define APB_FREQSCALE (((KSEG1_LOAD8(0xffffffffbfe104d2)>>4)&0x7)+1)
15+
16+
#define SPI_BASE 0x1fff0220
17+
#define PMON_ADDR 0xa1000000
18+
#define FLASH_ADDR 0x000000
19+
20+
#define SPCR 0x0
21+
#define SPSR 0x1
22+
#define FIFO 0x2
23+
#define TXFIFO 0x2
24+
#define RXFIFO 0x2
25+
#define SPER 0x3
26+
#define PARAM 0x4
27+
#define SOFTCS 0x5
28+
#define PARAM2 0x6
29+
30+
31+
32+
33+
#define SET_SPI(addr,val) KSEG1_STORE8(SPI_BASE+addr,val)
34+
#define GET_SPI(addr) KSEG1_LOAD8(SPI_BASE+addr)
35+
36+
37+
38+
//void spi_init(uint8_t ,uint8_t,uint8_t);
39+
//void spi_set_csn(uint8_t);
40+
//uint8_t spi_write_for_response(uint8_t);
41+
42+
43+
#endif

0 commit comments

Comments
 (0)