顯示具有 W79E632 標籤的文章。 顯示所有文章

winbond reset status

Posted by: 邱小新 at 上午10:08 in ,

記錄一下系統開機或是被 reset 時的一些旗標狀態。

旗標狀態

resetWTRFPOREWTWDCON判斷
power-on reset01001000000bPOR=1
external resetxxx0x0x0xx0bEWT=1*
POR=0#
watchdog reset1xx0x0x01x0bWTRF=1

註解

  1. x: 保留原值,不會變更。
  2. *: 系統如果有開啟 watchdog 功能,在發生 external reset 時,EWT 一定是 1。
  3. #: 一開機時 POR=1,此時把 POR 設成 0,下次發生 external reset 時,POR 一定是 0,以此來區分。適合沒有開啟 watchdog 功能的系統。

判斷順序

  1. 開啟 watchdog: WTRF=1(watchdog) -> EWT=1(external) -> POR=1(power-on)。
  2. 關閉 watchdog: POR=1(power-on) -> POR=0(external),watchdog 不用判斷。

reset 開機狀態

  1. Program Counter 強制跳回 0000h,也就是從頭開始執行。
  2. SFR 都會返回 reset value,datasheet 有一張表。
  3. stack point 會變成 07h。
  4. Vdd 小於 2V 時,RAM 資料會遺失;反之則會保存。

tiny rtos for 8051 part5

Posted by: 邱小新 at 下午4:24 in , ,
原始碼下載

到這裏應該算是一個總結了,後面有什麼功能,再慢慢來想吧。這次主要是加入了 rtos delay 函數,讓 delay 更為精準,也讓空出來的時間,給其它 task 去執行,並且加入了 rtos_idle 函數,利用 cpu idle 功能達到省電功能,當然如果你有用到 PWM 時,記得把這個功能換掉,免得 PWM 不動了。

主要加入的功能

  1. rtos_idle 函數主要是在所有 task 都在 wait 時要執行的函數。由於 rtos_idle 沒有用到任何的堆疊空間,所以在計算每一個 task 的堆疊空間時,把 idle task 的空間直接定義成 17 bytes,就造成 size = (256 - SP - 17) / MAX_TASKS;,而非 size = (256 - SP) / (MAX_TASKS + 1);。

  2. rtos_nexttask 函數主要是用來做切換任務的工作,並根據 rtos_tick 決定是否要執行。

  3. rtos_isr 函數中加入了計時功能(以 10ms 為一個單位),並把 nexttask 功能分離出來,並加上 RETI 把後面的 POP 擋掉。

  4. rtos_scheduling 函數主要是用在非中斷環境下執行 nexttask 功能。

  5. rtos_delay_10ms 函數主要是用來做時間延時用的,每 10ms 為一單位。

程式執行結果為 0.5 秒顯示數字,1 秒顯示字母,也就是看到 1a23b45c67d89e12f34g56h78i9 如此循環顯示的字串。

tiny rtos for 8051 part4

Posted by: 邱小新 at 下午4:40 in , ,
原始碼下載

這次修改的內容,主要是加入 code banking 功能。

  1. 這次主要是參考 Keil C51 的 RTX-51 code banking 設定,利用 ?B_CURRENTBANK 及呼叫 ?B_RESTORE_BANK 來切換。

  2. L51_BANK.A51 除了主要的設定外,需要把 ?B_RTX 也設成 1,才能讓 ?B_RESTORE_BANK 函數可以使用。

  3. 在初始化過程中,也要先切換第一個 task 的 code bank。

tiny rtos for 8051 part3

Posted by: 邱小新 at 下午3:49 in , ,
原始碼下載

在 tiny rtos for 8051 part2 裏,本來想把已經測試好的程式碼加入 code banking 的相容性,但經過幾天幾夜的測試,不管怎麼做都會出錯,真是莫名奇妙。後來就倒回去看看是否之前程式碼是否也有問題,結果真的是如此。part1 的程式碼執行無誤,part2 的程式碼執行有時會出錯。經過反覆檢查,發現把 interrupt 的程式碼全改成 assembly 就會出錯,即使照著 Keil C51 編出來的 assembly code 寫進去也是一樣有問題,只能猜想是否在 link 過程中,又被動了一些手腳,造成程式莫名奇妙的出錯吧。

