123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277 |
- #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 spi1_p_data = {
- .port = {
- IO_PORTB_06, //CLK
- IO_PORTB_07, //DO
- IO_PORTB_05, //DI
- },
- .mode = SPI_MODE_BIDIR_1BIT,
- .clk = 1000000,
- .role = SPI_ROLE_MASTER,
- };
- const struct spi_platform_data spi2_p_data = {
- .port = {
- IO_PORTB_02, //CLK
- IO_PORTB_03, //DO
- IO_PORTB_01, //DI
- },
- .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
- #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 = {
- /* IO_PORTC_00, // CLK */
- /* IO_PORTC_01, // DO,对应ellisys的DI */
- /* IO_PORTC_02, // DI,对应ellisys的DO */
- IO_PORTA_06, //
- IO_PORTA_07, //
- IO_PORTA_08, //
- },
- .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
|