AC63_BT_SDK/cpu/br23/spi_test.c
2025-02-18 15:40:42 +08:00

278 lines
7.4 KiB
C
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "system/includes.h"
#include "media/includes.h"
#include "asm/spi.h"
#include "generic/log.h"
#if 0
/*
[[[ README ]]]
1. 本spi测试demo提供了spi.c的API使用例程测试方式为两个spi的环回测试。
spi1设置为主机模式spi2设置为从机模式spi1发送数据到spi2然后接收spi2
原样返回的数据,然后比较发送出去的数据与接收的数据是否一致,一致则说明
验证通过。
2. 本demo涉及BYTE收发测试及DMA收发测试通过宏SPI_TEST_MODE选择。另外
demo还涉及到spi中断中调用可用于中断的spi API的使用。
3. spi.c的API不包含CS引脚CS由API以外控制。
4. 请在board_xxx.c中定义配置结构体例如用到spi1需要定义spi1_p_data
否则编译出错。
5. spi的DMA地址需要4字节对齐。
6. 虽然spi.c的API带有spi0但在有挂spi flash的芯片上使用可能会出问题
避免使用spi0。
*/
#define SPI1_CS_OUT() \
do { \
JL_PORTB->DIR &= ~BIT(4); \
JL_PORTB->DIE |= BIT(4); \
JL_PORTB->PU &= ~BIT(4); \
JL_PORTB->PD &= ~BIT(4); \
} while(0)
#define SPI1_CS_L() (JL_PORTB->OUT &= ~BIT(4))
#define SPI1_CS_H() (JL_PORTB->OUT |= BIT(4))
#define SPI2_CS_IN() \
do { \
JL_PORTA->DIR |= BIT(3); \
JL_PORTA->DIE |= BIT(3); \
JL_PORTA->PU &= ~BIT(3); \
JL_PORTA->PD &= ~BIT(3); \
} while (0)
#define SPI2_READ_CS() (JL_PORTA->IN & BIT(3))
static u8 slave_dir = 1;
static u8 spi1_send_buf[100] __attribute__((aligned(4)));
static u8 spi1_recv_buf[100] __attribute__((aligned(4)));
static u8 spi2_send_buf[100] __attribute__((aligned(4)));
static u8 spi2_recv_buf[100] __attribute__((aligned(4)));
static spi_dev spi1_hdl = 1;
static spi_dev spi2_hdl = 2;
#define SPI_TEST_BYTE_MODE 0x01
#define SPI_TEST_DMA_MODE 0x02
//测试模式选择
#define SPI_TEST_MODE SPI_TEST_BYTE_MODE
static void my_put_u8hex(u8 b)
{
u8 dat;
dat = b / 16;
if (dat >= 0 && dat <= 9) {
putchar('0' + dat);
} else {
putchar('A' + dat - 10);
}
dat = b % 16;
if (dat >= 0 && dat <= 9) {
putchar('0' + dat);
} else {
putchar('A' + dat - 10);
}
putchar(' ');
}
//中断函数,需以下特殊声明
__attribute__((interrupt("")))
static void spi2_isr()
{
static int i = 0;
if (spi_get_pending(spi2_hdl)) {
spi_clear_pending(spi2_hdl);
if (SPI2_READ_CS()) {
return;
}
#if SPI_TEST_MODE == SPI_TEST_BYTE_MODE
if (slave_dir == 1) {
spi2_recv_buf[i] = spi_recv_byte_for_isr(spi2_hdl);
spi_send_byte_for_isr(spi2_hdl, spi2_recv_buf[i]);
i >= 100 ? i = 0 : i++;
slave_dir = 0;
} else {
slave_dir = 1;
}
#elif SPI_TEST_MODE == SPI_TEST_DMA_MODE
if (slave_dir == 1) {
spi_dma_set_addr_for_isr(spi2_hdl, spi2_recv_buf, 100, 0);
slave_dir = 0;
} else {
slave_dir = 1;
}
#endif
}
}
#if 1 //仅用于spi demo正式工程请放到board_xxx.c文件中
/* const struct spi_platform_data spi0_p_data = { */
/* .port = 'A', */
/* .mode = SPI_MODE_BIDIR_1BIT, */
/* .clk = 1000000, */
/* .role = SPI_ROLE_MASTER, */
/* }; */
const struct spi_platform_data spi1_p_data = {
.port = 'A',
.mode = SPI_MODE_BIDIR_1BIT,
.clk = 1000000,
.role = SPI_ROLE_MASTER,
};
const struct spi_platform_data spi2_p_data = {
.port = 'A',
.mode = SPI_MODE_BIDIR_1BIT,
.clk = 1000000,
.role = SPI_ROLE_SLAVE,
};
#endif
void spi_test_main()
{
int i;
int err;
spi_open(spi1_hdl);
spi_open(spi2_hdl);
spi_set_ie(spi2_hdl, 1);
//配置中断优先级,中断函数
request_irq(IRQ_SPI2_IDX, 3, spi2_isr, 0);
SPI1_CS_OUT();
SPI2_CS_IN();
SPI1_CS_H();
for (i = 0; i < 100; i++) {
spi1_send_buf[i] = i % 26 + 'A';
spi1_recv_buf[i] = 0;
}
puts(">>> spi test start\n");
#if SPI_TEST_MODE == SPI_TEST_BYTE_MODE
SPI1_CS_L();
for (i = 0; i < 100; i++) {
err = spi_send_byte(spi1_hdl, spi1_send_buf[i]);
if (err) {
puts("spi1 byte send timeout\n");
break;
}
delay(100);
spi1_recv_buf[i] = spi_recv_byte(spi1_hdl, &err);
if (err) {
puts("spi1 byte recv timeout\n");
break;
}
delay(100);
}
SPI1_CS_H();
#elif SPI_TEST_MODE == SPI_TEST_DMA_MODE
spi_dma_set_addr_for_isr(spi2_hdl, spi2_recv_buf, 100, 1);
SPI1_CS_L();
err = spi_dma_send(spi1_hdl, spi1_send_buf, 100);
if (err < 0) {
puts("spi1 dma send timeout\n");
goto __out_dma;
}
//delay(100);
err = spi_dma_recv(spi1_hdl, spi1_recv_buf, 100);
if (err < 0) {
puts("spi1 dma recv timeout\n");
goto __out_dma;
}
//delay(100);
__out_dma:
SPI1_CS_H();
#endif
puts("<<< spi test end\n");
puts("\nspi master receivce buffer:\n");
for (i = 0; i < 100; i++) {
//my_put_u8hex(spi1_recv_buf[i]);
putchar(spi1_recv_buf[i]), putchar(0x20);
if (i % 16 == 15) {
putchar('\n');
}
}
if (i % 16) {
putchar('\n');
}
if (!memcmp(spi1_send_buf, spi1_recv_buf, 100)) {
puts("\nspi test pass\n");
} else {
puts("\nspi test fail\n");
}
spi_close(spi1_hdl);
spi_close(spi2_hdl);
}
#else
//蓝牙SPI debug时打开
#if 0
/* 配置要使用的 CS 脚 */
/* 为了省IO其实可以不用CS脚也能被ellisys分辨出来或者在ellisys端将CS脚接地 */
#define SPI1_PORT JL_PORTA
#define SPI1_PORT_BIT 1
#define SPI1_CS_OUT() \
do { \
SPI1_PORT->DIR &= ~BIT(SPI1_PORT_BIT); \
SPI1_PORT->DIE |= BIT(SPI1_PORT_BIT); \
SPI1_PORT->PU &= ~BIT(SPI1_PORT_BIT); \
SPI1_PORT->PD &= ~BIT(SPI1_PORT_BIT); \
} while(0)
#define SPI1_CS_L() (SPI1_PORT->DIR &= ~BIT(SPI1_PORT_BIT),SPI1_PORT->OUT &= ~BIT(SPI1_PORT_BIT))
#define SPI1_CS_H() (SPI1_PORT->DIR &= ~BIT(SPI1_PORT_BIT),SPI1_PORT->OUT |= BIT(SPI1_PORT_BIT))
typedef const int spi_dev;
extern int spi_open(spi_dev spi);
extern int spi_dma_send(spi_dev spi, const void *buf, u32 len);
const struct spi_platform_data spi2_p_data = {
.port = {
IO_PORTA_02, //CLK
IO_PORTA_03, //DO
IO_PORTA_01, //DI
},
.mode = SPI_MODE_BIDIR_1BIT,
.clk = 5000000,
.role = SPI_ROLE_MASTER,
};
const struct spi_platform_data spi1_p_data = {
.port = 'B',
/* .port = { */
/* #<{(| IO_PORTC_00, // CLK |)}># */
/* #<{(| IO_PORTC_01, // DO对应ellisys的DI |)}># */
/* #<{(| IO_PORTC_02, // DI对应ellisys的DO |)}># */
/* */
/* IO_PORTA_05, // */
/* IO_PORTA_06, // */
/* IO_PORTA_07, // */
/* }, */
.mode = SPI_MODE_BIDIR_1BIT,
.clk = 5000000, /* 经测试 ellisys 能分辨到这个速度 */
.role = SPI_ROLE_MASTER,
};
static spi_dev spi1_hdl = 1;
static u8 spi1_send_buf[512] ALIGNED(4);
void bb_spi_init(void)
{
r_printf("spi_open:%08x\n", spi_open);
spi_open(spi1_hdl);
/* SPI1_CS_OUT(); */
/* SPI1_CS_H(); */
}
void bb_spi_send(const void const *buf, size_t len)
{
memcpy(spi1_send_buf, buf, len);
/* SPI1_CS_L(); */
spi_dma_send(spi1_hdl, spi1_send_buf, len);
/* SPI1_CS_H(); */
}
#endif
#endif