310 lines
		
	
	
		
			9.2 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			310 lines
		
	
	
		
			9.2 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /****************************************************************************
 | |
| 
 | |
| 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.
 | |
| 
 | |
| ****************************************************************************/
 | |
| #include "os_types.h"
 | |
| #include "encoding.h"
 | |
| #include "platform.h"
 | |
| 
 | |
| #include "gpio_hw.h"
 | |
| #include "gpio_mtx.h"
 | |
| #include "clk.h"
 | |
| #include "apb.h"
 | |
| 
 | |
| #include "uart.h"
 | |
| #include "dbg_io.h"
 | |
| #include "gp_timer.h"
 | |
| #include "iot_irq.h"
 | |
| #include "iot_clock.h"
 | |
| #include "os_mem.h"
 | |
| #include "iot_system.h"
 | |
| 
 | |
| #include "iot_gpio_api.h"
 | |
| #include "os_mem_api.h"
 | |
| #include "iot_io_api.h"
 | |
| #include "iot_errno_api.h"
 | |
| #include "iot_utils_api.h"
 | |
| 
 | |
| #include "fdma_mst_protocol.h"
 | |
| 
 | |
| #define FDMA_MST_CMD_UART       0
 | |
| #define FDMA_MST_CMD_HELP       0x3F    //"?"
 | |
| #define FDMA_MST_CMD_HEADER     0xAA
 | |
| #define FDMA_MST_CMD_TAIL       0x55
 | |
| #define FDMA_MST_CMD_BUF_LEN    64
 | |
| 
 | |
| #define FDMA_MST_SWAP_BUF_LEN   64  //64 * 4 bytes
 | |
| 
 | |
| typedef enum {
 | |
|     FDMA_MST_UART_FSM_IDLE = 0,
 | |
|     FDMA_MST_UART_FSM_GET_HEADER,
 | |
|     FDMA_MST_UART_FSM_GET_CMD_DATA,
 | |
|     FDMA_MST_UART_FSM_WAITING_TAIL,
 | |
|     FDMA_MST_UART_FSM_COMPLETE,
 | |
| } fdma_mst_uart_fsm_t;
 | |
| 
 | |
| typedef enum {
 | |
|     FDMA_MST_CMD_READ = 0,
 | |
|     FDMA_MST_CMD_WRITE,
 | |
|     FDMA_MST_CMD_MAX,
 | |
| } fdma_mst_cmd_type_t;
 | |
| 
 | |
| typedef struct _fdma_mst_cmd_read_t {
 | |
|     uint32_t addr;
 | |
|     uint32_t len;
 | |
| } fdma_mst_cmd_read_t;
 | |
| 
 | |
| typedef struct _fdma_mst_cmd_write_t {
 | |
|     uint32_t addr;
 | |
|     uint32_t len;
 | |
|     uint32_t data[0];
 | |
| } fdma_mst_cmd_write_t;
 | |
| 
 | |
| typedef struct _fdma_mst_uart_cmd_t {
 | |
|     uint8_t fsm;
 | |
|     uint8_t cmd_type;
 | |
|     uint8_t buf_idx;
 | |
|     uint8_t padding;
 | |
|     uint8_t buf[FDMA_MST_CMD_BUF_LEN];  //ensure that is a four byte pair
 | |
| } fdma_mst_uart_cmd_t;
 | |
| 
 | |
| typedef struct _fdma_mst_globle_t {
 | |
|     fdma_mst_uart_cmd_t cmd;
 | |
|     uint32_t swap_buf[FDMA_MST_SWAP_BUF_LEN];
 | |
| } fdma_mst_globle_t;
 | |
| 
 | |
| fdma_mst_globle_t g_fm = {0};
 | |
| 
 | |
| void dtest_fdma_mst_print_usage()
 | |
| {
 | |
|     iot_printf("----------------HELP----------------\n");
 | |
|     iot_printf("| spi_read\n");
 | |
|     iot_printf("| spi_write\n");
 | |
|     iot_printf("| spi_debug\n");
 | |
|     iot_printf("| spi_reset_cpu\n");
 | |
|     iot_printf("| spi_release_cpu\n");
 | |
|     iot_printf("| spi_ping\n");
 | |
|     iot_printf("| spi_nop\n");
 | |
|     iot_printf("------------------------------------\n");
 | |
| }
 | |
| 
 | |
| uint32_t dtest_fdma_mst_get_cmd()
 | |
