mirror of
https://github.com/jialexd/sdk-ameba-v4.0c_180328.git
synced 2024-12-01 02:30:32 +00:00
652 lines
21 KiB
C
652 lines
21 KiB
C
|
/******************************************************************************
|
||
|
*
|
||
|
* Copyright(c) 2007 - 2015 Realtek Corporation. All rights reserved.
|
||
|
*
|
||
|
*
|
||
|
******************************************************************************/
|
||
|
|
||
|
#include <platform_opts.h>
|
||
|
|
||
|
#if CONFIG_EXAMPLE_SPI_ATCMD
|
||
|
|
||
|
#include "FreeRTOS.h"
|
||
|
#include "task.h"
|
||
|
#include <platform/platform_stdlib.h>
|
||
|
#include "semphr.h"
|
||
|
#include "device.h"
|
||
|
#include "osdep_api.h"
|
||
|
#include "osdep_service.h"
|
||
|
#include "device_lock.h"
|
||
|
|
||
|
#include "spi_atcmd/example_spi_atcmd.h"
|
||
|
|
||
|
#include "at_cmd/log_service.h"
|
||
|
#include "at_cmd/atcmd_wifi.h"
|
||
|
#include "at_cmd/atcmd_lwip.h"
|
||
|
|
||
|
#include "flash_api.h"
|
||
|
|
||
|
#include "spi_api.h"
|
||
|
#include "spi_ex_api.h"
|
||
|
|
||
|
#include "gpio_irq_api.h"
|
||
|
#include "gpio_irq_ex_api.h"
|
||
|
|
||
|
/**** SPI FUNCTIONS ****/
|
||
|
spi_t spi_obj;
|
||
|
gpio_t gpio_cs;
|
||
|
|
||
|
#define SPI_RX_BUFFER_SIZE ATSTRING_LEN/2
|
||
|
#define SPI_TX_BUFFER_SIZE ATSTRING_LEN/2
|
||
|
uint16_t spi_chunk_buffer[ATSTRING_LEN/2];
|
||
|
|
||
|
_Sema master_rx_done_sema;
|
||
|
_Sema master_tx_done_sema;
|
||
|
|
||
|
#define SPI_USE_STREAM (0)
|
||
|
#define SPI_USE_DMA (1)
|
||
|
|
||
|
/**** SLAVE HARDWARE READY ****/
|
||
|
gpio_t gpio_hrdy;
|
||
|
|
||
|
#define SPI_SLAVE_BUSY 0
|
||
|
#define SPI_SLAVE_READY 1
|
||
|
|
||
|
volatile int spi_slave_status = SPI_SLAVE_BUSY;
|
||
|
_Sema spi_check_hrdy_sema;
|
||
|
|
||
|
#define BLOCKING 1
|
||
|
#define NONBLOCKING 0
|
||
|
|
||
|
volatile int hrdy_pull_down_counter = 0;
|
||
|
|
||
|
/**** SLAVE SYNC ****/
|
||
|
|
||
|
gpio_irq_t gpio_sync;
|
||
|
|
||
|
#define SPI_STATE_MISO 0
|
||
|
#define SPI_STATE_MOSI 1
|
||
|
|
||
|
int spi_state = SPI_STATE_MISO;
|
||
|
|
||
|
/**** TASK THREAD ****/
|
||
|
|
||
|
_Sema spi_check_trx_sema;
|
||
|
|
||
|
/**** LOG SERVICE ****/
|
||
|
char at_string[ATSTRING_LEN];
|
||
|
|
||
|
extern char log_buf[LOG_SERVICE_BUFLEN];
|
||
|
extern xSemaphoreHandle log_rx_interrupt_sema;
|
||
|
|
||
|
#define LOG_TX_BUFFER_SIZE 48*1024
|
||
|
char log_tx_buffer[LOG_TX_BUFFER_SIZE];
|
||
|
uint32_t log_tx_idx = 0;
|
||
|
uint32_t log_rx_idx = 0;
|
||
|
|
||
|
/**** DATA FORMAT ****/
|
||
|
#define PREAMBLE_COMMAND 0x6000
|
||
|
#define PREAMBLE_DATA_READ 0x1000
|
||
|
#define PREAMBLE_DATA_WRITE 0x0000
|
||
|
|
||
|
#define COMMAND_DUMMY 0x0000
|
||
|
#define COMMAND_BEGIN 0x0304
|
||
|
#define COMMAND_END 0x0305
|
||
|
#define COMMAND_READ_BEGIN 0x0012
|
||
|
#define COMMAND_READ_RAW 0x0013
|
||
|
#define COMMAND_WRITE_BEGIN 0x0014
|
||
|
#define COMMAND_READ_WRITE_END 0x0015
|
||
|
|
||
|
#define REGISTER_ADDR 0x2000
|
||
|
|
||
|
void atcmd_update_partition_info(AT_PARTITION id, AT_PARTITION_OP ops, u8 *data, u16 len) {
|
||
|
flash_t flash;
|
||
|
int size, offset, i;
|
||
|
u32 read_data;
|
||
|
|
||
|
switch(id){
|
||
|
case AT_PARTITION_SPI:
|
||
|
size = SPI_CONF_DATA_SIZE;
|
||
|
offset = SPI_CONF_DATA_OFFSET;
|
||
|
break;
|
||
|
case AT_PARTITION_WIFI:
|
||
|
size = WIFI_CONF_DATA_SIZE;
|
||
|
offset = WIFI_CONF_DATA_OFFSET;
|
||
|
break;
|
||
|
case AT_PARTITION_LWIP:
|
||
|
size = LWIP_CONF_DATA_SIZE;
|
||
|
offset = LWIP_CONF_DATA_OFFSET;
|
||
|
break;
|
||
|
case AT_PARTITION_ALL:
|
||
|
size = 0x1000;
|
||
|
offset = 0;
|
||
|
break;
|
||
|
default:
|
||
|
printf("partition id is invalid!\r\n");
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
device_mutex_lock(RT_DEV_LOCK_FLASH);
|
||
|
|
||
|
if(id == AT_PARTITION_ALL && ops == AT_PARTITION_ERASE){
|
||
|
flash_erase_sector(&flash, SPI_SETTING_SECTOR);
|
||
|
goto exit;
|
||
|
}
|
||
|
|
||
|
if(ops == AT_PARTITION_READ){
|
||
|
flash_stream_read(&flash, SPI_SETTING_SECTOR+offset, len, data);
|
||
|
goto exit;
|
||
|
}
|
||
|
|
||
|
//erase BACKUP_SECTOR
|
||
|
flash_erase_sector(&flash, SPI_SETTING_BACKUP_SECTOR);
|
||
|
|
||
|
if(ops == AT_PARTITION_WRITE){
|
||
|
// backup new data
|
||
|
flash_stream_write(&flash, SPI_SETTING_BACKUP_SECTOR+offset, len, data);
|
||
|
}
|
||
|
|
||
|
//backup front data to backup sector
|
||
|
for(i = 0; i < offset; i += sizeof(read_data)){
|
||
|
flash_read_word(&flash, SPI_SETTING_SECTOR + i, &read_data);
|
||
|
flash_write_word(&flash, SPI_SETTING_BACKUP_SECTOR + i,read_data);
|
||
|
}
|
||
|
|
||
|
//backup rear data
|
||
|
for(i = (offset + size); i < 0x1000; i += sizeof(read_data)){
|
||
|
flash_read_word(&flash, SPI_SETTING_SECTOR + i, &read_data);
|
||
|
flash_write_word(&flash, SPI_SETTING_BACKUP_SECTOR + i,read_data);
|
||
|
}
|
||
|
|
||
|
//erase UART_SETTING_SECTOR
|
||
|
flash_erase_sector(&flash, SPI_SETTING_SECTOR);
|
||
|
|
||
|
//retore data to UART_SETTING_SECTOR from UART_SETTING_BACKUP_SECTOR
|
||
|
for(i = 0; i < 0x1000; i+= sizeof(read_data)){
|
||
|
flash_read_word(&flash, SPI_SETTING_BACKUP_SECTOR + i, &read_data);
|
||
|
flash_write_word(&flash, SPI_SETTING_SECTOR + i,read_data);
|
||
|
}
|
||
|
|
||
|
//erase BACKUP_SECTOR
|
||
|
flash_erase_sector(&flash, SPI_SETTING_BACKUP_SECTOR);
|
||
|
|
||
|
exit:
|
||
|
device_mutex_unlock(RT_DEV_LOCK_FLASH);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
/* AT cmd V2 API */
|
||
|
void spi_at_send_string(char *str) {
|
||
|
spi_at_send_buf(str, strlen(str));
|
||
|
}
|
||
|
|
||
|
/* AT cmd V2 API */
|
||
|
void spi_at_send_buf(u8 *buf, u32 len) {
|
||
|
int i;
|
||
|
int spi_tx_tail_next;
|
||
|
|
||
|
if( !len || (!buf) ){
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if (buf == log_tx_buffer) {
|
||
|
log_tx_idx = len;
|
||
|
} else {
|
||
|
for (i=0; i<len; i++) {
|
||
|
if (log_tx_idx == LOG_TX_BUFFER_SIZE) {
|
||
|
// overflow!
|
||
|
break;
|
||
|
}
|
||
|
log_tx_buffer[log_tx_idx++] = buf[i];
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (__get_IPSR() != 0) {
|
||
|
RtlUpSema(&spi_check_trx_sema);
|
||
|
} else {
|
||
|
RtlUpSemaFromISR(&spi_check_trx_sema);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* IRQ handler called when SPI TX/RX finish */
|
||
|
void master_trx_done_callback(void *pdata, SpiIrq event) {
|
||
|
switch(event){
|
||
|
case SpiRxIrq:
|
||
|
RtlUpSemaFromISR(&master_rx_done_sema);
|
||
|
//DBG_8195A("Master RX done!\n");
|
||
|
break;
|
||
|
case SpiTxIrq:
|
||
|
//DBG_8195A("Master TX done!\n");
|
||
|
break;
|
||
|
default:
|
||
|
DBG_8195A("unknown interrput evnent!\n");
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* IRQ handler called when SPI TX finish */
|
||
|
static void master_tx_done_callback(uint32_t id) {
|
||
|
RtlUpSemaFromISR(&master_tx_done_sema);
|
||
|
}
|
||
|
|
||
|
/* IRQ handler as gpio hrdy hit rising edge */
|
||
|
void slave_hrdy_change_callback(uint32_t id) {
|
||
|
gpio_irq_disable(&gpio_hrdy);
|
||
|
|
||
|
if (spi_slave_status == SPI_SLAVE_BUSY) {
|
||
|
// Transition from LOW to HIGH. Change to listen IRQ_LOW
|
||
|
spi_slave_status = SPI_SLAVE_READY;
|
||
|
hrdy_pull_down_counter++;
|
||
|
|
||
|
gpio_irq_set(&gpio_hrdy, IRQ_LOW, 1);
|
||
|
gpio_irq_enable(&gpio_hrdy);
|
||
|
} else {
|
||
|
// Transition from HIGH to LOW. Change to listen IRQ_HIGH
|
||
|
spi_slave_status = SPI_SLAVE_BUSY;
|
||
|
|
||
|
gpio_irq_set(&gpio_hrdy, IRQ_HIGH, 1);
|
||
|
gpio_irq_enable(&gpio_hrdy);
|
||
|
}
|
||
|
|
||
|
RtlUpSemaFromISR(&spi_check_hrdy_sema);
|
||
|
}
|
||
|
|
||
|
/* IRQ Handler as gpio sync state change */
|
||
|
void slave_sync_chagne_callback(uint32_t id)
|
||
|
{
|
||
|
gpio_irq_disable(&gpio_sync);
|
||
|
|
||
|
if (spi_state == SPI_STATE_MISO) {
|
||
|
// Transition from LOW to HIGH. Change to listen IRQ_LOW
|
||
|
spi_state = SPI_STATE_MOSI;
|
||
|
|
||
|
gpio_irq_set(&gpio_sync, IRQ_LOW, 1);
|
||
|
gpio_irq_enable(&gpio_sync);
|
||
|
} else {
|
||
|
// Transition from HIGH to LOW. Change to listen IRQ_HIGH
|
||
|
spi_state = SPI_STATE_MISO;
|
||
|
|
||
|
gpio_irq_set(&gpio_sync, IRQ_HIGH, 1);
|
||
|
gpio_irq_enable(&gpio_sync);
|
||
|
}
|
||
|
|
||
|
RtlUpSemaFromISR(&spi_check_trx_sema);
|
||
|
}
|
||
|
|
||
|
void spi_atcmd_main(void)
|
||
|
{
|
||
|
wifi_disable_powersave();
|
||
|
|
||
|
// read settings
|
||
|
SPI_LOG_CONF spiconf;
|
||
|
spiconf.bits = 16;
|
||
|
spiconf.frequency = 20000000;
|
||
|
spiconf.mode = (SPI_SCLK_IDLE_LOW|SPI_SCLK_TOGGLE_MIDDLE);
|
||
|
|
||
|
// init spi
|
||
|
spi_init(&spi_obj, SPI0_MOSI, SPI0_MISO, SPI0_SCLK, SPI0_CS);
|
||
|
spi_frequency(&spi_obj, spiconf.frequency);
|
||
|
spi_format(&spi_obj, spiconf.bits, spiconf.mode, 0);
|
||
|
|
||
|
spi_bus_tx_done_irq_hook(&spi_obj, master_tx_done_callback, (uint32_t)&spi_obj);
|
||
|
spi_irq_hook(&spi_obj, master_trx_done_callback, (uint32_t)&spi_obj);
|
||
|
|
||
|
// init simulated spi cs
|
||
|
gpio_init(&gpio_cs, GPIO_CS);
|
||
|
gpio_dir(&gpio_cs, PIN_OUTPUT);
|
||
|
gpio_mode(&gpio_cs, PullNone);
|
||
|
gpio_write(&gpio_cs, 1);
|
||
|
|
||
|
// init gpio for check if spi slave hw ready
|
||
|
gpio_init(&gpio_hrdy, GPIO_HRDY);
|
||
|
gpio_dir(&gpio_hrdy, PIN_INPUT);
|
||
|
gpio_mode(&gpio_hrdy, PullDown);
|
||
|
|
||
|
gpio_irq_init(&gpio_hrdy, GPIO_HRDY, slave_hrdy_change_callback, (uint32_t)&gpio_hrdy);
|
||
|
gpio_irq_set(&gpio_hrdy, IRQ_HIGH, 1);
|
||
|
gpio_irq_enable(&gpio_hrdy);
|
||
|
|
||
|
// init gpio for check if spi slave want to send data
|
||
|
gpio_irq_init(&gpio_sync, GPIO_SYNC, slave_sync_chagne_callback,(uint32_t)&gpio_sync);
|
||
|
gpio_irq_set(&gpio_sync, IRQ_HIGH, 1);
|
||
|
gpio_irq_enable(&gpio_sync);
|
||
|
|
||
|
// init semaphore for check hardware ready
|
||
|
RtlInitSema(&spi_check_hrdy_sema, 1);
|
||
|
RtlDownSema(&spi_check_hrdy_sema);
|
||
|
|
||
|
// init semaphore that makes spi tx/rx thread to check something
|
||
|
RtlInitSema(&spi_check_trx_sema, 1);
|
||
|
RtlDownSema(&spi_check_trx_sema);
|
||
|
|
||
|
// init semaphore for master tx
|
||
|
RtlInitSema(&master_tx_done_sema, 1);
|
||
|
RtlDownSema(&master_tx_done_sema);
|
||
|
|
||
|
// init semaphore for master rx
|
||
|
RtlInitSema(&master_rx_done_sema, 1);
|
||
|
RtlDownSema(&master_rx_done_sema);
|
||
|
}
|
||
|
|
||
|
int32_t spi_master_send(spi_t *obj, char *tx_buffer, uint32_t length) {
|
||
|
hrdy_pull_down_counter = 0;
|
||
|
spi_master_write_stream_dma(obj, tx_buffer, length);
|
||
|
RtlDownSema(&master_tx_done_sema);
|
||
|
|
||
|
if (spi_slave_status == SPI_SLAVE_BUSY) {
|
||
|
while (hrdy_pull_down_counter == 0);
|
||
|
hrdy_pull_down_counter = 0;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
int32_t spi_master_recv(spi_t *obj, char *rx_buffer, uint32_t length) {
|
||
|
hrdy_pull_down_counter = 0;
|
||
|
spi_flush_rx_fifo(obj);
|
||
|
spi_master_read_stream_dma(obj, rx_buffer, length);
|
||
|
RtlDownSema(&master_rx_done_sema);
|
||
|
RtlDownSema(&master_tx_done_sema);
|
||
|
|
||
|
if (spi_slave_status == SPI_SLAVE_BUSY) {
|
||
|
while (hrdy_pull_down_counter == 0);
|
||
|
hrdy_pull_down_counter = 0;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void atcmd_check_special_case(char *buf) {
|
||
|
int i;
|
||
|
if (strlen(buf) > 4) {
|
||
|
if (strncmp(buf, "ATPT", 4) == 0) {
|
||
|
for (i=0; i<strlen(buf); i++) {
|
||
|
if (buf[i] == ':') {
|
||
|
buf[i] = '\0';
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static void spi_trx_thread(void *param)
|
||
|
{
|
||
|
uint32_t i;
|
||
|
uint32_t rxlen, txlen;
|
||
|
uint32_t recv_len, recv_remain, send_len;
|
||
|
|
||
|
uint16_t dummy, L_address, H_address, L_size, H_size;
|
||
|
|
||
|
int slave_ready = 0;
|
||
|
do {
|
||
|
slave_ready = gpio_read(&gpio_hrdy);
|
||
|
rtw_msleep_os(1000);
|
||
|
} while(slave_ready == 0);
|
||
|
|
||
|
while(1) {
|
||
|
RtlDownSema(&spi_check_trx_sema);
|
||
|
|
||
|
if (spi_state == SPI_STATE_MOSI) {
|
||
|
if (log_tx_idx > 0) {
|
||
|
/* Slave hw is ready, and Master has something to send. */
|
||
|
|
||
|
// stage A, read target address
|
||
|
txlen = 0;
|
||
|
spi_chunk_buffer[txlen++] = PREAMBLE_COMMAND;
|
||
|
spi_chunk_buffer[txlen++] = COMMAND_BEGIN;
|
||
|
|
||
|
gpio_write(&gpio_cs, 0);
|
||
|
spi_master_send(&spi_obj, spi_chunk_buffer, txlen * 2);
|
||
|
gpio_write(&gpio_cs, 1);
|
||
|
|
||
|
gpio_write(&gpio_cs, 0);
|
||
|
spi_chunk_buffer[0] = PREAMBLE_DATA_READ;
|
||
|
spi_master_send(&spi_obj, spi_chunk_buffer, 1 * 2);
|
||
|
spi_master_recv(&spi_obj, spi_chunk_buffer, 1 * 2);
|
||
|
dummy = spi_chunk_buffer[0];
|
||
|
spi_master_recv(&spi_obj, spi_chunk_buffer, 1 * 2);
|
||
|
L_address = spi_chunk_buffer[0];
|
||
|
spi_master_recv(&spi_obj, spi_chunk_buffer, 1 * 2);
|
||
|
H_address = spi_chunk_buffer[0];
|
||
|
spi_master_recv(&spi_obj, spi_chunk_buffer, 1 * 2);
|
||
|
L_size = spi_chunk_buffer[0];
|
||
|
spi_master_recv(&spi_obj, spi_chunk_buffer, 1 * 2);
|
||
|
H_size = spi_chunk_buffer[0];
|
||
|
gpio_write(&gpio_cs, 1);
|
||
|
|
||
|
// stage B, write data
|
||
|
txlen = 0;
|
||
|
spi_chunk_buffer[txlen++] = PREAMBLE_COMMAND;
|
||
|
spi_chunk_buffer[txlen++] = COMMAND_WRITE_BEGIN;
|
||
|
|
||
|
gpio_write(&gpio_cs, 0);
|
||
|
spi_master_send(&spi_obj, spi_chunk_buffer, txlen * 2);
|
||
|
gpio_write(&gpio_cs, 1);
|
||
|
|
||
|
if (log_tx_idx % 2 != 0) {
|
||
|
log_tx_buffer[log_tx_idx++] = 0;
|
||
|
}
|
||
|
send_len = log_tx_idx / 2;
|
||
|
L_size = send_len & 0x0000FFFF;
|
||
|
H_size = (send_len & 0xFFFF0000) >> 16;
|
||
|
|
||
|
gpio_write(&gpio_cs, 0);
|
||
|
txlen = 1;
|
||
|
spi_chunk_buffer[0] = PREAMBLE_DATA_WRITE;
|
||
|
spi_master_send(&spi_obj, spi_chunk_buffer, txlen * 2);
|
||
|
spi_chunk_buffer[0] = L_address;
|
||
|
spi_master_send(&spi_obj, spi_chunk_buffer, txlen * 2);
|
||
|
spi_chunk_buffer[0] = H_address;
|
||
|
spi_master_send(&spi_obj, spi_chunk_buffer, txlen * 2);
|
||
|
spi_chunk_buffer[0] = L_size;
|
||
|
spi_master_send(&spi_obj, spi_chunk_buffer, txlen * 2);
|
||
|
spi_chunk_buffer[0] = H_size;
|
||
|
spi_master_send(&spi_obj, spi_chunk_buffer, txlen * 2);
|
||
|
gpio_write(&gpio_cs, 1);
|
||
|
|
||
|
gpio_write(&gpio_cs, 0);
|
||
|
txlen = 0;
|
||
|
spi_chunk_buffer[txlen++] = PREAMBLE_DATA_WRITE;
|
||
|
spi_master_send(&spi_obj, spi_chunk_buffer, txlen * 2);
|
||
|
txlen = log_tx_idx/2;
|
||
|
spi_master_send(&spi_obj, log_tx_buffer, txlen * 2); // sending raw data
|
||
|
gpio_write(&gpio_cs, 1);
|
||
|
|
||
|
// stage C, write data end
|
||
|
txlen = 0;
|
||
|
spi_chunk_buffer[txlen++] = PREAMBLE_COMMAND;
|
||
|
spi_chunk_buffer[txlen++] = COMMAND_READ_WRITE_END;
|
||
|
|
||
|
gpio_write(&gpio_cs, 0);
|
||
|
spi_master_send(&spi_obj, spi_chunk_buffer, txlen * 2);
|
||
|
gpio_write(&gpio_cs, 1);
|
||
|
|
||
|
// stage final
|
||
|
txlen = 0;
|
||
|
spi_chunk_buffer[txlen++] = PREAMBLE_COMMAND;
|
||
|
spi_chunk_buffer[txlen++] = COMMAND_END;
|
||
|
|
||
|
gpio_write(&gpio_cs, 0);
|
||
|
spi_master_send(&spi_obj, spi_chunk_buffer, txlen * 2);
|
||
|
gpio_write(&gpio_cs, 1);
|
||
|
|
||
|
L_size = log_tx_idx & 0x0000FFFF;
|
||
|
H_size = (log_tx_idx & 0xFFFF0000) >> 16;
|
||
|
|
||
|
txlen = 0;
|
||
|
spi_chunk_buffer[txlen++] = PREAMBLE_DATA_WRITE;
|
||
|
spi_chunk_buffer[txlen++] = L_size;
|
||
|
|
||
|
gpio_write(&gpio_cs, 0);
|
||
|
spi_master_send(&spi_obj, spi_chunk_buffer, txlen * 2);
|
||
|
gpio_write(&gpio_cs, 1);
|
||
|
|
||
|
txlen = 0;
|
||
|
spi_chunk_buffer[txlen++] = PREAMBLE_DATA_WRITE;
|
||
|
spi_chunk_buffer[txlen++] = H_size;
|
||
|
|
||
|
gpio_write(&gpio_cs, 0);
|
||
|
spi_master_send(&spi_obj, spi_chunk_buffer, txlen * 2);
|
||
|
gpio_write(&gpio_cs, 1);
|
||
|
|
||
|
// finalize
|
||
|
log_tx_idx = 0;
|
||
|
}
|
||
|
|
||
|
} else if (spi_state == SPI_STATE_MISO) {
|
||
|
/* Slave hw is ready, and Slave want to send something. */
|
||
|
do {
|
||
|
// stage A, read target address
|
||
|
txlen = 0;
|
||
|
spi_chunk_buffer[txlen++] = PREAMBLE_COMMAND;
|
||
|
spi_chunk_buffer[txlen++] = COMMAND_BEGIN;
|
||
|
|
||
|
gpio_write(&gpio_cs, 0);
|
||
|
spi_master_send(&spi_obj, spi_chunk_buffer, txlen * 2);
|
||
|
gpio_write(&gpio_cs, 1);
|
||
|
|
||
|
txlen = 0;
|
||
|
spi_chunk_buffer[txlen++] = PREAMBLE_DATA_READ;
|
||
|
|
||
|
gpio_write(&gpio_cs, 0);
|
||
|
spi_master_send(&spi_obj, spi_chunk_buffer, txlen * 2);
|
||
|
spi_master_recv(&spi_obj, spi_chunk_buffer, 1 * 2);
|
||
|
dummy = spi_chunk_buffer[0];
|
||
|
spi_master_recv(&spi_obj, spi_chunk_buffer, 1 * 2);
|
||
|
L_address = spi_chunk_buffer[0];
|
||
|
spi_master_recv(&spi_obj, spi_chunk_buffer, 1 * 2);
|
||
|
H_address = spi_chunk_buffer[0];
|
||
|
spi_master_recv(&spi_obj, spi_chunk_buffer, 1 * 2);
|
||
|
L_size = spi_chunk_buffer[0];
|
||
|
spi_master_recv(&spi_obj, spi_chunk_buffer, 1 * 2);
|
||
|
H_size = spi_chunk_buffer[0];
|
||
|
gpio_write(&gpio_cs, 1);
|
||
|
|
||
|
recv_len = ((H_size << 16) | L_size);
|
||
|
|
||
|
if (recv_len == 0) {
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
// Stage B, confirm addr & len
|
||
|
txlen = 0;
|
||
|
spi_chunk_buffer[txlen++] = PREAMBLE_COMMAND;
|
||
|
spi_chunk_buffer[txlen++] = COMMAND_READ_BEGIN;
|
||
|
|
||
|
gpio_write(&gpio_cs, 0);
|
||
|
spi_master_send(&spi_obj, spi_chunk_buffer, txlen * 2);
|
||
|
gpio_write(&gpio_cs, 1);
|
||
|
|
||
|
gpio_write(&gpio_cs, 0);
|
||
|
txlen = 1;
|
||
|
|
||
|
spi_chunk_buffer[0] = PREAMBLE_DATA_WRITE;
|
||
|
spi_master_send(&spi_obj, spi_chunk_buffer, txlen * 2);
|
||
|
spi_chunk_buffer[0] = L_address;
|
||
|
spi_master_send(&spi_obj, spi_chunk_buffer, txlen * 2);
|
||
|
spi_chunk_buffer[0] = H_address;
|
||
|
spi_master_send(&spi_obj, spi_chunk_buffer, txlen * 2);
|
||
|
spi_chunk_buffer[0] = L_size;
|
||
|
spi_master_send(&spi_obj, spi_chunk_buffer, txlen * 2);
|
||
|
spi_chunk_buffer[0] = H_size;
|
||
|
spi_master_send(&spi_obj, spi_chunk_buffer, txlen * 2);
|
||
|
gpio_write(&gpio_cs, 1);
|
||
|
|
||
|
// Stage C, begin to read
|
||
|
txlen = 0;
|
||
|
spi_chunk_buffer[txlen++] = PREAMBLE_COMMAND;
|
||
|
spi_chunk_buffer[txlen++] = COMMAND_READ_RAW;
|
||
|
|
||
|
gpio_write(&gpio_cs, 0);
|
||
|
spi_master_send(&spi_obj, spi_chunk_buffer, txlen * 2);
|
||
|
gpio_write(&gpio_cs, 1);
|
||
|
|
||
|
txlen = 0;
|
||
|
spi_chunk_buffer[txlen++] = PREAMBLE_DATA_READ;
|
||
|
|
||
|
gpio_write(&gpio_cs, 0);
|
||
|
spi_master_send(&spi_obj, spi_chunk_buffer, txlen * 2);
|
||
|
spi_master_recv(&spi_obj, spi_chunk_buffer, 1 * 2); // recv dummy
|
||
|
rxlen = recv_len;
|
||
|
spi_master_recv(&spi_obj, log_buf, rxlen * 2);
|
||
|
log_buf[rxlen*2]= '\0';
|
||
|
gpio_write(&gpio_cs, 1);
|
||
|
|
||
|
// Stage D, read end
|
||
|
txlen = 0;
|
||
|
spi_chunk_buffer[txlen++] = PREAMBLE_COMMAND;
|
||
|
spi_chunk_buffer[txlen++] = COMMAND_READ_WRITE_END;
|
||
|
|
||
|
gpio_write(&gpio_cs, 0);
|
||
|
spi_master_send(&spi_obj, spi_chunk_buffer, txlen * 2);
|
||
|
gpio_write(&gpio_cs, 1);
|
||
|
|
||
|
// stage final
|
||
|
txlen = 0;
|
||
|
spi_chunk_buffer[txlen++] = PREAMBLE_COMMAND;
|
||
|
spi_chunk_buffer[txlen++] = COMMAND_END;
|
||
|
|
||
|
gpio_write(&gpio_cs, 0);
|
||
|
spi_master_send(&spi_obj, spi_chunk_buffer, txlen * 2);
|
||
|
gpio_write(&gpio_cs, 1);
|
||
|
|
||
|
L_size = (recv_len) & 0x0000FFFF;
|
||
|
H_size = ((recv_len) & 0xFFFF0000) >> 16;
|
||
|
|
||
|
txlen = 0;
|
||
|
spi_chunk_buffer[txlen++] = PREAMBLE_DATA_WRITE;
|
||
|
spi_chunk_buffer[txlen++] = L_size;
|
||
|
|
||
|
gpio_write(&gpio_cs, 0);
|
||
|
spi_master_send(&spi_obj, spi_chunk_buffer, txlen * 2);
|
||
|
gpio_write(&gpio_cs, 1);
|
||
|
|
||
|
txlen = 0;
|
||
|
spi_chunk_buffer[txlen++] = PREAMBLE_DATA_WRITE;
|
||
|
spi_chunk_buffer[txlen++] = H_size;
|
||
|
|
||
|
gpio_write(&gpio_cs, 0);
|
||
|
spi_master_send(&spi_obj, spi_chunk_buffer, txlen * 2);
|
||
|
gpio_write(&gpio_cs, 1);
|
||
|
|
||
|
// finalize
|
||
|
//printf("%s", log_buf);
|
||
|
atcmd_check_special_case(log_buf);
|
||
|
RtlUpSema(&log_rx_interrupt_sema);
|
||
|
taskYIELD();
|
||
|
} while (0);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
vTaskDelete(NULL);
|
||
|
}
|
||
|
|
||
|
static void spi_atcmd_thread(void *param)
|
||
|
{
|
||
|
p_wlan_init_done_callback = NULL;
|
||
|
atcmd_wifi_restore_from_flash();
|
||
|
atcmd_lwip_restore_from_flash();
|
||
|
rtw_msleep_os(20);
|
||
|
spi_atcmd_main();
|
||
|
|
||
|
// the rx_buffer of atcmd is to receive and sending out to log_tx
|
||
|
atcmd_lwip_set_rx_buffer(log_tx_buffer, sizeof(log_tx_buffer));
|
||
|
|
||
|
at_set_debug_mask(0x0);
|
||
|
|
||
|
if(xTaskCreate(spi_trx_thread, ((const char*)"spi_trx_thread"), 4096, NULL, tskIDLE_PRIORITY+1 , NULL) != pdPASS)
|
||
|
printf("\n\r%s xTaskCreate(spi_trx_thread) failed", __FUNCTION__);
|
||
|
|
||
|
vTaskDelete(NULL);
|
||
|
}
|
||
|
|
||
|
int spi_atcmd_module_init(void){
|
||
|
if(xTaskCreate(spi_atcmd_thread, ((const char*)"spi_atcmd_thread"), 1024, NULL, tskIDLE_PRIORITY+1 , NULL) != pdPASS)
|
||
|
printf("\n\r%s xTaskCreate(spi_atcmd_thread) failed", __FUNCTION__);
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
void example_spi_atcmd(void)
|
||
|
{
|
||
|
p_wlan_init_done_callback = spi_atcmd_module_init;
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
#endif // #if CONFIG_EXAMPLE_SPI_ATCMD
|