diff --git a/spi_slave/README.md b/spi_slave/README.md deleted file mode 100644 index f4d936f..0000000 --- a/spi_slave/README.md +++ /dev/null @@ -1,7 +0,0 @@ -SPI slave test -===== -"project_cfg.h" is the hardware related configuration files. Include pin config ... -"project.cmake" include hal lib."fpioa_set_function" need. ... - -1.Write data to SPI slave device .Get data from SPI salve device. -2.Hardware connection:IO32-IO33 IO34-IO35 IO36-IO37 \ No newline at end of file diff --git a/spi_slave/README.txt b/spi_slave/README.txt new file mode 100644 index 0000000..f3909f6 --- /dev/null +++ b/spi_slave/README.txt @@ -0,0 +1,13 @@ +Hardware diagram: + + MASTER SLAVE + + +-- INT -- -0.6M pullup + CS ----------------+-- CS + + CLK ------------------- CLK + + DAT ------------------- DAT + + INT ------------------- RDY + diff --git a/spi_slave/main.c b/spi_slave/main.c index 145fd4f..92f6cbb 100644 --- a/spi_slave/main.c +++ b/spi_slave/main.c @@ -1,30 +1,87 @@ -#include +/* 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 +#include #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; } + diff --git a/spi_slave/project_cfg.h b/spi_slave/project_cfg.h index a96f27b..e8dd755 100644 --- a/spi_slave/project_cfg.h +++ b/spi_slave/project_cfg.h @@ -16,19 +16,39 @@ #define _PROJECT_CFG_H_ #include +#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}, } }; diff --git a/spi_slave/spi_master.c b/spi_slave/spi_master.c new file mode 100644 index 0000000..6c12d45 --- /dev/null +++ b/spi_slave/spi_master.c @@ -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 +#include + +#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; +} + diff --git a/spi_slave/spi_master.h b/spi_slave/spi_master.h new file mode 100644 index 0000000..161561a --- /dev/null +++ b/spi_slave/spi_master.h @@ -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 + +int spi_master_init(void); +int spi_master_transfer(uint8_t *data, uint32_t addr, uint32_t len, uint8_t mode); + +#endif diff --git a/spi_slave/spi_slave.c b/spi_slave/spi_slave.c index 04ac5b7..3178636 100644 --- a/spi_slave/spi_slave.c +++ b/spi_slave/spi_slave.c @@ -1,104 +1,46 @@ -#include -#include -#include -#include -#include "spi_slave.h" -#include "fpioa.h" -#include "FreeRTOS.h" -#include "task.h" -#include "semphr.h" - -#define CHIP_SELECT 1 -handle_t spi0; -uintptr_t spi_stand; -handle_t spi_slave; - -slave_info_t spi_slave_device; -spi_slave_handler_t spi_slave_handler; - -void spi_slave_receive(uint32_t data) -{ - if(data & 0x40000000) - { - if (spi_slave_device.acces_reg < SLAVE_MAX_ADDR) - spi_slave_device.reg_data[spi_slave_device.acces_reg] = data & 0x3FFFFFFF; - spi_slave_device.acces_reg = SLAVE_MAX_ADDR; - } - else - { - spi_slave_device.acces_reg = (data & 0x3FFFFFFF); - } -} - -uint32_t spi_slave_transmit(uint32_t data) -{ - uint32_t ret = 0; - spi_slave_device.acces_reg = (data & 0x3FFFFFFF); - if (spi_slave_device.acces_reg < SLAVE_MAX_ADDR) - ret = spi_slave_device.reg_data[spi_slave_device.acces_reg]; - else - ret = 0xFF; - spi_slave_device.acces_reg = SLAVE_MAX_ADDR; - return ret; -} - -spi_slave_event_t spi_slave_event(uint32_t data) -{ - if(data & 0x80000000) - return SPI_EV_RECV; - else - return SPI_EV_TRANS; -} - -void spi_slave_init(void) -{ - spi_slave = io_open("/dev/spi_slave"); - configASSERT(spi_slave); - spi_slave_handler.on_event = spi_slave_event, - spi_slave_handler.on_receive = spi_slave_receive, - spi_slave_handler.on_transmit = spi_slave_transmit, - - spi_slave_config(spi_slave, 32, &spi_slave_handler); -} - -void spi_master_init(void) -{ - spi0 = io_open("/dev/spi0"); - configASSERT(spi0); - spi_stand = spi_get_device(spi0, SPI_MODE_0, SPI_FF_STANDARD, CHIP_SELECT, 32); - spi_dev_set_clock_rate(spi_stand, 23000000); -} - -void spi_write_reg(uint32_t reg, uint32_t data) -{ - uint32_t reg_value = reg | 0x80000000; - uint32_t data_value = data | 0xc0000000; - uint8_t* tmp_buf = malloc(4 + 4); - memcpy(tmp_buf, ®_value, 4); - memcpy(tmp_buf + 4, &data_value, 4); - taskENTER_CRITICAL(); - io_write(spi_stand, (uint8_t *)tmp_buf, 4 + 4); - taskEXIT_CRITICAL(); - free(tmp_buf); -} - -uint32_t spi_read_reg(uint32_t reg) -{ - uint32_t value = 0; - - uint32_t reg_value = reg & 0x7FFFFFFF; - taskENTER_CRITICAL(); - io_write(spi_stand, (uint8_t *)®_value, 4); - taskEXIT_CRITICAL(); - - fpioa_set_function(36, FUNC_SPI0_D1); - fpioa_set_function(38, FUNC_SPI0_D0); - taskENTER_CRITICAL(); - io_read(spi_stand, (uint8_t *)&value, 4); - taskEXIT_CRITICAL(); - fpioa_set_function(36, FUNC_SPI0_D0); - fpioa_set_function(38, FUNC_SPI0_D1); - return value; -} - - +/* 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 +#include + +#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 + +static handle_t gio; +static handle_t spi_slave; + +int spi_slave_receive_hook(void *data) +{ + printf("%d\n", ((spi_slave_command_t *)data)->err); + return 0; +} + +int spi_slave_init(uint8_t *data, uint32_t len) +{ + gio = io_open("/dev/gpio0"); + configASSERT(gio); + spi_slave = io_open("/dev/spi_slave"); + configASSERT(spi_slave); + spi_slave_config(spi_slave, gio, SPI_SLAVE_INT_IO, SPI_SLAVE_READY_IO, 8, data, len, spi_slave_receive_hook); + + return 0; +} diff --git a/spi_slave/spi_slave.h b/spi_slave/spi_slave.h index 4917257..0b5b8a2 100644 --- a/spi_slave/spi_slave.h +++ b/spi_slave/spi_slave.h @@ -1,19 +1,22 @@ -#ifndef _SPI_SLAVE_H -#define _SPI_SLAVE_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. + */ +#ifndef __SPI_SLAVE__ +#define __SPI_SLAVE__ #include -#define SLAVE_MAX_ADDR 15 - -typedef struct _slave_info -{ - uint32_t acces_reg; - uint32_t reg_data[SLAVE_MAX_ADDR]; -} slave_info_t; - -void spi_master_init(void); -void spi_slave_init(void); -void spi_write_reg(uint32_t reg, uint32_t data); -uint32_t spi_read_reg(uint32_t reg); +int spi_slave_init(uint8_t *data, uint32_t len); #endif