Skip to content

Commit

Permalink
modify spi slave demo
Browse files Browse the repository at this point in the history
  • Loading branch information
xiangbingj committed Mar 15, 2019
1 parent 61d238d commit e86330d
Show file tree
Hide file tree
Showing 8 changed files with 354 additions and 154 deletions.
7 changes: 0 additions & 7 deletions spi_slave/README.md

This file was deleted.

13 changes: 13 additions & 0 deletions spi_slave/README.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
Hardware diagram:

MASTER SLAVE

+-- INT -- -0.6M pullup
CS ----------------+-- CS

CLK ------------------- CLK

DAT ------------------- DAT

INT ------------------- RDY

99 changes: 78 additions & 21 deletions spi_slave/main.c
Original file line number Diff line number Diff line change
@@ -1,30 +1,87 @@
#include <stdio.h>
/* Copyright 2018 Canaan Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "spi_slave.h"
#include "spi_master.h"
#include <devices.h>
#include <stdio.h>
#include "project_cfg.h"

//#define MASTER_MODE

#ifdef MASTER_MODE
static uint8_t test_data[1024];
#else
static uint8_t slave_cfg[32];
static uint8_t test_data_tmp[1024];
#endif

int main(void)
{
uint8_t index;
#ifdef MASTER_MODE
printf("spi master init\n");
spi_master_init();
spi_slave_init();

printf("spi slave test\n");

printf("spi write\n");
for (index = 0; index < SLAVE_MAX_ADDR; index++)
spi_write_reg(index, index+0x10000);
printf("spi read\n");
for (index = 0; index < SLAVE_MAX_ADDR; index++)
{
if (index+0x10000 != spi_read_reg(index))
{
printf("_TEST_FAIL_\n");
return 0;
}
#else
printf("spi slave init\n");
*(uint32_t *)(&slave_cfg[8]) = (uint32_t)test_data_tmp;
spi_slave_init(slave_cfg, 32);
#endif

printf("System start\n");
#ifdef MASTER_MODE
for (uint32_t i = 0; i < 8; i++)
test_data[i] = i;
spi_master_transfer(test_data, 0, 8, WRITE_CONFIG);
for (uint32_t i = 0; i < 8; i++)
test_data[i] = 0;
spi_master_transfer(test_data, 0, 8, READ_CONFIG);
for (uint32_t i = 0; i < 8; i++) {
if (test_data[i] != (uint8_t)i)
printf("%d: 0x%02x," ,i, test_data[i]);
}
printf("\n");

uint32_t addr;
spi_master_transfer((uint8_t *)&addr, 8, 4, READ_CONFIG);

for (uint32_t i = 0; i < 8; i++)
test_data[i] = i;
spi_master_transfer(test_data, addr, 8, WRITE_DATA_BYTE);
for (uint32_t i = 0; i < 8; i++)
test_data[i] = 0;
spi_master_transfer(test_data, addr, 8, READ_DATA_BYTE);
for (uint32_t i = 0; i < 8; i++) {
if (test_data[i] != (uint8_t)i)
printf("%d: 0x%02x," ,i, test_data[i]);
}
printf("\n");

for (uint32_t i = 0; i < 1024; i++)
test_data[i] = i;
spi_master_transfer(test_data, addr, 1024, WRITE_DATA_BLOCK);
for (uint32_t i = 0; i < 1024; i++)
test_data[i] = 0;
spi_master_transfer(test_data, addr, 1024, READ_DATA_BLOCK);
for (uint32_t i = 0; i < 1024; i++) {
if (test_data[i] != (uint8_t)i)
printf("%d: 0x%02x," ,i, test_data[i]);
}
printf("spi slave test ok\n");
printf("_TEST_PASS_\n");
while(1)
printf("\n");

printf("test finish\n");
#endif
while (1)
;
return 0;
}

36 changes: 28 additions & 8 deletions spi_slave/project_cfg.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,19 +16,39 @@
#define _PROJECT_CFG_H_
#include <pin_cfg.h>

#define SPI_SLAVE_INT_PIN 18
#define SPI_SLAVE_INT_IO 4
#define SPI_SLAVE_READY_PIN 22
#define SPI_SLAVE_READY_IO 5
#define SPI_SLAVE_CS_PIN 19
#define SPI_SLAVE_CLK_PIN 20
#define SPI_SLAVE_MOSI_PIN 21
#define SPI_SLAVE_MISO_PIN 21

#define SPI_MASTER_INT_PIN 28
#define SPI_MASTER_INT_IO 6
#define SPI_MASTER_CS_PIN 25
#define SPI_MASTER_CS_IO 7
#define SPI_MASTER_CLK_PIN 26
#define SPI_MASTER_MOSI_PIN 27
#define SPI_MASTER_MISO_PIN 27

const fpioa_cfg_t g_fpioa_cfg =
{
.version = PIN_CFG_VERSION,
.functions_count = 7,
.functions_count = 5 + 4,
.functions =
{
{32, FUNC_SPI0_SCLK},
{34, FUNC_SPI0_SS0},
{36, FUNC_SPI0_D0},
{38, FUNC_SPI0_D1},
{33, FUNC_SPI_SLAVE_SCLK},
{35, FUNC_SPI_SLAVE_SS},
{37, FUNC_SPI_SLAVE_D0}
{SPI_SLAVE_CS_PIN, FUNC_SPI_SLAVE_SS},
{SPI_SLAVE_CLK_PIN, FUNC_SPI_SLAVE_SCLK},
{SPI_SLAVE_MOSI_PIN, FUNC_SPI_SLAVE_D0},
{SPI_SLAVE_INT_PIN, FUNC_GPIOHS0 + SPI_SLAVE_INT_IO},
{SPI_SLAVE_READY_PIN, FUNC_GPIOHS0 + SPI_SLAVE_READY_IO},

{SPI_MASTER_CLK_PIN, FUNC_SPI0_SCLK},
{SPI_MASTER_MOSI_PIN, FUNC_SPI0_D0},
{SPI_MASTER_CS_PIN, FUNC_GPIOHS0 + SPI_MASTER_CS_IO},
{SPI_MASTER_INT_PIN, FUNC_GPIOHS0 + SPI_MASTER_INT_IO},
}
};

Expand Down
149 changes: 149 additions & 0 deletions spi_slave/spi_master.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
/* Copyright 2018 Canaan Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "spi_master.h"
#include "fpioa.h"
#include <stdio.h>
#include <devices.h>

#define WAIT_TIMEOUT 0xFFFFFF
#define SPI_MASTER_INT_PIN 28
#define SPI_MASTER_INT_IO 6
#define SPI_MASTER_CS_PIN 25
#define SPI_MASTER_CS_IO 7
#define SPI_MASTER_CLK_PIN 26
#define SPI_MASTER_MOSI_PIN 27
#define SPI_MASTER_MISO_PIN 27

static volatile uint8_t spi_slave_ready;

static void spi_slave_ready_irq(uint32_t pin, void *userdata);

static handle_t gio;

static handle_t spi0;
static uintptr_t spi_stand;

int spi_master_init(void)
{
gio = io_open("/dev/gpio0");
configASSERT(gio);

spi0 = io_open("/dev/spi0");
configASSERT(spi0);
spi_stand = spi_get_device(spi0, SPI_MODE_0, SPI_FF_STANDARD, 1, 8);
spi_dev_set_clock_rate(spi_stand, 100000);

gpio_set_drive_mode(gio, SPI_MASTER_CS_IO, GPIO_DM_OUTPUT);
gpio_set_pin_value(gio, SPI_MASTER_CS_IO, GPIO_PV_HIGH);

gpio_set_drive_mode(gio, SPI_MASTER_INT_IO, GPIO_DM_INPUT_PULL_UP);
gpio_set_pin_edge(gio, SPI_MASTER_INT_IO, GPIO_PE_FALLING);
gpio_set_on_changed(gio, SPI_MASTER_INT_IO, (gpio_on_changed_t)spi_slave_ready_irq, NULL);

return 0;
}

static void spi_slave_ready_irq(uint32_t pin, void *userdata)
{
spi_slave_ready = 1;
}

static int spi_receive_data(uint8_t *data, uint32_t len)
{
fpioa_set_function(SPI_MASTER_MISO_PIN, FUNC_SPI0_D1);
gpio_set_pin_value(gio, SPI_MASTER_CS_IO, GPIO_PV_LOW);

io_read(spi_stand, (uint8_t *)data, len);

gpio_set_pin_value(gio, SPI_MASTER_CS_IO, GPIO_PV_HIGH);
fpioa_set_function(SPI_MASTER_MOSI_PIN, FUNC_SPI0_D0);
return 0;
}

static int spi_send_data(uint8_t *data, uint32_t len)
{
gpio_set_pin_value(gio, SPI_MASTER_CS_IO, GPIO_PV_LOW);

io_write(spi_stand, (const uint8_t *)data, len);

gpio_set_pin_value(gio, SPI_MASTER_CS_IO, GPIO_PV_HIGH);
return 0;
}

static int spi_master_send_cmd(spi_slave_command_t *cmd)
{
uint8_t data[8];

for (uint32_t i = 0; i < WAIT_TIMEOUT; i++)
{
if (gpio_get_pin_value(gio, SPI_MASTER_INT_IO) == 1)
break;
}
if (gpio_get_pin_value(gio, SPI_MASTER_INT_IO) == 0)
return -1;

data[0] = cmd->cmd;
data[1] = cmd->addr;
data[2] = cmd->addr >> 8;
data[3] = cmd->addr >> 16;
data[4] = cmd->addr >> 24;
data[5] = cmd->len;
data[6] = cmd->len >> 8;
data[7] = 0;
for (uint32_t i = 0; i < 7; i++)
data[7] += data[i];
spi_slave_ready = 0;
spi_send_data(data, 8);
for (uint32_t i = 0; i < WAIT_TIMEOUT; i++)
{
if (spi_slave_ready != 0)
break;
}
if (spi_slave_ready)
return 0;
else
return -2;
}

int spi_master_transfer(uint8_t *data, uint32_t addr, uint32_t len, uint8_t mode)
{
spi_slave_command_t cmd;

if (mode <= READ_DATA_BYTE)
{
if (len > 8)
len = 8;
cmd.len = len;
}
else if (mode <= READ_DATA_BLOCK)
{
if (len > 0x100000)
len = 0x100000;
addr &= 0xFFFFFFF0;
cmd.len = len >> 4;
}
else
return -1;
cmd.cmd = mode;
cmd.addr = addr;
if (spi_master_send_cmd(&cmd) != 0)
return -2;
if (mode & 0x01)
spi_receive_data(data, len);
else
spi_send_data(data, len);
return 0;
}

23 changes: 23 additions & 0 deletions spi_slave/spi_master.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/* Copyright 2018 Canaan Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef __SPI_MASTER__
#define __SPI_MASTER__

#include <stdint.h>

int spi_master_init(void);
int spi_master_transfer(uint8_t *data, uint32_t addr, uint32_t len, uint8_t mode);

#endif
Loading

0 comments on commit e86330d

Please sign in to comment.