這次主要修改的內容

  1. 原本 rtos_isr 函數維持加入部份 assembly code,不要全部改成 assembly code。

  2. ?C_IBP 儲存方式改成放入堆疊裏,以利精簡程式碼,減少 interrupt 執行時間。

  3. 原本的 void (* const task_func[MAX_TASKS])(void) 改成 unsigned int code task_func[MAX_TASKS],將函數指標改成一般變數放在 rom 裏,如此可以節省記憶體用量,也精簡程式碼。

  4. 為了避免 LCALL rtos_start 變成 LJMP rtos_start 問題,直接改變 SP 的初始化過程,藉由修改 STARTUP.A51 來增加 STACK 位址的讀取。

  5. 不可以將 STARTUP.A51 中的 IBPSTACK 設成 1,原來使用 reentrant 函數都需要將 IBPSTACK 設成 1,但是不知什麼原因,在用 IspWriter 燒錄完後的自動重啟執行都會出現怪怪的執行結果。

tiny rtos for 8051 part2

Posted by: 邱小新 at 下午2:08 in , ,

經過反覆測試,發現將 interrupt 全改寫成 assembly 會造成不明原因輸出錯誤,這個原始碼不要用喔,後面有解決方法。

原始碼下載

在這次的實驗裏要解決 reentrant 函數的問題,其實也很簡單,就是把 reentrant 的 stack 變數依照每個 task 儲存起來,執行該 task 時,再回復其值就好了。程式碼如下,都是用 c 語法做說明,實際程式碼很多都改成 assemble 語法,主要是因為 Keil C51 的 reentrant stack 是存在 ?C_IBP,而 C 語法不允許變數有 ? 符號,所以就改成用 asseble 來寫。