| {
 | |
|     char get_char = 0;
 | |
|     fdma_mst_cmd_write_t *cmd_write;
 | |
| 
 | |
|     while(1) {
 | |
|         if (uart_e_ctrl.rx_fifo_cnt(FDMA_MST_CMD_UART) == 0) {
 | |
|             continue;
 | |
|         }
 | |
| 
 | |
|         get_char = uart_e_ctrl.getc(FDMA_MST_CMD_UART);
 | |
|         switch (g_fm.cmd.fsm) {
 | |
|         case FDMA_MST_UART_FSM_IDLE:
 | |
|             if (get_char == FDMA_MST_CMD_HEADER) {
 | |
|                 g_fm.cmd.fsm = FDMA_MST_UART_FSM_GET_HEADER;
 | |
|             } else if (get_char == FDMA_MST_CMD_HELP) {
 | |
|                 dtest_fdma_mst_print_usage();
 | |
|             }
 | |
|             break;
 | |
|         case FDMA_MST_UART_FSM_GET_HEADER:
 | |
|             if (g_fm.cmd.cmd_type >= FDMA_MST_CMD_MAX) {
 | |
|                 if (get_char >= FDMA_MST_CMD_MAX) {
 | |
|                     iot_printf("get invalid cmd type:0x%x\n", get_char);
 | |
|                     g_fm.cmd.fsm = FDMA_MST_UART_FSM_IDLE;
 | |
|                 } else {
 | |
|                     g_fm.cmd.cmd_type = get_char;
 | |
|                     g_fm.cmd.fsm = FDMA_MST_UART_FSM_GET_CMD_DATA;
 | |
|                 }
 | |
|             }
 | |
|             break;
 | |
|         case FDMA_MST_UART_FSM_GET_CMD_DATA:
 | |
|             switch(g_fm.cmd.cmd_type) {
 | |
|             case FDMA_MST_CMD_READ:
 | |
|                 g_fm.cmd.buf[g_fm.cmd.buf_idx] = get_char;
 | |
|                 g_fm.cmd.buf_idx++;
 | |
|                 if (g_fm.cmd.buf_idx >= sizeof(fdma_mst_cmd_read_t)) {
 | |
|                     g_fm.cmd.fsm = FDMA_MST_UART_FSM_WAITING_TAIL;
 | |
|                 }
 | |
|                 break;
 | |
|             case FDMA_MST_CMD_WRITE:
 | |
|                 g_fm.cmd.buf[g_fm.cmd.buf_idx] = get_char;
 | |
|                 g_fm.cmd.buf_idx++;
 | |
|                 cmd_write = (fdma_mst_cmd_write_t *)g_fm.cmd.buf;
 | |
|                 if (g_fm.cmd.buf_idx >= sizeof(fdma_mst_cmd_write_t) +
 | |
|                     NTOHL(cmd_write->len) * 4) {
 | |
|                     g_fm.cmd.fsm = FDMA_MST_UART_FSM_WAITING_TAIL;
 | |
|                 }
 | |
|                 break;
 | |
|             }
 | |
|             break;
 | |
|         case FDMA_MST_UART_FSM_WAITING_TAIL:
 | |
|             if (get_char == FDMA_MST_CMD_TAIL) {
 | |
|                 g_fm.cmd.fsm = FDMA_MST_UART_FSM_COMPLETE;
 | |
|                 return ERR_OK;
 | |
|             } else {
 | |
|                 iot_printf("get error tail byte:0x%x\n", get_char);
 | |
|                 g_fm.cmd.fsm = FDMA_MST_UART_FSM_IDLE;
 | |
|                 g_fm.cmd.cmd_type = FDMA_MST_CMD_MAX;
 | |
|                 g_fm.cmd.buf_idx = 0;
 | |
|             }
 | |
|             break;
 | |
|         }
 | |
|     }
 | |
| }
 | |
| 
 | |
| static void dtest_fdma_mst_main()
 | |
| {
 | |
|     fdma_mst_cmd_read_t *cmd_read;
 | |
|     fdma_mst_cmd_write_t *cmd_write;
 | |
|     uint32_t i, addr, len;
 | |
| 
 | |
|     iot_printf("fdma master test\n");
 | |
|     dtest_fdma_mst_print_usage();
 | |
| 
 | |
|     gp_timer_init();
 | |
|     gp_timer_set(0, 0xffffffff, 0);
 | |
|     gp_timer_start(0);
 | |
| 
 | |
|     g_fm.cmd.cmd_type = FDMA_MST_CMD_MAX;
 | |
| 
 | |
|     while(1) {
 | |
|         if (dtest_fdma_mst_get_cmd() != ERR_OK) {
 | |
|             iot_printf("entry ? get usage\n");
 | |
|             continue;
 | |
|         }
 | |
| 
 | |
|         switch (g_fm.cmd.cmd_type) {
 | |
|         case FDMA_MST_CMD_READ:
 | |
|             cmd_read = (fdma_mst_cmd_read_t *)g_fm.cmd.buf;
 | |
|             addr = NTOHL(cmd_read->addr);
 | |
|             len = NTOHL(cmd_read->len);
 | |
|             iot_printf("get read cmd, addr:0x%08x, len:0x%08x\n", addr, len);
 | |
|             //call read api
 | |
|             iot_spi_fdma_master_read(addr, len, g_fm.swap_buf);
 | |
|             iot_printf("read data:");
 | |
|             for (i = 0; i < len; i++) {
 | |
|                 iot_printf("0x%08x ", g_fm.swap_buf[i]);
 | |
|             }
 | |
|             iot_printf("\n");
 | |
|             break;
 | |
|         case FDMA_MST_CMD_WRITE:
 | |
|             cmd_write = (fdma_mst_cmd_write_t *)g_fm.cmd.buf;
 | |
|             addr = NTOHL(cmd_write->addr);
 | |
|             len = NTOHL(cmd_write->len);
 | |
|             iot_printf("get write cmd, addr:0x%08x, len:0x%08x, data:", addr, len);
 | |
|             for (i = 0; i < len; i++) {
 | |
|                 iot_printf("0x%08x ", cmd_write->data[i]);
 | |
|             }
 | |
|             iot_printf("\n");
 | |
|             iot_spi_fdma_master_write(addr, len, cmd_write->data);
 | |
|             break;
 | |
|         }
 | |
|         g_fm.cmd.fsm = FDMA_MST_UART_FSM_IDLE;
 | |
|         g_fm.cmd.cmd_type = FDMA_MST_CMD_MAX;
 | |
|         g_fm.cmd.buf_idx = 0;
 | |
|     }
 | |
| 
 | |
|     return;
 | |
| }
 | |
