賈工 先楫資深 FAE
12年產品研發(fā)經驗,具有變頻器、伺服等工業(yè)產品開發(fā)經驗,也負責過激光投影顯示系統(tǒng)開發(fā)、AI應用開發(fā)、PYQT、Linux驅動開發(fā)等工作。
1、SEI簡介
SEI(Serial Encoder Interface)串行編碼器接口,是先楫半導體創(chuàng)新性設計的一個針對串行絕對值編碼器通信的外設。SEI支持同步通信模式與異步通信模式,既能做主機——從編碼器獲取數據,又能做從機——將位置信息以主機需要的串行協議發(fā)出。在電機類應用中極大的降低了編碼器相關開發(fā)任務的難度,同時以硬件編解碼的方式降低了CPU負載率,讓CPU有更多算力處理其他任務。
先楫半導體SDK 1.5.0提供了諸多SEI應用的實例,包括BISS-C、Endat、Hiperface、Nikon、SSI、Tamagawa等串行協議的主站、從站配置源碼,開發(fā)者在sample實例的基礎上,簡單的進行修改即可應用到項目中。
本文以Tamagawa協議為例,對SEI在異步通信中用法進行講解,同時對slave例程進行修改,增加對Tamagawa協議中EEPROM指令的支持,使讀者對SEI的用法有進一步的認識與了解。
本文中,命令指協議中主站向從站發(fā)送的命令,從站需要根據命令內容進行回復或執(zhí)行某些操作;指令指SEI引擎執(zhí)行的動作。
1.1SEI關鍵概念
1.1.1數據寄存器
數據寄存器是SEI收發(fā)數據的數據存放單元。在通信的接收過程中,接收到的數據會被存放于數據寄存器中;在通信的發(fā)送過程中,需要向外發(fā)送的數據同樣存放在數據寄存器中。
SEI共有9組數據寄存器,每個寄存器寬度為32bit。當以字節(jié)(8bit)為單位進行收發(fā)時,可以只使用數據寄存器的bit0~bit7,也可以使用bit0~bit32(或bit0~bit23),此時SEI引擎會自動將數據每8bit為一個單位,增加起始位、奇偶校驗位、結束位等進行收發(fā)。例如有一個24bit的編碼器單圈位置數據,接收時雖然每8bit接收1包,但連續(xù)收到的3包數據會放到同一個數據寄存器內;發(fā)送時,用戶在數據寄存器的bit0~bit23填入數據,SEI引擎會自動拆包,將bit0~bit7、bit8~bit15、bit16~bit23分別增加起始位、奇偶校驗位、結束位對外發(fā)出。
數據寄存器0用于忽略接收到的數據——某些開發(fā)者不關心的數據可以使用數據數據寄存器0進行接收;其概念與linux系統(tǒng)下黑洞文件類似。
數據寄存器2~數據寄存器9為通用數據寄存器??梢怨ぷ髟?種模式下:
1)數據模式:僅用于存儲數據;
2)檢查模式:可設定期待值,例如用戶期待接收到0x17,當接收到的寫入該數據寄存器的值不為0x17時,可產生傳輸錯誤提示;
3)CRC模式:用于收發(fā)數據過程中實時計算CRC值,可通過設置CRC多項式與CRC初始值來設計CRC算法,當接收數據的CRC計算結果與實時計算結果不符時,可產生錯誤傳輸提示。
1.1.2命令寄存器
用于接收串行編碼器協議中的命令數據。例如Tamagawa協議中CF(Control Field)字段為命令,其含義如下圖:
可以看到,CF字段內的cc0~cc3決定了通信的內容,根據該字段的不同,主機可以從編碼器中讀取單圈位置數據、多圈位置數據、報警信息、操作EEPROM等。
1.1.3命令匹配表
命令寄存器接收到命令后,SEI引擎接收JUMP跳轉指令,會根據命令內容在命令匹配表內進行檢索。找到符合命令的表項后,則跳轉至該命令匹配表指向的指令開始執(zhí)行。SEI共支持8張命令匹配表,SEI引擎會以順序方式對每張命令匹配表的命令進行對比,如果命令匹配表0~命令匹配表6都匹配失敗,則無條件執(zhí)行命令匹配表7的預設指令(回復/不回復)。
1.1.4指令
SEI引擎共支持8種指令,分為停止、等待、接收、發(fā)送、跳轉5大類指令,根據是否有超時保護拓展為8種指令。例如接收指令可分為時限內接收與無限時接收,時限內接收在規(guī)定的時間內未收到數據會進行報錯處理,無限時接收則會永遠等待下去。其它時限內發(fā)送與無限時發(fā)送等概念,請讀者自行理解。SEI共支持預設64條指令。
1.1.5狀態(tài)機
SEI狀態(tài)機包括4個狀態(tài),狀態(tài)的切換只能以0-->1-->2-->3-->0的順序進行,每種狀態(tài)的切換條件可由開發(fā)者自行定義,例如設置執(zhí)行完第10條指令后狀態(tài)機從狀態(tài)0切換到狀態(tài)1。狀態(tài)切換可向外發(fā)送事件信號,開發(fā)者可將該信號拉到其它外設進行觸發(fā),實現硬件同步;或簡單的產生一次中斷或DMA事件,使用中斷或DMA進行一定的數據處理工作。
理解SEI工作的關鍵就在于以上5個概念的掌握。其它更多的技術細節(jié)需要讀者自行查閱UM手冊進行理解。下面就以這5個概念對SEI工作的流程進行直觀的舉例描述:
1)從機開始以指令0“接收”狀態(tài)等待主機發(fā)送CF字段,若接收到數據,將接收到的指令保存到指令寄存器;
2)例如收到了DATA ID3指令,接收到指令后檢查指令匹配表;
3)順序檢查8張指令匹配表進行指令匹配,例如匹配到了指令表1,該指令表內描述“收到DATA ID3后執(zhí)行預設的64條指令中的指令10”;
4)SEI引擎執(zhí)行指令10,指令10內容為“時限內發(fā)送,CF,CF存放于指令寄存器”;
5)SEI引擎執(zhí)行指令11,指令11內容為“時限內發(fā)送,SF,SF存放于數據寄存器2”;
6)SEI引擎執(zhí)行指令12,指令12內容為“時限內發(fā)送,ABS0~ABS2,ABS存放于數據寄存器3”;
7)SEI引擎執(zhí)行指令13,指令13內容為“時限內發(fā)送,ENID,ENID存放于數據寄存器4”;
8)SEI引擎執(zhí)行指令14,指令14內容為“時限內發(fā)送,ABM,ABM存放于數據寄存器5”;
9)SEI引擎執(zhí)行指令15,指令15內容為“時限內發(fā)送,ALC,ALC存放于數據寄存器6”;
10)SEI引擎執(zhí)行指令16,指令16內容為“時限內發(fā)送,CRC,CRC存放于數據寄存器9”;
11)SEI引擎執(zhí)行指令17,指令17內容為“結束,跳轉回指令0”;
12)SEI引擎執(zhí)行指令0,指令0內容為“接收,等待主機發(fā)送CF字段,若接收到數據,將接收到的指令保存到指令寄存器”。
可以看到,通過以上工作流程的描述,SEI就依靠硬件自動完成了數據的發(fā)送,響應了主機讀數據的需求。CPU只要在合適的時間點將數據更新到數據寄存器即可。
2 多摩川協議簡介
多摩川編碼器在工業(yè)控制領域廣泛應用,本節(jié)簡單介紹Tamagawa編碼器協議。
注意,協議整體架構是固定的,但具體到每款編碼器,根據編碼器精度不同、多圈數據位數不同,協議的數據內容需要進行微調。
多摩川編碼器支持向主站提供單圈位置信息、多圈位置信息、報警信息、復位操作、EEPROM讀寫操作等,不同操作指令的下發(fā)位于CF字段內。下面分別介紹協議內不同指令的具體格式。
具體的,多摩川協議以2.5M固定波特率進行數通信,數據格式8、N、1。
2.1數據讀取指令格式
數據讀取過程:
1)主機下發(fā)CF,CF內的cc0~cc3為ID0~ID3時,代表讀取編碼器信息;
2)從機回復CF,響應主機;
3)從機回復SF,發(fā)送編碼器狀態(tài)信息(具體有什么狀態(tài)Flag請讀者自行學習多摩川編碼器Datasheet);
4)從機回復DF0~DF7,即數據字段。根據不同的指令ID,數據字段長度不同,數據字段內可包含ABS(單圈信息),ENID(固定0x17),ABM(多圈信息),ALMC(報警信息),不同ID回復內容見下表。
5)從機回復CRC,供主機進行數據完整性校驗。
時序要求如下,在收到CF后的0.5us時刻鎖存當前位置信息:
2.2EEPROM讀指令格式
多摩川編碼器為客戶提供了762字節(jié)的EEPROM空間,分為6頁,每頁包含127個(0~126)字節(jié)。對地址127進行寫操作可改變操作頁數。
1)主機發(fā)送CF,CF內cc0~cc3字段解析為ID D;
2)主機發(fā)送ADF,代表要讀取當前頁的第ADF個(0~126)字節(jié)的數據;
3)主機發(fā)送CRC,供從機進行數據完整性校驗;
4)從機回復CF、ADF;
5)從機回復EDF,即主機需要的數據;
6)從機回復CRC,供主機進行數據完整性校驗。
2.3EEPROM寫指令格式
1)主機發(fā)送CF,CF內cc0~cc3字段解析為ID 6;
2)主機發(fā)送ADF,代表要寫入當前頁的第ADF個(0~126)字節(jié);
3)主機發(fā)送EDF,代表要寫入的數據;
4)主機發(fā)送CRC,供從機進行數據完整性校驗;
5)從機回復CF、ADF、EDF、CRC,與主機下發(fā)內容相同,代表寫入成功。
讀寫時序要求如下:
3多摩川從站例程介紹
打開
sdk_env_v1.5.0\hpm_sdk\samples\drivers\sei\slave\tamagawa\src文件,獲取Tamagawa從站源碼。
/* [1] tranceiver config */
tranceiver_config.mode=sei_asynchronous_mode;
tranceiver_config.tri_sample= false;
tranceiver_config.src_clk_freq=clock_get_frequency(BOARD_MOTOR_CLK_NAME);
tranceiver_config.asynchronous_config.wait_len =0;
tranceiver_config.asynchronous_config.data_len =8;
tranceiver_config.asynchronous_config.parity_enable=false;
tranceiver_config.asynchronous_config.data_idle_high_z =false;
tranceiver_config.asynchronous_config.data_idle_state= sei_idle_high_state;
tranceiver_config.asynchronous_config.baudrate= 2500000;
sei_tranceiver_config_init(BOARD_SEI,BOARD_SEI_CTRL,&tranceiver_config);
設置SEI工作在異步模式,波特率為2.5M,數據格式為8、N、1。以及數據線的默認狀態(tài)等,這一部分請讀者自行對照UM手冊SEI寄存器進行解析。
/* [2] data register config */
/* cmd register : recv CF */
data_format_config.mode= sei_data_mode;
data_format_config.signed_flag= false;
data_format_config.bit_order= sei_bit_lsb_first;
data_format_config.word_order= sei_word_nonreverse;
data_format_config.word_len= 8;
data_format_config.last_bit= 7;
data_format_config.first_bit= 0;
data_format_config.max_bit= 7;
data_format_config.min_bit= 0;
sei_cmd_data_format_config_init
(BOARD_SEI,SEI_SELECT_CMD,BOARD_SEI_CTRL,&data_format_config);
/* data register 4: send SF */
data_format_config.mode= sei_data_mode;
data_format_config.signed_flag= false;
data_format_config.bit_order= sei_bit_lsb_first;
data_format_config.word_order= sei_word_nonreverse;
data_format_config.word_len= 8;
data_format_config.last_bit= 7;
data_format_config.first_bit= 0;
data_format_config.max_bit= 7;
data_format_config.min_bit= 0;
sei_cmd_data_format_config_init
(BOARD_SEI, SEI_SELECT_DATA, SEI_DAT_4, &data_format_config);
/* data register 5: send ABS0 ABS1 ABS2 */
data_format_config.mode=sei_data_mode;
data_format_config.signed_flag= false;
data_format_config.bit_order=sei_bit_lsb_first;
data_format_config.word_order=sei_word_nonreverse;
data_format_config.word_len= 24;
data_format_config.last_bit= 23;
data_format_config.first_bit= 0;
data_format_config.max_bit= 23;
data_format_config.min_bit= 0;
sei_cmd_data_format_config_init
(BOARD_SEI, SEI_SELECT_DATA, SEI_DAT_5, &data_format_config);
/* data register 6: send ENID */
data_format_config.mode= sei_data_mode;
data_format_config.signed_flag= false;
data_format_config.bit_order=sei_bit_lsb_first;
data_format_config.word_order=sei_word_nonreverse;
data_format_config.word_len= 8;
data_format_config.last_bit= 7;
data_format_config.first_bit= 0;
data_format_config.max_bit= 7;
data_format_config.min_bit= 0;
sei_cmd_data_format_config_init
(BOARD_SEI, SEI_SELECT_DATA, SEI_DAT_6, &data_format_config);
/* data register 7: send ABM0 ABM1 ABM2 */
data_format_config.mode= sei_data_mode;
data_format_config.signed_flag= false;
data_format_config.bit_order=sei_bit_lsb_first;
data_format_config.word_order=sei_word_nonreverse;
data_format_config.word_len= 24;
data_format_config.last_bit= 23;
data_format_config.first_bit= 0;
data_format_config.max_bit= 23;
data_format_config.min_bit= 0;
sei_cmd_data_format_config_init
(BOARD_SEI, SEI_SELECT_DATA, SEI_DAT_7, &data_format_config);
/* data register 8: send ALMC */
data_format_config.mode= sei_data_mode;
data_format_config.signed_flag= false;
data_format_config.bit_order=sei_bit_lsb_first;
data_format_config.word_order=sei_word_nonreverse;
data_format_config.word_len= 8;
data_format_config.last_bit= 7;
data_format_config.first_bit= 0;
data_format_config.max_bit= 7;
data_format_config.min_bit= 0;
sei_cmd_data_format_config_init
(BOARD_SEI, SEI_SELECT_DATA, SEI_DAT_8, &data_format_config);
/* data register 9: send crc */
data_format_config.mode= sei_crc_mode;
data_format_config.signed_flag= false;
data_format_config.bit_order=sei_bit_lsb_first;
data_format_config.word_order=sei_word_nonreverse;
data_format_config.word_len= 8;
data_format_config.crc_invert= false;
data_format_config.crc_shift_mode= false;
data_format_config.crc_len= 8;
data_format_config.last_bit= 7;
data_format_config.first_bit= 0;
data_format_config.max_bit= 7;
data_format_config.min_bit= 0;
data_format_config.crc_init_value= 0;
data_format_config.crc_poly= 1;
sei_cmd_data_format_config_init
(BOARD_SEI, SEI_SELECT_DATA, SEI_DAT_9, &data_format_config);
設置數據寄存器,其中:
1)指令寄存器用于收發(fā)CF;
2)DATA4(數據寄存器4)用于發(fā)送SF;
3)DATA5(數據寄存器5)用于發(fā)送ABS;
4)DATA6(數據寄存器6)用于發(fā)送ENID;
5)DATA7(數據寄存器7)用于發(fā)送ABM;
6)DATA8(數據寄存器8)用于發(fā)送ALM;
7)DATA9(數據寄存器9)用于發(fā)送CRC;
/* [3] instructions */
instr_idx= 0;
/* instr0 : Recv CF */
sei_set_instr(BOARD_SEI, instr_idx++, SEI_INSTR_OP_RECV_WDG, 0, SEI_DAT_0, SEI_DAT_1, 8);
/* instr1 : halt 1 bit for update */
sei_set_instr(BOARD_SEI, instr_idx++, SEI_INSTR_OP_HALT, 0, SEI_DAT_0, SEI_DAT_0, 1);
/* instr2 : halt some bits for waiting */
sei_set_instr(BOARD_SEI, instr_idx++, SEI_INSTR_OP_HALT, 0, SEI_DAT_0, SEI_DAT_0, 6);
/* instr3 : jump to cmd table instr_idx[0] */
sei_set_instr(BOARD_SEI, instr_idx++, SEI_INSTR_OP_JUMP, 0, SEI_DAT_0, SEI_DAT_0, SEI_JUMP_CMD_TABLE_INSTR_IDX0);
/* Data ID0 : 0x02 */
/*instr4 : sendCF */
sei_set_instr(BOARD_SEI, instr_idx++, SEI_INSTR_OP_SEND, 0, SEI_DAT_9, SEI_DAT_1, 8);
/* instr5 : send SF */
sei_set_instr(BOARD_SEI, instr_idx++, SEI_INSTR_OP_SEND, 0, SEI_DAT_9, SEI_DAT_4, 8);
/*instr6 :send ST(POS) */
sei_set_instr(BOARD_SEI, instr_idx++, SEI_INSTR_OP_SEND, 0, SEI_DAT_9, SEI_DAT_5, 24);
/*instr7 :CRC */
sei_set_instr(BOARD_SEI, instr_idx++, SEI_INSTR_OP_SEND, 0, SEI_DAT_0, SEI_DAT_9, 8);
/*instr8 :Jump back to initiate*/
sei_set_instr(BOARD_SEI, instr_idx++, SEI_INSTR_OP_JUMP, 0, SEI_DAT_0, SEI_DAT_0, SEI_JUMP_INIT_INSTR_IDX);
/* Data ID1 : 0x8A */
/* Reference to instr0 ~ instr8 */
sei_set_instr(BOARD_SEI, instr_idx++, SEI_INSTR_OP_SEND, 0, SEI_DAT_9, SEI_DAT_1, 8);/* CF */
sei_set_instr(BOARD_SEI, instr_idx++, SEI_INSTR_OP_SEND, 0, SEI_DAT_9, SEI_DAT_4, 8);/* SF */
sei_set_instr(BOARD_SEI, instr_idx++, SEI_INSTR_OP_SEND, 0, SEI_DAT_9, SEI_DAT_7, 24);/* MT */
sei_set_instr(BOARD_SEI, instr_idx++, SEI_INSTR_OP_SEND, 0, SEI_DAT_0, SEI_DAT_9, 8); /* CRC */
sei_set_instr(BOARD_SEI, instr_idx++, SEI_INSTR_OP_JUMP, 0, SEI_DAT_0, SEI_DAT_0, SEI_JUMP_INIT_INSTR_IDX);
/* Data ID2 : 0x92 */
sei_set_instr(BOARD_SEI, instr_idx++, SEI_INSTR_OP_SEND, 0, SEI_DAT_9, SEI_DAT_1, 8);/* CF */
sei_set_instr(BOARD_SEI, instr_idx++, SEI_INSTR_OP_SEND, 0, SEI_DAT_9, SEI_DAT_4, 8); /* SF */
sei_set_instr(BOARD_SEI, instr_idx++, SEI_INSTR_OP_SEND, 0, SEI_DAT_9, SEI_DAT_6, 8);/* ENID:0x17 */
sei_set_instr(BOARD_SEI, instr_idx++, SEI_INSTR_OP_SEND, 0, SEI_DAT_0, SEI_DAT_9, 8);/* CRC */
sei_set_instr(BOARD_SEI, instr_idx++, SEI_INSTR_OP_JUMP, 0, SEI_DAT_0, SEI_DAT_0, SEI_JUMP_INIT_INSTR_IDX);
/* Data ID3 : 0x1A */
sei_set_instr(BOARD_SEI, instr_idx++, SEI_INSTR_OP_SEND, 0, SEI_DAT_9, SEI_DAT_1, 8);/* CF */
sei_set_instr(BOARD_SEI, instr_idx++, SEI_INSTR_OP_SEND, 0, SEI_DAT_9, SEI_DAT_4, 8); /* SF */
sei_set_instr(BOARD_SEI, instr_idx++, SEI_INSTR_OP_SEND, 0, SEI_DAT_9, SEI_DAT_5, 24);/* ST(POS) */
sei_set_instr(BOARD_SEI, instr_idx++, SEI_INSTR_OP_SEND, 0, SEI_DAT_9, SEI_DAT_6, 8);/* ENID:0x17 */
sei_set_instr(BOARD_SEI, instr_idx++, SEI_INSTR_OP_SEND, 0, SEI_DAT_9, SEI_DAT_7, 24);/* MT */
sei_set_instr(BOARD_SEI, instr_idx++, SEI_INSTR_OP_SEND, 0, SEI_DAT_9, SEI_DAT_8, 8);/* ALMC */
sei_set_instr(BOARD_SEI, instr_idx++, SEI_INSTR_OP_SEND, 0, SEI_DAT_0, SEI_DAT_9, 8);/* CRC */
sei_set_instr(BOARD_SEI, instr_idx++, SEI_INSTR_OP_JUMP, 0, SEI_DAT_0, SEI_DAT_0, SEI_JUMP_INIT_INSTR_IDX);
設置預設指令,其中:
1)指令0用于接收CF;
2)指令1用于延遲0.5us后鎖存位置信息;
3)指令2用于延遲3us滿足時序要求;
4)指令3用于跳轉,查找指令匹配表進行匹配;
5)指令4~指令表結束,根據不同的指令向主機發(fā)送主機查詢的信息。
/* [4] command table */
command_table_config.cmd_min_value= 0x02u;
command_table_config.cmd_max_value= 0x02u;
command_table_config.cmd_mask_value= 0xFFu;
command_table_config.instr_idx[0] = 4;
sei_cmd_table_config_init(BOARD_SEI, BOARD_SEI_CTRL, SEI_CMD_TABLE_0, &command_table_config);
command_table_config.cmd_min_value= 0x8Au;
command_table_config.cmd_max_value= 0x8Au;
command_table_config.cmd_mask_value= 0xFFu;
command_table_config.instr_idx[0] = 9;
sei_cmd_table_config_init(BOARD_SEI, BOARD_SEI_CTRL, SEI_CMD_TABLE_1, &command_table_config);
command_table_config.cmd_min_value= 0x92u;
command_table_config.cmd_max_value= 0x92u;
command_table_config.cmd_mask_value= 0xFFu;
command_table_config.instr_idx[0] = 14;
sei_cmd_table_config_init(BOARD_SEI, BOARD_SEI_CTRL, SEI_CMD_TABLE_2,&command_table_config);
command_table_config.cmd_min_value= 0x1Au;
command_table_config.cmd_max_value= 0x1Au;
command_table_config.cmd_mask_value= 0xFFu;
command_table_config.instr_idx[0] = 19;
sei_cmd_table_config_init(BOARD_SEI, BOARD_SEI_CTRL, SEI_CMD_TABLE_3,&command_table_config);
設置指令匹配表,
cmd_min_value、cmd_max_value、cmd_mask_value設置了指令匹配的模式,請參考UM手冊查詢具體的含義;instr_idx[0]設置了如果匹配成功,跳轉的目標指令。
/* [5] state transition config */
/* latch0 */
state_transition_config.disable_clk_check= true;
state_transition_config.disable_txd_check= true;
state_transition_config.disable_rxd_check= true;
state_transition_config.disable_timeout_check= true;
state_transition_config.disable_instr_ptr_check= false;
state_transition_config.instr_ptr_cfg= sei_state_tran_condition_fall_leave;
state_transition_config.instr_ptr_value= 1;
sei_state_transition_config_init(BOARD_SEI, BOARD_SEI_CTRL, SEI_LATCH_0, SEI_CTRL_LATCH_TRAN_0_1, &state_transition_config);
state_transition_config.disable_clk_check= true;
state_transition_config.disable_txd_check= true;
state_transition_config.disable_rxd_check= true;
state_transition_config.disable_timeout_check= true;
state_transition_config.disable_instr_ptr_check= true;
sei_state_transition_config_init(BOARD_SEI, BOARD_SEI_CTRL, SEI_LATCH_0, SEI_CTRL_LATCH_TRAN_1_2,&state_transition_config);
state_transition_config.disable_clk_check= true;
state_transition_config.disable_txd_check= true;
state_transition_config.disable_rxd_check= true;
state_transition_config.disable_timeout_check= true;
state_transition_config.disable_instr_ptr_check= true;
sei_state_transition_config_init(BOARD_SEI, BOARD_SEI_CTRL, SEI_LATCH_0, SEI_CTRL_LATCH_TRAN_2_3, &state_transition_config);
state_transition_config.disable_clk_check= true;
state_transition_config.disable_txd_check= true;
state_transition_config.disable_rxd_check= true;
state_transition_config.disable_timeout_check= true;
state_transition_config.disable_instr_ptr_check= true;
sei_state_transition_config_init(BOARD_SEI, BOARD_SEI_CTRL, SEI_LATCH_0, SEI_CTRL_LATCH_TRAN_3_0, &state_transition_config);
state_transition_latch_config.enable= true;
state_transition_latch_config.output_select= SEI_CTRL_LATCH_TRAN_0_1;
state_transition_latch_config.delay= 0;
sei_state_transition_latch_config_init(BOARD_SEI, BOARD_SEI_CTRL, SEI_LATCH_0,&state_transition_latch_config);
狀態(tài)機跳轉的配置代碼,此處只配置了狀態(tài)0到狀態(tài)1轉換的條件為“指令1執(zhí)行完成”,即接收到CF后0.5us的時間點,進行狀態(tài)轉換,同時向外生成事件(本例程內產生了中斷,中斷內對要發(fā)送的數據進行了設置)。
/* [6] sample config*/
sample_config.pos_data_idx= SEI_DAT_5;
sample_config.rev_data_idx= SEI_DAT_7;
sample_config.pos_data_use_rx= false;
sample_config.rev_data_use_rx= false;
sample_config.sample_window= 0x5;
sample_config.sample_once= true;
sample_config.latch_select= SEI_LATCH_0;
sample_config.data_register_select= BIT5_MASK| BIT7_MASK; /* SEI_DAT_5, SEI_DAT_7 */
sei_sample_config_init(BOARD_SEI, BOARD_SEI_CTRL,&sample_config);
sei_set_sample_pos_override_value(BOARD_SEI, BOARD_SEI_CTRL, mock_pos);
sei_set_sample_rev_override_value(BOARD_SEI, BOARD_SEI_CTRL,mock_rev);
/* [7] interrupt config */
intc_m_enable_irq_with_priority(BOARD_SEI_IRQn, 1);
sei_set_irq_enable(BOARD_SEI, BOARD_SEI_CTRL, sei_irq_latch0_event | sei_irq_wdog_event | sei_irq_trx_err_event,true);
采樣設置(讀取電機系統(tǒng)內的位置信息)與中斷開啟,狀態(tài)0到狀態(tài)1實現狀態(tài)轉換時,出發(fā)了sei_irq_latch0_event中斷。
/* [8] enbale sync timer timestamp */
synt_enable_timestamp(HPM_SYNT, true);
/* [9] engine config */
printf("Started sei engine!\n");
engine_config.arming_mode= sei_arming_direct_exec;
engine_config.data_cdm_idx= 0;
engine_config.data_base_idx= 0;
engine_config.init_instr_idx= 0;
engine_config.wdg_enable= true;
engine_config.wdg_action= sei_wdg_exec_exception_instr;
engine_config.wdg_instr_idx= 0;
engine_config.wdg_time= 1000; /* 1000 bits time */
sei_engine_config_init(BOARD_SEI, BOARD_SEI_CTRL,&engine_config);
sei_set_engine_enable(BOARD_SEI, BOARD_SEI_CTRL, true);
看門狗的設置及使能SEI引擎,看門狗的配置含義請參考UM手冊。
voidisr_sei(void)
{
uint32_tdelta;
if(sei_get_irq_status(BOARD_SEI, BOARD_SEI_CTRL, sei_irq_latch0_event)) {
sei_clear_irq_flag(BOARD_SEI, BOARD_SEI_CTRL, sei_irq_latch0_event);
sample_latch_tm1= sei_get_latch_time(BOARD_SEI, BOARD_SEI_CTRL, SEI_LATCH_0);
mock_pos++;
if(mock_pos> 0x00FFFFFF) {
mock_pos= 0;
mock_rev++;
if(mock_rev> 0x00FFFFFF) {
mock_rev= 0;
}
}
sei_set_sample_pos_override_value(BOARD_SEI, BOARD_SEI_CTRL, mock_pos);
sei_set_sample_rev_override_value(BOARD_SEI, BOARD_SEI_CTRL, mock_rev);
sei_set_data_value(BOARD_SEI, SEI_DAT_4, 0x00);
sei_set_data_value(BOARD_SEI, SEI_DAT_6, 0x17);
sei_set_data_value(BOARD_SEI, SEI_DAT_8, 0x00);
delta= (sample_latch_tm1> sample_latch_tm2) ? (sample_latch_tm1- sample_latch_tm2) : (sample_latch_tm1- sample_latch_tm2+ 0xFFFFFFFFu);
printf("CMD:%#x, SF:%#x, ST:%#x, ENID:%#x, MT:%#x, ALMC:%#x, CRC:%#x, sample_tm1:%u, sample_tm2:%u, sample_interval:%dus\n",
sei_get_command_value(BOARD_SEI, BOARD_SEI_CTRL),
sei_get_data_value(BOARD_SEI, SEI_DAT_4),
sei_get_data_value(BOARD_SEI, SEI_DAT_5),
sei_get_data_value(BOARD_SEI, SEI_DAT_6),
sei_get_data_value(BOARD_SEI, SEI_DAT_7),
sei_get_data_value(BOARD_SEI, SEI_DAT_8),
sei_get_data_value(BOARD_SEI, SEI_DAT_9),
sample_latch_tm1, sample_latch_tm2, delta/ (clock_get_frequency(BOARD_MOTOR_CLK_NAME) / 1000000));
sample_latch_tm2= sample_latch_tm1;
}
if(sei_get_irq_status(BOARD_SEI, BOARD_SEI_CTRL, sei_irq_wdog_event)) {
sei_clear_irq_flag(BOARD_SEI, BOARD_SEI_CTRL, sei_irq_wdog_event);
sei_set_command_rewind(BOARD_SEI, BOARD_SEI_CTRL);
}
if(sei_get_irq_status(BOARD_SEI, BOARD_SEI_CTRL, sei_irq_trx_err_event)) {
sei_clear_irq_flag(BOARD_SEI, BOARD_SEI_CTRL, sei_irq_trx_err_event);
printf("TRX Error!\n");
}
}
SEI中斷設置,當sei_irq_latch0_event中斷發(fā)生時,設置了向主機回復的數據,滿足多摩川時序要求,即接收到CF后0.5us時間點進行數據設置。
4 EEPROM指令支持
由于讀寫EEPROM的指令格式與讀取位置數據指令格式有區(qū)別,即接收CF后不進行鎖存,需要繼續(xù)接收ADF、EDF等數據,因此整個SEI指令處理流程上,指令的跳轉邏輯變得更復雜。下圖是在做EEPROM指令支持開發(fā)過程中,繪制的流程圖。
支持EEPROM指令的關鍵源碼如下:
uint32_teeprom_page= 0;
uint32_teeprom[6][127] = {0};
聲明eeprom地址頁信息變量與6頁共762字節(jié)的eeprom數據數組。
/* [2] data register config */
/* cmd register : recv CF */
data_format_config.mode= sei_data_mode;
data_format_config.signed_flag= false;
data_format_config.bit_order= sei_bit_lsb_first;
data_format_config.word_order= sei_word_nonreverse;
data_format_config.word_len= 8;
data_format_config.last_bit= 7;
data_format_config.first_bit= 0;
data_format_config.max_bit= 7;
data_format_config.min_bit= 0;
sei_cmd_data_format_config_init
(BOARD_SEI,SEI_SELECT_CMD, BOARD_SEI_CTRL, &data_format_config);
/* cmd register : recv ADF */
data_format_config.mode= sei_data_mode;
data_format_config.signed_flag= false;
data_format_config.bit_order= sei_bit_lsb_first;
data_format_config.word_order= sei_word_nonreverse;
data_format_config.word_len= 8;
data_format_config.last_bit= 7;
data_format_config.first_bit= 0;
data_format_config.max_bit= 7;
data_format_config.min_bit= 0;
sei_cmd_data_format_config_init
(BOARD_SEI,SEI_SELECT_DATA, SEI_DAT_2,&data_format_config);
/* cmd register : recv EDF */
data_format_config.mode= sei_data_mode;
data_format_config.signed_flag= false;
data_format_config.bit_order= sei_bit_lsb_first;
data_format_config.word_order= sei_word_nonreverse;
data_format_config.word_len= 8;
data_format_config.last_bit= 7;
data_format_config.first_bit= 0;
data_format_config.max_bit= 7;
data_format_config.min_bit= 0;
sei_cmd_data_format_config_init
(BOARD_SEI,SEI_SELECT_DATA, SEI_DAT_3,&data_format_config);
/* data register 4: send SF */
data_format_config.mode= sei_data_mode;
data_format_config.signed_flag= false;
data_format_config.bit_order= sei_bit_lsb_first;
data_format_config.word_order= sei_word_nonreverse;
data_format_config.word_len= 8;
data_format_config.last_bit= 7;
data_format_config.first_bit= 0;
data_format_config.max_bit= 7;
data_format_config.min_bit= 0;
sei_cmd_data_format_config_init
(BOARD_SEI,SEI_SELECT_DATA, SEI_DAT_4, &data_format_config);
/* data register 5: send ABS0 ABS1 ABS2 */
data_format_config.mode= sei_data_mode;
data_format_config.signed_flag=false;
data_format_config.bit_order=sei_bit_lsb_first;
data_format_config.word_order= sei_word_nonreverse;
data_format_config.word_len= 24;
data_format_config.last_bit= 23;
data_format_config.first_bit= 0;
data_format_config.max_bit= 23;
data_format_config.min_bit= 0;
sei_cmd_data_format_config_init
(BOARD_SEI,SEI_SELECT_DATA, SEI_DAT_5, &data_format_config);
/* data register 6: send ENID */
data_format_config.mode= sei_data_mode;
data_format_config.signed_flag= false;
data_format_config.bit_order= sei_bit_lsb_first;
data_format_config.word_order= sei_word_nonreverse;
data_format_config.word_len= 8;
data_format_config.last_bit= 7;
data_format_config.first_bit= 0;
data_format_config.max_bit= 7;
data_format_config.min_bit= 0;
sei_cmd_data_format_config_init
(BOARD_SEI,SEI_SELECT_DATA, SEI_DAT_6, &data_format_config);
/* data register 7: send ABM0 ABM1 ABM2 */
data_format_config.mode= sei_data_mode;
data_format_config.signed_flag= false;
data_format_config.bit_order= sei_bit_lsb_first;
data_format_config.word_order= sei_word_nonreverse;
data_format_config.word_len= 24;
data_format_config.last_bit= 23;
data_format_config.first_bit= 0;
data_format_config.max_bit= 23;
data_format_config.min_bit= 0;
sei_cmd_data_format_config_init
(BOARD_SEI,SEI_SELECT_DATA, SEI_DAT_7,&data_format_config);
/* data register 8: send ALMC */
data_format_config.mode= sei_data_mode;
data_format_config.signed_flag= false;
data_format_config.bit_order= sei_bit_lsb_first;
data_format_config.word_order= sei_word_nonreverse;
data_format_config.word_len= 8;
data_format_config.last_bit= 7;
data_format_config.first_bit= 0;
data_format_config.max_bit= 7;
data_format_config.min_bit= 0;
sei_cmd_data_format_config_init
(BOARD_SEI,SEI_SELECT_DATA, SEI_DAT_8,&data_format_config);
/* data register 9: send crc */
data_format_config.mode= sei_crc_mode;
data_format_config.signed_flag= false;
data_format_config.bit_order= sei_bit_lsb_first;
data_format_config.word_order= sei_word_nonreverse;
data_format_config.word_len= 8;
data_format_config.crc_invert= false;
data_format_config.crc_shift_mode= false;
data_format_config.crc_len= 8;
data_format_config.last_bit= 7;
data_format_config.first_bit= 0;
data_format_config.max_bit= 7;
data_format_config.min_bit= 0;
data_format_config.crc_init_value= 0;
data_format_config.crc_poly= 1;
sei_cmd_data_format_config_init
(BOARD_SEI,SEI_SELECT_DATA, SEI_DAT_9, &data_format_config);
設置數據寄存器,其中:
1)指令寄存器用于收發(fā)CF
2)DATA2(數據寄存器2)用于收發(fā)ADF
3)DATA3(數據寄存器3)用于發(fā)送EDF
4)DATA4(數據寄存器4)用于發(fā)送SF
5)DATA5(數據寄存器5)用于發(fā)送ABS
6)DATA6(數據寄存器6)用于發(fā)送ENID
7)DATA7(數據寄存器7)用于發(fā)送ABM
8)DATA8(數據寄存器8)用于發(fā)送ALM
9)DATA9(數據寄存器9)用于發(fā)送CRC
/* [3] instructions */
instr_idx= 0;
/*00*/sei_set_instr(BOARD_SEI, instr_idx++, SEI_INSTR_OP_RECV_WDG, 0, SEI_DAT_9, SEI_DAT_1, 8);/* Recv CF */
/* jump to cmd */
/*01*/sei_set_instr(BOARD_SEI, instr_idx++, SEI_INSTR_OP_JUMP, 0, SEI_DAT_0, SEI_DAT_0, SEI_JUMP_CMD_TABLE_INSTR_IDX0);/* jump to cmd table instr_idx[0] */
/*02*/sei_set_instr(BOARD_SEI, instr_idx++, SEI_INSTR_OP_HALT, 0, SEI_DAT_0, SEI_DAT_0, 1); /* halt 1 bit for update */
/*03*/sei_set_instr(BOARD_SEI, instr_idx++, SEI_INSTR_OP_HALT, 0, SEI_DAT_0, SEI_DAT_0, 6); /* halt some bits for waiting */
/*04*/sei_set_instr(BOARD_SEI, instr_idx++, SEI_INSTR_OP_JUMP, 0, SEI_DAT_0, SEI_DAT_0, SEI_JUMP_CMD_TABLE_INSTR_IDX6);
/* Data ID0 : 0x02 */
/*05*/sei_set_instr(BOARD_SEI, instr_idx++, SEI_INSTR_OP_SEND, 0, SEI_DAT_9, SEI_DAT_1, 8); /* CF */
/*06*/sei_set_instr(BOARD_SEI, instr_idx++, SEI_INSTR_OP_SEND, 0, SEI_DAT_9, SEI_DAT_4, 8);/* SF */
/*07*/sei_set_instr(BOARD_SEI, instr_idx++, SEI_INSTR_OP_SEND, 0, SEI_DAT_9, SEI_DAT_5, 24);/* ST(POS) */
/*08*/sei_set_instr(BOARD_SEI, instr_idx++, SEI_INSTR_OP_SEND, 0, SEI_DAT_0, SEI_DAT_9, 8);/* CRC */
/*09*/sei_set_instr(BOARD_SEI, instr_idx++, SEI_INSTR_OP_JUMP, 0, SEI_DAT_0, SEI_DAT_0, SEI_JUMP_INIT_INSTR_IDX);
/* Data ID1 : 0x8A */
/*10*/sei_set_instr(BOARD_SEI, instr_idx++, SEI_INSTR_OP_SEND, 0, SEI_DAT_9, SEI_DAT_1, 8); /* CF */
/*11*/sei_set_instr(BOARD_SEI, instr_idx++, SEI_INSTR_OP_SEND, 0, SEI_DAT_9, SEI_DAT_4, 8);/* SF */
/*12*/sei_set_instr(BOARD_SEI, instr_idx++, SEI_INSTR_OP_SEND, 0, SEI_DAT_9, SEI_DAT_7, 24);/* MT */
/*13*/sei_set_instr(BOARD_SEI, instr_idx++, SEI_INSTR_OP_SEND, 0, SEI_DAT_0, SEI_DAT_9, 8);/* CRC */
/*14*/sei_set_instr(BOARD_SEI, instr_idx++, SEI_INSTR_OP_JUMP, 0, SEI_DAT_0, SEI_DAT_0, SEI_JUMP_INIT_INSTR_IDX);
/* Data ID2 : 0x92 */
/*15*/sei_set_instr(BOARD_SEI, instr_idx++, SEI_INSTR_OP_SEND, 0, SEI_DAT_9, SEI_DAT_1, 8);/* CF */
/*16*/sei_set_instr(BOARD_SEI, instr_idx++, SEI_INSTR_OP_SEND, 0, SEI_DAT_9, SEI_DAT_4, 8);/* SF */
/*17*/sei_set_instr(BOARD_SEI, instr_idx++, SEI_INSTR_OP_SEND, 0, SEI_DAT_9, SEI_DAT_6, 8);/* ENID:0x17 */
/*18*/sei_set_instr(BOARD_SEI, instr_idx++, SEI_INSTR_OP_SEND, 0, SEI_DAT_0, SEI_DAT_9, 8);/* CRC */
/*19*/sei_set_instr(BOARD_SEI, instr_idx++, SEI_INSTR_OP_JUMP, 0, SEI_DAT_0, SEI_DAT_0, SEI_JUMP_INIT_INSTR_IDX);
/* Data ID3 : 0x1A */
/*20*/sei_set_instr(BOARD_SEI, instr_idx++, SEI_INSTR_OP_SEND, 0, SEI_DAT_9, SEI_DAT_1, 8); /* CF */
/*21*/sei_set_instr(BOARD_SEI, instr_idx++, SEI_INSTR_OP_SEND, 0, SEI_DAT_9, SEI_DAT_4, 8);/* SF */
/*22*/sei_set_instr(BOARD_SEI, instr_idx++, SEI_INSTR_OP_SEND, 0, SEI_DAT_9, SEI_DAT_5, 24);/* ST(POS) */
/*23*/sei_set_instr(BOARD_SEI, instr_idx++, SEI_INSTR_OP_SEND, 0, SEI_DAT_9, SEI_DAT_6, 8);/* ENID:0x17 */
/*24*/sei_set_instr(BOARD_SEI, instr_idx++, SEI_INSTR_OP_SEND, 0, SEI_DAT_9, SEI_DAT_7, 24);/* MT */
/*25*/sei_set_instr(BOARD_SEI, instr_idx++, SEI_INSTR_OP_SEND, 0, SEI_DAT_9, SEI_DAT_8, 8); /* ALMC */
/*26*/sei_set_instr(BOARD_SEI,instr_idx++, SEI_INSTR_OP_SEND, 0, SEI_DAT_0, SEI_DAT_9, 8);/* CRC */
/*27*/sei_set_instr(BOARD_SEI, instr_idx++, SEI_INSTR_OP_JUMP, 0, SEI_DAT_0, SEI_DAT_0, SEI_JUMP_INIT_INSTR_IDX);
/* Data ID6 : 0x32 */ /*write to eeprom */
/*28*/sei_set_instr(BOARD_SEI, instr_idx++, SEI_INSTR_OP_RECV_WDG, 0, SEI_DAT_9, SEI_DAT_2, 8); /* ADF */
/*29*/sei_set_instr(BOARD_SEI,instr_idx++, SEI_INSTR_OP_RECV_WDG, 0, SEI_DAT_9, SEI_DAT_3, 8); /* EDF */
/*30*/sei_set_instr(BOARD_SEI, instr_idx++, SEI_INSTR_OP_RECV_WDG, 0, SEI_DAT_0, SEI_DAT_9, 8); /* CRC */
/*31*/sei_set_instr(BOARD_SEI, instr_idx++, SEI_INSTR_OP_JUMP, 0, SEI_DAT_0, SEI_DAT_0, SEI_JUMP_CMD_TABLE_INSTR_IDX6);
/* Data IDD : 0xEA */ /*read from eeprom */
/*32*/sei_set_instr(BOARD_SEI, instr_idx++, SEI_INSTR_OP_RECV_WDG, 0, SEI_DAT_9, SEI_DAT_2, 8);/* ADF */
/*33*/sei_set_instr(BOARD_SEI, instr_idx++, SEI_INSTR_OP_RECV_WDG, 0, SEI_DAT_0, SEI_DAT_9, 8);/* CRC */
/*34*/sei_set_instr(BOARD_SEI, instr_idx++, SEI_INSTR_OP_JUMP, 0, SEI_DAT_0, SEI_DAT_0, SEI_JUMP_CMD_TABLE_INSTR_IDX6);
/*response to write/read eeprom */
/*35*/sei_set_instr(BOARD_SEI,instr_idx++, SEI_INSTR_OP_HALT, 0, SEI_DAT_0, SEI_DAT_0, 1); /* halt 1 bit for update */
/*36*/sei_set_instr(BOARD_SEI, instr_idx++, SEI_INSTR_OP_HALT, 0, SEI_DAT_0, SEI_DAT_0, 6); /* halt some bits for waiting */
/*37*/sei_set_instr(BOARD_SEI, instr_idx++, SEI_INSTR_OP_SEND, 0, SEI_DAT_9, SEI_DAT_1, 8);/* CF */
/*38*/sei_set_instr(BOARD_SEI, instr_idx++, SEI_INSTR_OP_SEND, 0, SEI_DAT_9, SEI_DAT_2, 8); /* ADF */
/*39*/sei_set_instr(BOARD_SEI, instr_idx++, SEI_INSTR_OP_SEND, 0, SEI_DAT_9, SEI_DAT_3, 8);/* EDF */
/*40*/sei_set_instr(BOARD_SEI, instr_idx++, SEI_INSTR_OP_SEND, 0, SEI_DAT_0, SEI_DAT_9, 8); /* CRC */
/*41*/sei_set_instr(BOARD_SEI,instr_idx++, SEI_INSTR_OP_JUMP, 0, SEI_DAT_0, SEI_DAT_0, SEI_JUMP_INIT_INSTR_IDX);
以上代碼為根據流程圖編寫的新指令預設內容。
/* [4] command table */
command_table_config.cmd_min_value= 0x02u;
command_table_config.cmd_max_value= 0x02u;
command_table_config.cmd_mask_value= 0xFFu;
command_table_config.instr_idx[0] = 2;
command_table_config.instr_idx[6] = 05;
sei_cmd_table_config_init(BOARD_SEI, BOARD_SEI_CTRL, SEI_CMD_TABLE_0,&command_table_config);
command_table_config.cmd_min_value= 0x8Au;
command_table_config.cmd_max_value= 0x8Au;
command_table_config.cmd_mask_value= 0xFFu;
command_table_config.instr_idx[0] = 2;
command_table_config.instr_idx[6] = 10;
sei_cmd_table_config_init(BOARD_SEI, BOARD_SEI_CTRL, SEI_CMD_TABLE_1,&command_table_config);
command_table_config.cmd_min_value= 0x92u;
command_table_config.cmd_max_value= 0x92u;
command_table_config.cmd_mask_value= 0xFFu;
command_table_config.instr_idx[0] = 2;
command_table_config.instr_idx[6] = 15;
sei_cmd_table_config_init(BOARD_SEI, BOARD_SEI_CTRL, SEI_CMD_TABLE_2,&command_table_config);
command_table_config.cmd_min_value= 0x1Au;
command_table_config.cmd_max_value= 0x1Au;
command_table_config.cmd_mask_value= 0xFFu;
command_table_config.instr_idx[0] = 2;
command_table_config.instr_idx[6] = 20;
sei_cmd_table_config_init(BOARD_SEI, BOARD_SEI_CTRL, SEI_CMD_TABLE_3,&command_table_config);
command_table_config.cmd_min_value= 0x32u;
command_table_config.cmd_max_value= 0x32u;
command_table_config.cmd_mask_value= 0xFFu;
command_table_config.instr_idx[0] = 28;
command_table_config.instr_idx[6] = 35;
sei_cmd_table_config_init(BOARD_SEI, BOARD_SEI_CTRL,SEI_CMD_TABLE_4,&command_table_config);
command_table_config.cmd_min_value= 0xEAu;
command_table_config.cmd_max_value= 0xEAu;
command_table_config.cmd_mask_value= 0xFFu;
command_table_config.instr_idx[0] = 32;
command_table_config.instr_idx[6] = 35;
sei_cmd_table_config_init(BOARD_SEI, BOARD_SEI_CTRL, SEI_CMD_TABLE_5,&command_table_config);
以上代碼為根據流程圖編寫的新指令匹配表。
/* [5] state transition config */
/* latch0 */
state_transition_config.disable_clk_check= true;
state_transition_config.disable_txd_check= true;
state_transition_config.disable_rxd_check= true;
state_transition_config.disable_timeout_check= true;
state_transition_config.disable_instr_ptr_check= false;
state_transition_config.instr_ptr_cfg= sei_state_tran_condition_fall_leave;
state_transition_config.instr_ptr_value= 2;
sei_state_transition_config_init(BOARD_SEI, BOARD_SEI_CTRL, SEI_LATCH_0, SEI_CTRL_LATCH_TRAN_0_1, &state_transition_config);
state_transition_config.disable_clk_check= true;
state_transition_config.disable_txd_check= true;
state_transition_config.disable_rxd_check= true;
state_transition_config.disable_timeout_check= true;
state_transition_config.disable_instr_ptr_check= true;
sei_state_transition_config_init(BOARD_SEI, BOARD_SEI_CTRL, SEI_LATCH_0, SEI_CTRL_LATCH_TRAN_1_2, &state_transition_config);
state_transition_config.disable_clk_check= true;
state_transition_config.disable_txd_check= true;
state_transition_config.disable_rxd_check= true;
state_transition_config.disable_timeout_check= true;
state_transition_config.disable_instr_ptr_check= true;
sei_state_transition_config_init(BOARD_SEI, BOARD_SEI_CTRL, SEI_LATCH_0, SEI_CTRL_LATCH_TRAN_2_3, &state_transition_config);
state_transition_config.disable_clk_check= true;
state_transition_config.disable_txd_check= true;
state_transition_config.disable_rxd_check= true;
state_transition_config.disable_timeout_check= true;
state_transition_config.disable_instr_ptr_check= true;
sei_state_transition_config_init(BOARD_SEI, BOARD_SEI_CTRL, SEI_LATCH_0, SEI_CTRL_LATCH_TRAN_3_0,&state_transition_config);
state_transition_latch_config.enable= true;
state_transition_latch_config.output_select= SEI_CTRL_LATCH_TRAN_0_1;
state_transition_latch_config.delay= 0;
sei_state_transition_latch_config_init(BOARD_SEI, BOARD_SEI_CTRL, SEI_LATCH_0,&state_transition_latch_config);
/* [6] state transition config */
/* latch1 */
state_transition_config.disable_clk_check= true;
state_transition_config.disable_txd_check= true;
state_transition_config.disable_rxd_check= true;
state_transition_config.disable_timeout_check= true;
state_transition_config.disable_instr_ptr_check= false;
state_transition_config.instr_ptr_cfg= sei_state_tran_condition_fall_leave;
state_transition_config.instr_ptr_value= 35;
sei_state_transition_config_init(BOARD_SEI, BOARD_SEI_CTRL, SEI_LATCH_1, SEI_CTRL_LATCH_TRAN_0_1, &state_transition_config);
state_transition_config.disable_clk_check= true;
state_transition_config.disable_txd_check= true;
state_transition_config.disable_rxd_check= true;
state_transition_config.disable_timeout_check= true;
state_transition_config.disable_instr_ptr_check= true;
sei_state_transition_config_init(BOARD_SEI, BOARD_SEI_CTRL,SEI_LATCH_1, SEI_CTRL_LATCH_TRAN_1_2, &state_transition_config);
state_transition_config.disable_clk_check= true;
state_transition_config.disable_txd_check= true;
state_transition_config.disable_rxd_check= true;
state_transition_config.disable_timeout_check= true;
state_transition_config.disable_instr_ptr_check= true;
sei_state_transition_config_init(BOARD_SEI, BOARD_SEI_CTRL, SEI_LATCH_1, SEI_CTRL_LATCH_TRAN_2_3,&state_transition_config);
state_transition_config.disable_clk_check= true;
state_transition_config.disable_txd_check= true;
state_transition_config.disable_rxd_check= true;
state_transition_config.disable_timeout_check= true;
state_transition_config.disable_instr_ptr_check= true;
sei_state_transition_config_init(BOARD_SEI, BOARD_SEI_CTRL, SEI_LATCH_1, SEI_CTRL_LATCH_TRAN_3_0, &state_transition_config);
state_transition_latch_config.enable= true;
state_transition_latch_config.output_select= SEI_CTRL_LATCH_TRAN_0_1;
state_transition_latch_config.delay= 0;
sei_state_transition_latch_config_init(BOARD_SEI, BOARD_SEI_CTRL, SEI_LATCH_1,&state_transition_latch_config);
鎖存器0配置為執(zhí)行完指令2(讀取位置信息CF的0.5us鎖存點)后進行位置鎖存;
鎖存器1配置為執(zhí)行完指令35(操作EEPROM指令CRC后0.5us鎖存點)后進行EEPROM操作;
voidisr_sei(void)
{
uint32_tdelta;
if(sei_get_irq_status(BOARD_SEI, BOARD_SEI_CTRL, sei_irq_latch0_event)) {
sei_clear_irq_flag(BOARD_SEI, BOARD_SEI_CTRL, sei_irq_latch0_event);
sei_set_data_rewind(BOARD_SEI,SEI_DAT_9);
sample_latch_tm1= sei_get_latch_time(BOARD_SEI, BOARD_SEI_CTRL, SEI_LATCH_0);
mock_pos++;
if(mock_pos> 0x00FFFFFF) {
mock_pos= 0;
mock_rev++;
if(mock_rev> 0x00FFFFFF) {
mock_rev= 0;
}
}
sei_set_sample_pos_override_value(BOARD_SEI, BOARD_SEI_CTRL, mock_pos);
sei_set_sample_rev_override_value(BOARD_SEI, BOARD_SEI_CTRL, mock_rev);
sei_set_data_value(BOARD_SEI, SEI_DAT_4, 0x00);
sei_set_data_value(BOARD_SEI, SEI_DAT_6, 0x17);
sei_set_data_value(BOARD_SEI, SEI_DAT_8, 0x00);
delta= (sample_latch_tm1> sample_latch_tm2) ? (sample_latch_tm1- sample_latch_tm2) : (sample_latch_tm1- sample_latch_tm2+ 0xFFFFFFFFu);
printf("CMD:%#x, SF:%#x, ST:%#x, ENID:%#x,MT:%#x, ALMC:%#x, CRC:%#x,sample_tm1:%u,sample_tm2:%u, sample_interval:%dus\n",
sei_get_command_value(BOARD_SEI, BOARD_SEI_CTRL),
sei_get_data_value(BOARD_SEI, SEI_DAT_4),
sei_get_data_value(BOARD_SEI, SEI_DAT_5),
sei_get_data_value(BOARD_SEI, SEI_DAT_6),
sei_get_data_value(BOARD_SEI, SEI_DAT_7),
sei_get_data_value(BOARD_SEI, SEI_DAT_8),
sei_get_data_value(BOARD_SEI, SEI_DAT_9),
sample_latch_tm1, sample_latch_tm2, delta/ (clock_get_frequency(BOARD_MOTOR_CLK_NAME) / 1000000));
sample_latch_tm2= sample_latch_tm1;
}
elseif(sei_get_irq_status(BOARD_SEI, BOARD_SEI_CTRL, sei_irq_latch1_event)) {
sei_clear_irq_flag(BOARD_SEI, BOARD_SEI_CTRL, sei_irq_latch1_event);
uint32_tcmd= sei_get_command_value(BOARD_SEI, SEI_CTRL_1);
if(cmd== 0x32u) {
uint32_taddr= sei_get_data_value(BOARD_SEI, SEI_DAT_2);
uint32_tdata= sei_get_data_value(BOARD_SEI, SEI_DAT_3);
if(addr== 127) {
eeprom_page= data;
}else{
eeprom[eeprom_page][addr] = data;
}
}elseif(cmd== 0xEAu) {
uint32_taddr= sei_get_data_value(BOARD_SEI, SEI_DAT_2);
sei_set_data_value(BOARD_SEI, SEI_DAT_3, eeprom[eeprom_page][addr]);
}
}
if(sei_get_irq_status(BOARD_SEI, BOARD_SEI_CTRL, sei_irq_wdog_event)) {
sei_clear_irq_flag(BOARD_SEI, BOARD_SEI_CTRL, sei_irq_wdog_event);
sei_set_command_rewind(BOARD_SEI, BOARD_SEI_CTRL);
printf("WDG!\n");
}
if(sei_get_irq_status(BOARD_SEI, BOARD_SEI_CTRL, sei_irq_trx_err_event)) {
sei_clear_irq_flag(BOARD_SEI, BOARD_SEI_CTRL, sei_irq_trx_err_event);
printf("TRX Error!\n");
}
}
在中斷內,sei_irq_latch0_event分支處理位置鎖存信息;sei_irq_latch1_event根據收到的指令信息對eeprom數組和地址頁進行操作,更新數據/設置回復數據。
5 小結
相信通過以上針對SEI的講解,及對多摩川協議、例程代碼的分析與修改,讀者對SEI有了更深的認識,希望開發(fā)者可以用好SEI模塊,加速項目開發(fā)與落地。
-
編碼器
+關注
關注
45文章
3638瀏覽量
134426 -
異步通信
+關注
關注
1文章
57瀏覽量
10124 -
異步通訊
+關注
關注
0文章
12瀏覽量
7465 -
先楫半導體
+關注
關注
10文章
214瀏覽量
2102
發(fā)布評論請先 登錄
相關推薦
評論