void rtos_isr(void) interrupt 1 { // save current stack rtos_stack[rtos_task_id] = SP; rtos_stack_IBP[rtos_task_id] = ?C_IBP; // load next stack if (++rtos_task_id >= MAX_TASKS) rtos_task_id = 0; SP = rtos_stack[rtos_task_id]; ?C_IBP = rtos_stack_IBP[rtos_task_id]; } void rtos_start(void) { xdata unsigned char i, size; xdata unsigned char idata *sp; // variable init rtos_task_id = 0; // stack init size = (256 - SP + 2) / MAX_TASKS; sp = (unsigned char idata *)SP; for (i=0; i<MAX_TASKS; i++) { *sp-- = ((unsigned int)(task_func[i])) / 256; *sp-- = ((unsigned int)(task_func[i])) % 256; rtos_stack[i] = sp + 15; sp += size; rtos_stack_IBP[i] = sp; sp += 2; } ?C_IBP = rtos_stack_IBP[0]; // timer0 init TMOD = (TMOD & 0xF0) | 0x01; TH0 = 0; TL0 = 0; TF0 = LOW; ET0 = HIGH; TR0 = HIGH; }

接下來二個 test tasks 就全改成 reentrant,如此就不會有 data overlaying 的問題,而且 Code Optimization Level 也可以調到 7:Extended Index Access Optimizing。執行結果就會看到數字跟英文字母相互出現。

void task1(void) reentrant { unsigned char i=0x30; while(1) { if (++i>=0x3a) i=0x31; putchar(i); delay_1ms(100); } } void task2(void) reentrant { unsigned char j=0x60; while(1) { if (++j>=0x6a) j=0x61; putchar(j); delay_1ms(100); } }

寫到這裏也許有人會覺得奇怪,為什麼 Code Optimization Level 沒有調到預設值 8:Reuse of Common Entry Code?主要是因為在 rtos_start 裏,我利用 LCALL 的特性把 stack 裏的返回位址改成 task1 的位址,而 level 8 會把 main 函數裏的 LCALL rtos_start 改成 LJMP rtos_start,造成程式無法執行。當然只要一個小修改就可以修正掉這個 bug 了。

tiny rtos for 8051 part1

Posted by: 邱小新 at 下午3:50 in , ,
原始碼下載

最近有空去研究了一下陳明計的 small rtos for 8051,看了老半天,還是看不懂他在寫什麼;尤其是他在 stack 的處理方式,實在是有看沒有懂。所以自己就自己來寫了一套 tiny rtos for 8051。沒有 semaphore,也沒有 task priority,什麼都沒有,只有簡單的時間分配,也就是所有工作時間都一致,current task 工作固定時間後,再換 next task 工作固定時間,如此循環工作。

工作原理也很簡單,如果有 n 個 tasks 就把 stack 分成 n 等份,讓每個 task 保有自己的 stack,不要互相干擾就可以。再利用 timer interrupt 來切換 task。很簡單吧,就如下面程式碼所列,並不會很難。

#define MAX_TASKS 2 unsigned char rtos_task_id; unsigned char rtos_stack[MAX_TASKS]; void (* const task_func[MAX_TASKS])(void)={ task1, task2 }; void rtos_isr(void) interrupt 1 { // save current stack rtos_stack[rtos_task_id] = SP; // load next stack if (++rtos_task_id >= MAX_TASKS) rtos_task_id = 0; SP = rtos_stack[rtos_task_id]; } void rtos_start(void) { xdata unsigned char i, size; xdata unsigned char idata *sp; rtos_task_id = 0; size = (256 - SP + 2) / MAX_TASKS; sp = (unsigned char idata *)SP; for (i=0; i<MAX_TASKS; i++) { *sp-- = ((unsigned int)(task_func[i])) / 256; *sp-- = ((unsigned int)(task_func[i])) % 256; rtos_stack[i] = sp + 15; sp += size + 2; } TMOD = (TMOD & 0xF0) | 0x01; TH0 = 0; TL0 = 0; TF0 = LOW; ET0 = HIGH; TR0 = HIGH; }

寫了二個測試函數,主要就是從 rs232 印出 1~9 及 a~i,如下所示。

void task1(void) { xdata unsigned char i=0x30; while(1) { if (++i>=0x3a) i=0x31; putchar(i); delay_1ms(50); } } void task2(void) { xdata unsigned char j=0x60; while(1) { if (++j>=0x6a) j=0x61; putchar(j); delay_1ms(50); } }

但是結果卻不如預期,跑出來的東西都是亂碼,傻眼。最後,經過了二天的努力,總算把結果正確無誤的弄出來了。主要有下列幾個地方要修改。

  1. 把 C51 的 Code Optimization Level 降成 1:Dead code elimination。因為 Data overlaying 的關係,造成 task1 的 i 變數跟 task2 的 j 變數共用同樣的位址,所以讓印出來的值都在 1~9 跳動。

  2. 原本 data overlaying 問題想要利用 reentrant 指令來建立可重入函數去解決,但最後發現仍然是無效。因為 keil 把變數都放在一個 ?C_IBP 的位址,仍然會造成共用的問題,這個問題真是難解啊,以後如果要寫複雜的 multi-task 函數有一定的難度,必須克服可重入函數及 data overlaying 造成的問題。

  3. 在 rtos_isr 函數裏加入 push 及 pop 指令,把 R0~R7,ACC,B,PSW,DPH,DPL 都丟到 stack 裏去。因為 keil 都會利用這些暫存器做一些運算,在進入 interrupt 時,也會主動 push 一些在 interrupt 會用到的暫存器到 stack 裏,但其它沒用到的暫存器就沒有主動 push,造成切換到其它 task 再切回原來 task 時,那些暫存器裏的值都被變更了,而造成運算錯誤。

  4. 另外在加入 assembly code 時,需把 Generate Assembler SRC File 及 Assemble SRC File 都打勾才可以,缺一不可。

W79E632 code banking using Keil C51

Posted by: 邱小新 at 下午3:40 in ,
  1. copy C:\Keil\C51\LIB\L51_BANK.A51 到專案目錄下。

  2. 修改 L51_BANK.A51 中的設定。
    ?B_NBANKS EQU 4 改成 ?B_NBANKS EQU 2。

  3. 在 mcu_init 中加入 ROMCON = 0x0A;,藉此設定 P1.2 as A16 並開啟 code banking 功能。

  4. 將 L51_BANK.A51 加入 project source file 裏。

  5. 進入 Project --> Manage --> Components, Environment and Books。

  6. 在 Groups 裏新增 bank0 及 bank1,完成後會在 Project Workspace 會出現 bank0 及 bank1 二個目錄。

  7. 在 bank0 按右鍵,選擇 Options for Group 'bank0',在 Code Bank 處選擇 "Bank #0"。

  8. 在 bank1 按右鍵,選擇 Options for Group 'bank1',在 Code Bank 處選擇 "Bank #1"。

  9. 在 bank0 及 bank1 各新增一個 souce file。

  10. 完成編譯後,原本會產生一個 xxx.HEX,現在則產生 xxx.H00 及 xxx.H01 二個檔案。

範例程式碼下載

SDCC autobaud function

Posted by: 邱小新 at 下午3:56 in , ,

測試原由

SDCC 的 serial.h 內有一行 void autobaud(); 宣告,表示有自動鮑率偵測功能。所以就在 W79L632A 上實驗是否可行。它的原理是假定使用者第一次會輸入 return 鍵,也就是 ascii code 13。依照這個值利用 timer1 算時間差來做運算,進而取得 timer1 8-bit auto reload 的 TH 值。以下是測試的程式碼,大多是參考 SDCC 內的 serial.c 函數功能。

變數宣告

#include <8051.h> extern void autobaud();

輸出函數

void putchar(char c) { while(!TI); TI=0; SBUF=c; }

輸入函數

char getchar(void) { char c; while(!RI); RI=0; c=SBUF; return c; }

主要函數

void main(void) { ES=0; /* kill SIO IRQ */ TI=0; /* prepare sending */ RI=0; /* prepare reading */ autobaud(); /* automatically detect and set baud rate */ getchar(); /* discard the CR character from the autobaud routine */ // echo while(1) { putchar(getchar()); } }

測試結果

結果非常失望,完全沒有作用,功能無效。不知是不是因為我的 W79L632A 使用 40MHz 的震盪器。也不知 winbond LD 的 autobaund 功能怎麼寫的?只好放棄這個功能囉。

W79L632A ISP Operation Modes register

Posted by: 邱小新 at 下午1:33 in
  1. BANK: BANK=0 選擇 Flash 0,BANK=1 選擇 Flash 1,由於 LD 只有一個 bank,所以當 WFWIN=0 時,BANK 不可寫入 1。
  2. WFWIN: WFWIN=0 選擇 LDFlash,WFWIN=1 選擇 APFlash。
  3. NOE: NOE=0 唯讀模式,NOE=1 寫入模式。
  4. NCE: NCE=0 flash 燒錄模式,NCE=1 flash 工作模式。
  5. CTRL[3:0]: 燒錄模式選擇。

ISP MODEBANKWFWINNOENCECTRLSFRCNtime
抹除 LDFlash011000100x6215ms
抹除 APFlash0001000100x2215ms
抹除 APFlash1101000100xA215ms
寫入 LDFlash011000010x6150us
寫入 APFlash0001000010x2150us
寫入 APFlash1101000010xA150us
讀取 LDFlash010000000x401.5us
讀取 APFlash0000000000x001.5us
讀取 APFlash1100000000x801.5us

  1. 抹除功能一次可抹除整個 flash,抹除完成後全部的值都變成 0xff。
  2. 讀寫功能一次只能讀寫一個 byte。
  3. 操作時間要視 XTAL 的速度來計算,上述的值是以 XTAL=24MHz 來計算。
  4. SFRAH/SFRAL 儲放欲讀寫的位址,SFRFD 則儲放讀寫的值。

W79E632A ISP control register

Posted by: 邱小新 at 上午11:37 in
  1. SWRST: software reset,令 W79E632A 回到初始狀態,並自動清除這個 bit。
  2. HWB: hardware boot,HWB=1 表示 ISP hardware reboot mode。
  3. LDAP: reand only,LDAP=1 表示在 LDFlash 運行,LDAP=0 表示在 APFlash 運行。
  4. LDSEL: LDSEL=1 表示從 LDFlash 讀取 code 執行。
  5. ENP: ENP=1 表示進入 the ISP mode。

從 APFlash 進入 LDFlash

TA = 0xAA; TA = 0x55; CHPCON = CHP_LSEL | CHP_ENP; SFRCN = 0; /* 不執行也可以, 原廠 sample code 有做 */ PCON |= IDL;

從 LDFlash 進入 APFlash

TA = 0xAA; TA = 0x55; CHPCON = SWRST | CHP_LSEL | CHP_ENP; SFRCN = 0; /* 不執行也可以, 原廠 sample code 有做 */ PCON |= IDL;

在 LDFlash 執行 ISP 指令前,需先指定 CHPCON 參數,只需指定一次即可。

TA = 0xAA; TA = 0x55; CHPCON = CHP_LSEL | CHP_ENP; SFRCN = 0; /* 不執行也可以, 原廠 sample code 有做 */ PCON |= IDL; /* 不執行也可以, 原廠 sample code 有做 */

在 APFlash 執行 ISP 指令前,需先指定 CHPCON 參數,只需指定一次即可。

TA = 0xAA; TA = 0x55; CHPCON = CHP_ENP; SFRCN = 0; /* 不執行也可以, 原廠 sample code 有做 */ PCON |= IDL; /* 不執行也可以, 原廠 sample code 有做 */

注意事項

  1. CHPCON 在寫入時需要 timed access protection
  2. CHPCON 在進入 idle mode 才會執行上述指令,所以記得要讓 W79L632A 離開 idle mode,原廠 sample code 使用 XTAL=24MHz 在 idle mode 花費 8us。
  3. 其實可以不要理會 datasheet 上在寫什麼,記住切換 flash 要如上述的下指令即可,不要想要更動指令,會產生錯誤的結果,因為我已經試過都無效了。

watchdog interrupt function

Posted by: 邱小新 at 下午5:13 in

watchdog time-out 後會呼叫 watchdog interrupt function,再經過 512 clock 後會做 reset 8051 動作。如果在這 512 clock 之間重置 watchdog 就不會 reset 8051。經過測試結果,在很久很久的時間過後,仍有機會引起 reset 動作,也就是 reset watchdog 沒有來得急做,即使把 watchdog interrupt priority 提高也是一樣。最好不要用喔。

void watchdog_isr(void) interrupt 12 { // clear interrupt flag TA = 0xAA; TA = 0x55; WDIF = 0; // reset watchdog TA = 0xAA; TA = 0x55; RWT= 1; }

W79E632A 啟動時的旗標

Posted by: 邱小新 at 下午4:46 in
flagPower-on resetWatchdog resetExternal reset
POR1xx
WTRF010
EWT0xx
WDCON01000000b0x0x01x0b0x0x0xx0b

由上表得知一些判斷開機的因素,整理如下:

  1. 判斷是因為電源開關所引起的開機。
    只要判斷 POR 為 1 即可,開完機後需要立即把 POR 清為 0,以利後續判斷。
  2. 判斷是因為 watchdog 所引起的開機。
    只要判斷 WTRF 為 1 即可,開完機後需要立即把 WTRF 清為 0,以利後續判斷。
  3. 判斷是因為外部中斷所引起的開機。
    只要不是上述二個條件就是外部中斷引起的。
if (POR) { POR = 0; // power-on reset } else if(WTRF) { WTRF = 0; // watchdog reset } else { // external reset } PS: 一開機後請立即清除 EWT,以免 watchdog reset 再次發生。

W79E632 watchdog function

Posted by: 邱小新 at 下午3:27 in

啟動 watchdog 程序

  1. 先關閉 watchdog 功能,防止一些干擾的問題。
  2. 選擇 watchdog time-out 時間。
  3. 設定 watchdog 中斷開關。
  4. 開啟 watchdog 重置工作。
  5. 開啟 watchdog 功能。
void watchdog_start(void) { // clear watchdog flag TA = 0xAA; TA = 0x55; WDCON = 0; // select 2^26 time-out interval CKCON |= 0xC0; // disable watchdog interrupt EWDI = 0; // start watchdog reset task poller_start(POLLER_WATCHDOG, TIMER_WATCHDOG); // enable watchdog TA = 0xAA; TA = 0x55; WDCON = 3; }

關閉 watchdog 程序

void watchdog_stop(void) { TA = 0xAA; TA = 0x55; EWT= 0; }

重置 watchdog 程序

void watchdog_reset(void) { TA = 0xAA; TA = 0x55; RWT= 1; } PS: 一開機後請立即清除 EWT,以免 watchdog reset 再次發生。

W79x632A timed access protection

Posted by: 邱小新 at 下午1:08 in
  1. W79L632A 有幾個 register 需要接受寫入保護,免得招到中斷破壞,導致問題出現。
  2. 這些需要寫入保護的 register,一定要使用寫入保護方式才可以做寫入動作,其餘無效。
  3. 做法為寫入 TA=0xAA; 再寫入 TA=0x55; 後,有三個 machine cycles 時間受到寫入保護,不被干擾。

受到寫入保護的 register
  1. WDCON
  2. POR
  3. EWT
  4. WDIF
  5. RWT
  6. CHPCON

TA REG C7H MOV TA, #AAH MOV TA, #55H MOV WDCON, #00H

watchdog 中斷觸發時間

Posted by: 邱小新 at 上午11:38 in

watchdog 中斷觸發時間計算方式:(以 40MHz 為例)
1/40000000 * 2^17 = 131072/40000000 = 0.0032768(s) = 3.2768(ms)

WD1WD0intervalclocks@40MHz
002^171310723.2768 ms
012^20104857626.2144 ms
102^238388608209.7152 ms
112^26671088641677.7216 ms

Idle mode 省電功能

Posted by: 邱小新 at 上午10:24 in
  1. 進入 idle mode 後,CPU clock 會停止,進而逹到省電效果。
  2. 只要中斷產生,就可以回復程式執行,會從進入 idel mode 的命令之後開始執行。
  3. 在 main loop 不可有即時性工作,以免進入 idel mode 後無法執行而造成錯誤。
  4. 切記,當使用到 PWM 指令時,不可進入 idle mode,會失效的。

/* entry the idle mode */ PCON |= 1;

W79L632A on-chip 1KB MOVX SRAM

Posted by: 邱小新 at 上午10:03 in
  1. 空間位址在 0x0000 ~ 0x03ff。
  2. 只能使用 MOVX 指令來讀寫,也就是設成 xdata 的變數。
  3. PMR 中 DME0 (bit 0) 可以設定是否使用 on-chip。
    DME0=0,0x0000~0xffff 都指向外部記憶體。
    DME1=0,0x0000~0x03ff 指向內部記憶體。

/* enable on-chip 1KB MOVX SRAM */ PMR |= 0x01;

W79L632A register define

Posted by: 邱小新 at 上午9:56 in
#include <8052.h> /* ------------------------------------------------ */ /* The SFRs reside in the register locations 80-FFh */ /* and are accessed by direct addressing only. */ /* ------------------------------------------------ */ __sfr __at (0x8E) CKCON; __sfr __at (0x92) P4CONA; __sfr __at (0x93) P4CONB; __sfr __at (0x9F) CHPCON; __sfr __at (0xA5) P4; __sfr __at (0xA9) SADDR; __sfr __at (0xAB) ROMCON; __sfr __at (0xAC) SFRAL; __sfr __at (0xAD) SFRAH; __sfr __at (0xAE) SFRFD; __sfr __at (0xAF) SFRCN; __sfr __at (0xC3) PWM5; __sfr __at (0xC4) PMR; __sfr __at (0xC7) TA; __sfr __at (0xCE) PWMCON2; __sfr __at (0xCF) PWM4; __sfr __at (0xD8) WDCON; __sfr __at (0xD9) PWMP; __sfr __at (0xDA) PWM0; __sfr __at (0xDB) PWM1; __sfr __at (0xDC) PWMCON1; __sfr __at (0xDD) PWM2; __sfr __at (0xDE) PWM3; __sfr __at (0xE8) EIE; __sfr __at (0xF8) EIP; /* ------------------------------------------------ */ /* The SFRs that are bit addressable are those */ /* whose addresses end in 0 or 8. */ /* ------------------------------------------------ */ __sbit __at (0xD8) RWT ; /* protected bit */ /* Mnemonic:WDCON, bit 0 */ __sbit __at (0xD9) EWT ; /* protected bit */ __sbit __at (0xDA) WTRF; __sbit __at (0xDB) WDIF; /* protected bit */ __sbit __at (0xDC) WD_4; /* not used */ __sbit __at (0xDD) WD_5; /* not used */ __sbit __at (0xDE) POR ; /* protected bit */ /* Mnemonic:WDCON, bit 6 */ __sbit __at (0xDF) WD_7; /* not used */ //---------------------------------------------------------------------- // EIE register 0xE8 (Extended Interrupt Enable register) // 7 6 5 4 3 2 1 0 // X X X EWDI X X X X //---------------------------------------------------------------------- __sbit __at (0xEC) EWDI; //---------------------------------------------------------------------- // EIP register 0xF8 (Extended Interrupt Priority register) // 7 6 5 4 3 2 1 0 // X X X PWDI X X X X //---------------------------------------------------------------------- __sbit __at (0xFC) PWDI;//---------------------------------------------------------------------- // PWMCON1 register 0xDC (PWM control 1 register) // 7 6 5 4 3 2 1 0 // PWM3OE PWM2OE ENPWM3 ENPWM2 PWM1OE PWM0OE ENPWM1 ENPWM0 //---------------------------------------------------------------------- #define PWM3OE 0x80 // Output enable for PWM3 #define PWM2OE 0x40 // Output enable for PWM2 #define ENPWM3 0x20 // Enable PWM3 #define ENPWM2 0x10 // Enable PWM2 #define PWM1OE 0x08 // Output enable for PWM1 #define PWM0OE 0x04 // Output enable for PWM0 #define ENPWM1 0x02 // Enable PWM1 #define ENPWM0 0x01 // Enable PWM0 //---------------------------------------------------------------------- // PWMCON2 register 0xCE (PWM control 2 register) // 7 6 5 4 3 2 1 0 // X X X X PWM5OE PWM4OE ENPWM5 ENPWM4 //---------------------------------------------------------------------- #define PWM5OE 0x08 // Output enable for PWM5 #define PWM4OE 0x04 // Output enable for PWM4 #define ENPWM5 0x02 // Enable PWM5 #define ENPWM4 0x01 // Enable PWM4 //---------------------------------------------------------------------- // PCON register 0x87 (power control register) // 7 6 5 4 3 2 1 0 // SMOD X X X GF1 GF0 PD IDL //---------------------------------------------------------------------- #define PCON_SMOD 0x80 // double baud rate, when serial mode 1,2,3 #define PCON_GF1 0x08 // general purpose #define PCON_GF0 0x04 // general purpose #define PCON_PD 0x02 // entry power down mode #define PCON_IDLE 0x01 // entry idle mode //---------------------------------------------------------------------- // CHPCON register 0x9F (ISP control register) protected byte // 7 6 5 4 3 2 1 0 // SWRST X LDAP X X X LSEL ENP //---------------------------------------------------------------------- #define CHP_SWRST 0x80 // Set this bit to launch a whole device reset // that is same as asserting high th RST pin. #define CHP_LDAP 0x20 // read only. High: the device is excuting the program in LDFlash // Low: the device is excuting the program in APFlashs #define CHP_LSEL 0x02 // Set to high to route the device fetching code from LDFlash #define CHP_ENP 0x01 // Set this be to launch the ISP mode

W79E632A security bits 說明

Posted by: 邱小新 at 上午10:20 in
  1. 出廠 default 值為 0xFF,存放位址在 LDFlash 的 0xFFFF(根據 W78E65 datasheet 猜測值)。
  2. 當某一個 bit 變成 0 後,就不可以再改成 1,要變成 1 的唯一方法就是使用 earse LDFlash 功能。
  3. Bit 0 - Lock bit (LOCK BIT)
    設成 0 時 (Active),flash 及 security 都無法讀取。
  4. Bit 1 - MOVC Inhibit (MOVC BIT)
    設成 0 時 (Enable),當 MOVC 指令在外部記憶体空間時,只能存取外部記憶体。當 MOVC 指令在內部記憶体空間時,則可以存取內部及外部記憶體。
  5. Bit 2,3 -- reserved 沒用到
  6. Bit 4 - H/W Reboot with P2.6 and 2.7 (Set P2 reboot)
    設成 0 時 (Enable),在開機時(RST = HIGH),P2.6 = LOW and P2.7 = LOW 時,MCU 會進入 LDFlash。
  7. Bit 5 - H/W Reboot with P4.3 (Set P4 reboot)
    設成 0 時 (Enable),在開機時(RST = HIGH),P4.3 = LOW 時,MCU 會進入 LDFlash。
  8. Bit 6 -- reserved 沒用到
  9. Bit 7 -- Select clock freqency (Osillator Control)
    設成 0 時 (FULL),MCU 頻率小於 24 MHz。
    設成 1 時 (1/2),MCU 頻率大於 24 MHz。