/**************************************************************************** Copyright(c) 2019 by Aerospace C.Power (Chongqing) Microelectronics. ALL RIGHTS RESERVED. This Information is proprietary to Aerospace C.Power (Chongqing) Microelectronics and MAY NOT be copied by any method or incorporated into another program without the express written consent of Aerospace C.Power. This Information or any portion thereof remains the property of Aerospace C.Power. The Information contained herein is believed to be accurate and Aerospace C.Power assumes no responsibility or liability for its use in any way and conveys no license or title under any patent or copyright and makes no representation or warranty that this Information is free from patent or copyright infringement. ****************************************************************************/ /* Copied on iot_gpio_simu_spi.c and slightly modified */ #include "os_types.h" #include "gpio_hw.h" #include "clk.h" #include "uart.h" #include "iot_gpio.h" #include "iot_clock.h" #include "iot_errno.h" #include "iot_io_api.h" #include "iot_gpio_api.h" #include "fdma_mst_protocol.h" #define IRQ_DISABLE() #define IRQ_ENABLE() #define USE_HAL_API 1 #if !USE_HAL_API static volatile int clk_val = 0; #endif static void cs_high(void) { #if USE_HAL_API iot_gpio_value_set(GPIO_S_CS, 1); #else hw_gpio_api_table.set_value(GPIO_S_CS, 1); #endif } static void cs_low(void) { #if USE_HAL_API iot_gpio_value_set(GPIO_S_CS, 0); #else hw_gpio_api_table.set_value(GPIO_S_CS, 0); #endif } static void clk_overturn(void) { #if USE_HAL_API int val = 0; iot_gpio_output_value_get(GPIO_S_CLK, &val); iot_gpio_value_set(GPIO_S_CLK, val^1); #else for (volatile uint32_t i = 0; i < 10; i++); hw_gpio_api_table.set_value(GPIO_S_CLK, !clk_val); clk_val = !clk_val; #endif } static void spi_write_byte(unsigned char d) { int i; for (i = 15; i >= 0; i--) { // From high 7 to low 0 written sequentially. #if USE_HAL_API iot_gpio_value_set(GPIO_S_MS, d & (1 << i / 2)); #else hw_gpio_api_table.set_value(GPIO_S_MS, d & (1 << i / 2)); #endif clk_overturn(); } } static int iot_s_spi_write_data(int dev, char* buf, int wt_size) { int i; for (i = 0; i < wt_size; i++) { spi_write_byte(buf[i]); } return 0; } static uint8_t spi_read_byte(void) { int i; uint8_t r = 0; for (i = 0; i <= 15; i++) { // From high 7 to low 0 serial readout clk_overturn(); #if USE_HAL_API r = r | ((uint8_t)iot_gpio_value_get(GPIO_S_MS) << (7 - i / 2)); #else r = r | ((uint8_t)hw_gpio_api_table.get_value(GPIO_S_MS) << (7 - i / 2)); #endif } return r; } static uint32_t iot_s_spi_read_data(int dev, int rd_size) { int i; uint32_t data = 0; #if USE_HAL_API iot_gpio_close(GPIO_S_MS); iot_gpio_open_as_input(GPIO_S_MS); #else hw_gpio_api_table.set_value(GPIO_S_MS, 0); hw_gpio_api_table.set_gpio_mode(GPIO_S_MS, GPIO_INPUT); #endif // Read in teh data. for (i = 0; i < rd_size; i++) { data = data | ((uint32_t)spi_read_byte() << (8 * (rd_size - 1 - i))); } #if USE_HAL_API iot_gpio_close(GPIO_S_MS); iot_gpio_open_as_output(GPIO_S_MS); iot_gpio_value_set(GPIO_S_CLK, 0); iot_gpio_value_set(GPIO_S_MS, 1); #else hw_gpio_api_table.set_gpio_mode(GPIO_S_MS, GPIO_OUTPUT); hw_gpio_api_table.set_value(GPIO_S_CLK, 1); clk_val = 1; hw_gpio_api_table.set_value(GPIO_S_MS, 1); #endif return data; } // purpose:Shake hands with slave static void spi_start(void) { uint16_t i; #if USE_HAL_API iot_gpio_value_set(GPIO_S_CLK, 1); #else hw_gpio_api_table.set_value(GPIO_S_CLK, 0); clk_val = 0; #endif iot_delay_us(100); // iot_delay_us_cpu_cycle(100); for (i = 0; i < 15; i++) { #if USE_HAL_API iot_gpio_value_set(GPIO_S_MS, 1); #else hw_gpio_api_table.set_value(GPIO_S_MS, 1); #endif clk_overturn(); } cs_low(); } // purpose:goodbye with slave static void spi_end(void) { uint16_t i; for (i = 0; i < 14; i++) { #if USE_HAL_API iot_gpio_value_set(GPIO_S_MS, 1); #else hw_gpio_api_table.set_value(GPIO_S_MS, 1); #endif clk_overturn(); } #if USE_HAL_API iot_gpio_value_set(GPIO_S_CLK, 1); iot_gpio_value_set(GPIO_S_MS, 1); #else hw_gpio_api_table.set_value(GPIO_S_CLK, 1); clk_val = 1; hw_gpio_api_table.set_value(GPIO_S_MS, 1); #endif cs_high(); } void iot_spi_fdma_master_write(uint32_t addr, uint32_t w_lenth, uint32_t* w_data) { uint32_t fifo[2]; uint16_t i; uint32_t data_temp; fifo[0] = NTOHL(FMST_SET_CMD(FMST_CMD_WRITE, w_lenth)); fifo[1] = NTOHL(addr); IRQ_DISABLE(); spi_start(); iot_s_spi_write_data(INVALID_DRIVER, (char*)fifo, sizeof(fifo)); for (i = 0; i < w_lenth; i++) { data_temp = NTOHL(w_data[i]); iot_s_spi_write_data(INVALID_DRIVER, (char*)&data_temp, sizeof(uint32_t)); } spi_end(); IRQ_ENABLE(); } uint16_t iot_spi_fdma_master_read(uint32_t addr, uint32_t r_lenth, uint32_t* rx_buff) { uint32_t fifo[2]; uint32_t fifo2[1]; uint16_t i; if (!r_lenth) { return ERR_FAIL; } fifo[0] = NTOHL(FMST_SET_CMD(FMST_CMD_READ_ALLOCATE, r_lenth)); fifo[1] = NTOHL(addr); IRQ_DISABLE(); spi_start(); iot_s_spi_write_data(INVALID_DRIVER, (char*)fifo, sizeof(fifo)); spi_end(); fifo2[0] = NTOHL(FMST_SET_CMD(FMST_CMD_READ_FETCH, r_lenth)); spi_start(); iot_s_spi_write_data(INVALID_DRIVER, (char*)fifo2, sizeof(fifo2)); for (i = 0; i < r_lenth;) { rx_buff[i] = iot_s_spi_read_data(INVALID_DRIVER, sizeof(uint32_t)); i++; } #if USE_HAL_API iot_gpio_value_set(GPIO_S_CLK, 1); iot_gpio_value_set(GPIO_S_MS, 1); #else hw_gpio_api_table.set_value(GPIO_S_CLK, 1); clk_val = 1; hw_gpio_api_table.set_value(GPIO_S_MS, 1); #endif cs_high(); IRQ_ENABLE(); return ERR_OK; } uint16_t iot_spi_fdma_master_get_debuginfo(uint32_t id, uint32_t* rx_buff) { uint32_t cmd; uint16_t i; cmd = NTOHL(FMST_SET_CMD(FMST_CMD_MODULE_STS, id)); IRQ_DISABLE(); spi_start(); iot_s_spi_write_data(INVALID_DRIVER, (char*)&cmd, sizeof(cmd)); for (i = 0; i < 8; i++) { rx_buff[i] = iot_s_spi_read_data(INVALID_DRIVER, sizeof(uint32_t)); } #if USE_HAL_API iot_gpio_value_set(GPIO_S_CLK, 1); iot_gpio_value_set(GPIO_S_MS, 1); #else hw_gpio_api_table.set_value(GPIO_S_CLK, 1); clk_val = 1; hw_gpio_api_table.set_value(GPIO_S_MS, 1); #endif cs_high(); IRQ_ENABLE(); return ERR_OK; } void iot_spi_fdma_master_reset_cpu(void) { uint32_t cmd; cmd = NTOHL(FMST_SET_CMD(FMST_CMD_CPU_RESET, 0)); IRQ_DISABLE(); spi_start(); iot_s_spi_write_data(INVALID_DRIVER, (char*)&cmd, sizeof(cmd)); spi_end(); IRQ_ENABLE(); } void iot_spi_fdma_master_reset_release_cpu(void) { uint32_t cmd; cmd = NTOHL(FMST_SET_CMD(FMST_CMD_CPU_RESET_RELEASE, 0)); IRQ_DISABLE(); spi_start(); iot_s_spi_write_data(INVALID_DRIVER, (char*)&cmd, sizeof(cmd)); spi_end(); IRQ_ENABLE(); } uint16_t iot_spi_fdma_master_ping(uint32_t* rx_buff) { uint32_t cmd; uint16_t i; cmd = NTOHL(FMST_SET_CMD(FMST_CMD_PING, 0)); IRQ_DISABLE(); spi_start(); iot_s_spi_write_data(INVALID_DRIVER, (char*)&cmd, sizeof(cmd)); for (i = 0; i < 4; i++) { rx_buff[i] = iot_s_spi_read_data(INVALID_DRIVER, sizeof(uint32_t)); } #if USE_HAL_API iot_gpio_value_set(GPIO_S_CLK, 1); iot_gpio_value_set(GPIO_S_MS, 1); #else hw_gpio_api_table.set_value(GPIO_S_CLK, 1); clk_val = 1; hw_gpio_api_table.set_value(GPIO_S_MS, 1); #endif cs_high(); IRQ_ENABLE(); return ERR_OK; } void iot_spi_fdma_master_nop(void) { uint32_t cmd; cmd = NTOHL(FMST_SET_CMD(FMST_CMD_NOP, 0)); IRQ_DISABLE(); spi_start(); iot_s_spi_write_data(INVALID_DRIVER, (char*)&cmd, sizeof(cmd)); spi_end(); IRQ_ENABLE(); }