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; | ||
|  | } |