| 
 | |
| void dtest_fdma_exception_handler(uintptr_t mcause)
 | |
| {
 | |
|     uint32_t mbadaddr = 0;
 | |
| 
 | |
|     //disble global interrupt;
 | |
|     __asm volatile  ( "csrc mstatus,8" );
 | |
|     __asm volatile  ( "csrr %0, mbadaddr" : "=r"(mbadaddr));
 | |
| 
 | |
|     switch(mcause) {
 | |
|         case 0x0:
 | |
|             iot_printf("mcause: 0x%02x[Instruction address misaligned]\n",
 | |
|                 mcause);
 | |
|             break;
 | |
|         case 0x1:
 | |
|             iot_printf("mcause: 0x%02x[Instruction access fault]\n",
 | |
|                 mcause);
 | |
|             break;
 | |
|         case 0x2:
 | |
|             iot_printf("mcause: 0x%02x[Illegal instruction]\n", mcause);
 | |
|             break;
 | |
|         case 0x3:
 | |
|             iot_printf("mcause: 0x%02x[Breakpoint]\n", mcause);
 | |
|             break;
 | |
|         case 0x4:
 | |
|             iot_printf("mcause: 0x%02x[Load address misaligned]\n",
 | |
|                 mcause);
 | |
|             break;
 | |
|         case 0x5:
 | |
|             iot_printf("mcause: 0x%02x[Load access fault]\n", mcause);
 | |
|             break;
 | |
|         case 0x6:
 | |
|             iot_printf("mcause: 0x%02x[Store address misaligned]\n",
 | |
|                 mcause);
 | |
|             break;
 | |
|         case 0x7:
 | |
|             iot_printf("mcase: 0x%02x[Store access fault]\n", mcause);
 | |
|             break;
 | |
|         default:
 | |
|             iot_printf("mcause: 0x%02x\n", mcause);
 | |
|             break;
 | |
|     }
 | |
| }
 | |
| 
 | |
| uintptr_t dtest_fdma_handle_trap(uintptr_t mcause,
 | |
|         uintptr_t epc, saved_registers *reg)
 | |
| {
 | |
|     if ((mcause & MCAUSE_CAUSE) == IRQ_M_EXT) {
 | |
| //        intc_handler(cpu_get_mhartid());
 | |
|     } else {
 | |
|         dtest_fdma_exception_handler(mcause);
 | |
| //        void dtest_fdma_mst_main(void);
 | |
| //        void (*pgm_start)(void) = (void*)dtest_fdma_mst_main;
 | |
| //        pgm_start();
 | |
|         dtest_fdma_mst_main();
 | |
|     }
 | |
|     return epc;
 | |
| }
 | |
| 
 | |
| extern unsigned int _heap_end, _heap_start;
 | |
| extern void dtest_fdma_trap_entry();
 | |
| int main(void)
 | |
| {
 | |
|     write_csr(mtvec, &dtest_fdma_trap_entry);
 | |
| 
 | |
|     clk_core_freq_set(CPU_FREQ_150M);
 | |
| 
 | |
|     dbg_uart_init();
 | |
| 
 | |
|     os_mem_init(&_heap_start,
 | |
|         (unsigned char *)&_heap_end - (unsigned char*)&_heap_start);
 | |
| 
 | |
|     apb_enable(APB_GPIO);
 | |
|     apb_enable(APB_PIN);
 | |
| 
 | |
|     gpio_pin_select(GPIO_S_CLK, 0);
 | |
|     gpio_pin_select(GPIO_S_CS, 0);
 | |
|     gpio_pin_select(GPIO_S_MS, 0);
 | |
| 
 | |
|     iot_gpio_open_as_output(GPIO_S_CLK);
 | |
|     iot_gpio_open_as_output(GPIO_S_CS);
 | |
|     iot_gpio_open_as_output(GPIO_S_MS);
 | |
| 
 | |
|     gpio_pin_wpd(GPIO_S_MS, 1);
 | |
|     gpio_pin_wpu(GPIO_S_MS, 0);
 | |
|     iot_gpio_set_opendrain_mode(GPIO_S_MS, GPIO_DRAIN_ONLY_0);
 | |
| 
 | |
|     dtest_fdma_mst_main();
 | |
|     return 0;
 | |
| }
 |