From 07d2ace8b4771e2ad48d4a9e6bf43a2022a25fac Mon Sep 17 00:00:00 2001 From: Joe Zhao Date: Fri, 23 May 2014 15:36:51 +0800 Subject: Added SYSSTOP & MSTATE macro New example main.c --- rs422lib/main.c | 67 +++++++++- rs422lib/precomp.h | 75 +++++------ rs422lib/rsbus.c | 364 ++++++++++++++++++++++++++--------------------------- rs422lib/rsbus.h | 130 +++++++++---------- rs422lib/sysctl.c | 8 +- rs422lib/sysctl.h | 118 ++++++++--------- 6 files changed, 418 insertions(+), 344 deletions(-) diff --git a/rs422lib/main.c b/rs422lib/main.c index 2a2517f..34cb03e 100644 --- a/rs422lib/main.c +++ b/rs422lib/main.c @@ -4,6 +4,7 @@ #include"sysctl.h" int cnt=0; +int cnt2=0; void port_init(void) { @@ -13,7 +14,52 @@ void port_init(void) void received(unsigned char* str,unsigned int len) { - rsbus_w(0,str,len); + unsigned char ch; + switch (str[0]) + { + case 1:// start + if (!MSTATE) + { + SWITCH_STATE(ST_RUN); + cnt2=0; + STATE(0)=0; + SYSCALL(TEST); + } + RETSTATE; + break; + case 2:// Get Res + if (MSTATE&ST_RUN) + { + ch=(unsigned char)(cnt2-STATE(0)); + rsbus_w(0,&ch,1); + } + else + if (MSTATE&ST_RES) + { + SWITCH_STATE(ST_REST); + ch=(unsigned char)(cnt2); + rsbus_w(0,&ch,1); + } + else + RETSTATE; + break; + case 3:// Stop + if (MSTATE&ST_RUN) + { + SWITCH_STATE(ST_REST); + SYSSTOP(TEST); + } + RETSTATE; + break; + case 4:// Block + if (!MSTATE) + { + cnt2=0; + SWITCH_STATE(ST_BUSY); + } + RETSTATE; + } + //rsbus_w(0,str,len); } // Timer A0 interrupt service routine @@ -24,13 +70,19 @@ __interrupt void Timer_A0 (void) if (cnt==25) { STATE(0)=(STATE(0)+1)&0xFF; + if ((MSTATE&ST_BUSY) && !(MSTATE&ST_RES)) + { + ++cnt2; + if (STATE(0)>200) + SWITCH_STATE(ST_BUSY|ST_RES); + } cnt=0; P1OUT^=BIT6; } } //TIMER A0 initialize - -// desired value: 5ms +// desired value: 40ms void TimerA0_Init(void) { // Configure TimerA0 @@ -60,9 +112,20 @@ void init_devices(void) _BIS_SR(GIE); } +// Clock tick using cycle estimation +void basic_running_ex() +{ + int i; + for (i=950;i>0;--i) + delay_ms(1); + ++cnt2; + SYSCALL(TEST); +} + void main(void) { init_devices(); + sysctl_reghdlr(TEST,basic_running_ex); while(1) sysroutine(); } diff --git a/rs422lib/precomp.h b/rs422lib/precomp.h index d2d2380..6e54606 100644 --- a/rs422lib/precomp.h +++ b/rs422lib/precomp.h @@ -1,37 +1,38 @@ -/* - * precomp.h - * - * Created on: 2014-4-26 - * Author: Tuowen - */ - -#ifndef PRECOMP_H_ -#define PRECOMP_H_ - -#include - -// ====== RSBUS configuration ====== - -// Data Enable pin configuration -// P1.0 -> red led -#define RSDIR (P1DIR) -#define RSOUT (P1OUT) -#define RSPIN (BIT0) - -// This is the highest level -#define RSSYSBIT (SYS_BIT0) - -// Specify the physical address on the rsbus -#define RSADDR (1) - -// Machine Type -// TYPE 0 is a dummy used for debug -// Change it in real implementation -#define MACTYPE (0x00) - -// ====== End RSBUS configuration ====== - -//define delay func -#define delay_ms(ms) __delay_cycles(16000*(ms)) - -#endif /* PRECOMP_H_ */ +/* + * precomp.h + * + * Created on: 2014-4-26 + * Author: Tuowen + */ + +#ifndef PRECOMP_H_ +#define PRECOMP_H_ + +#include + +// ====== RSBUS configuration ====== + +// Data Enable pin configuration +// P1.0 -> red led +#define RSDIR (P1DIR) +#define RSOUT (P1OUT) +#define RSPIN (BIT0) + +// This is the highest level +#define RSSYSBIT (SYS_BIT0) +#define TEST (SYS_BIT1) + +// Specify the physical address on the rsbus +#define RSADDR (1) + +// Machine Type +// TYPE 0 is a dummy used for debug +// Change it in real implementation +#define MACTYPE (0x00) + +// ====== End RSBUS configuration ====== + +//define delay func +#define delay_ms(ms) __delay_cycles(16000*(ms)) + +#endif /* PRECOMP_H_ */ diff --git a/rs422lib/rsbus.c b/rs422lib/rsbus.c index c69a664..e0a18ec 100644 --- a/rs422lib/rsbus.c +++ b/rs422lib/rsbus.c @@ -1,182 +1,182 @@ -/* - * rsbus.c - * - * Created on: 2014-4-26 - * Author: Tuowen - */ -#include "rsbus.h" -#include "sysctl.h" - -#define SYSRET (0xF0) -#define INSREP (0x0F) - -// Maximum size of receive buffer -#define RSMAX (20) - -#define CODE_LEN (6) - -unsigned char rs_rxbuf[RSMAX]; -unsigned char len; -unsigned char pch; -rshdlr rxhdlr; -enum rs_stat{REST,ST,ADDR,READ,DISCARD,ED,DED}; -enum rs_stat rs_st=REST; - -unsigned char rs_tx[CODE_LEN+RS_MAX]={STBIT1,0,RSADDR,MACTYPE}; -volatile unsigned char tx_len; -volatile unsigned char tx_pos=255; - -volatile unsigned char mac_stat[4]={0,0,0,0}; - -// UART transmit routine -#pragma vector=USCIAB0TX_VECTOR -__interrupt void USCI0TX_ISR(void) -{ - if (tx_pos == tx_len) // TX over? - { - UC0IE &= ~UCA0TXIE; // Disable USCI_A0 TX interrupt - RSOUT &= ~(RSPIN); - tx_pos = 255; - } - else - UCA0TXBUF = rs_tx[tx_pos++]; // TX next character -} - -// Inline send for ISR -#pragma FUNC_ALWAYS_INLINE(rsbus_w_irq) -static __inline void rsbus_w_irq(unsigned char* buf,unsigned int len) -{ - unsigned int i; - if (tx_pos < tx_len) // This shouldn't happen - return; // Race condition - RSOUT |= RSPIN; - tx_len=len+7; - unsigned int parity=MACTYPE^RSADDR; - rs_tx[1]=0; // Useless addr spec - for (i=0;i=RSMAX) - rs_st=REST; - break; - case DISCARD: - if (dat==EDBIT0) - rs_st=DED; - break; - case DED: - if (dat==EDBIT1) - rs_st=REST; - else - rs_st=DISCARD; - break; - case ED: - if (dat==EDBIT1) - { - rs_st=REST; - --len; - pch^=EDBIT0; - if (pch==0) // Parity check passed - { - if (len<2) - rsbus_w_irq((unsigned char*)mac_stat,4); // RETURN CURRENT STATUS - else - SYSCALL_IRQ(RSSYSBIT); // SYSCTL call happened here!!! - } - else // Parity check failed - { - dat = SYSRET ^ INSREP; // RETURN REP - rsbus_w_irq(&dat,1); - } - } - else - { - rs_rxbuf[len++]=dat; - pch^=dat; - rs_st=READ; - if (len>=RSMAX) - rs_st=REST; - } - break; - } -} - -void rsbus_w(int addr,unsigned char* buf,unsigned int len) -{ - while (tx_pos < tx_len) // This shouldn't happen - __delay_cycles(100); // Race condition -> wait - unsigned int i; - if (len>RS_MAX) - return; - RSOUT |= RSPIN; - tx_len=len+7; - unsigned int parity=addr^MACTYPE^RSADDR; - rs_tx[1]=addr; // Useless addr spec - for (i=0;i Low as DEFAULT - /******************* SYSCTL INIT *************************/ - rxhdlr=hdlr; - sysctl_reghdlr(RSSYSBIT,&rsbus_syscall); -} +/* + * rsbus.c + * + * Created on: 2014-4-26 + * Author: Tuowen + */ +#include "rsbus.h" +#include "sysctl.h" + +#define SYSRET (0xF0) +#define INSREP (0x0F) + +// Maximum size of receive buffer +#define RSMAX (20) + +#define CODE_LEN (6) + +unsigned char rs_rxbuf[RSMAX]; +unsigned char len; +unsigned char pch; +rshdlr rxhdlr; +enum rs_stat{REST,ST,ADDR,READ,DISCARD,ED,DED}; +enum rs_stat rs_st=REST; + +unsigned char rs_tx[CODE_LEN+RS_MAX]={STBIT1,0,RSADDR,MACTYPE}; +volatile unsigned char tx_len; +volatile unsigned char tx_pos=255; + +volatile unsigned char mac_stat[4]={0,0,0,0}; + +// UART transmit routine +#pragma vector=USCIAB0TX_VECTOR +__interrupt void USCI0TX_ISR(void) +{ + if (tx_pos == tx_len) // TX over? + { + UC0IE &= ~UCA0TXIE; // Disable USCI_A0 TX interrupt + RSOUT &= ~(RSPIN); + tx_pos = 255; + } + else + UCA0TXBUF = rs_tx[tx_pos++]; // TX next character +} + +// Inline send for ISR +#pragma FUNC_ALWAYS_INLINE(rsbus_w_irq) +static __inline void rsbus_w_irq(unsigned char* buf,unsigned int len) +{ + unsigned int i; + if (tx_pos < tx_len) // This shouldn't happen + return; // Race condition + RSOUT |= RSPIN; + tx_len=len+7; + unsigned int parity=MACTYPE^RSADDR; + rs_tx[1]=0; // Useless addr spec + for (i=0;i=RSMAX) + rs_st=REST; + break; + case DISCARD: + if (dat==EDBIT0) + rs_st=DED; + break; + case DED: + if (dat==EDBIT1) + rs_st=REST; + else + rs_st=DISCARD; + break; + case ED: + if (dat==EDBIT1) + { + rs_st=REST; + --len; + pch^=EDBIT0; + if (pch==0) // Parity check passed + { + if (len<2) + rsbus_w_irq((unsigned char*)mac_stat,4); // RETURN CURRENT STATUS + else + SYSCALL_IRQ(RSSYSBIT); // SYSCTL call happened here!!! + } + else // Parity check failed + { + dat = SYSRET ^ INSREP; // RETURN REP + rsbus_w_irq(&dat,1); + } + } + else + { + rs_rxbuf[len++]=dat; + pch^=dat; + rs_st=READ; + if (len>=RSMAX) + rs_st=REST; + } + break; + } +} + +void rsbus_w(int addr,unsigned char* buf,unsigned int len) +{ + while (tx_pos < tx_len) // This shouldn't happen + __delay_cycles(100); // Race condition -> wait + unsigned int i; + if (len>RS_MAX) + return; + RSOUT |= RSPIN; + tx_len=len+7; + unsigned int parity=addr^MACTYPE^RSADDR; + rs_tx[1]=addr; // Useless addr spec + for (i=0;i Low as DEFAULT + /******************* SYSCTL INIT *************************/ + rxhdlr=hdlr; + sysctl_reghdlr(RSSYSBIT,&rsbus_syscall); +} diff --git a/rs422lib/rsbus.h b/rs422lib/rsbus.h index 2e29b9b..1297d72 100644 --- a/rs422lib/rsbus.h +++ b/rs422lib/rsbus.h @@ -1,63 +1,67 @@ -/* - * rsbus.h - * - * Created on: 2014-4-26 - * Author: Tuowen - */ - -// DE RSOUT.RSPIN HIGH ENABLE -// RE LOW ENABLE -> ALWAYS ENABLE -// RECEIVE QUERY -> Conditional FNC call -// Process -> Output (Done in main program) -// SMCLK set to 4MHZ - - -#ifndef RSBUS_H_ -#define RSBUS_H_ - -#include -#include"precomp.h" - -// MAXIMUM length to be send -#define RS_MAX (14) - -#define ST_BUSY (0x04) -#define ST_RUN (0x02) -#define ST_RES (0x01) -#define ST_REST (0x00) - -// Switch the machine to a new state specified above -// This will shown on the network -> must call -#define SWITCH_STATE(STATE) (mac_stat[0]=STATE) - -// Changing the state value (unsigned char) -> -// Available indices 0,1,2 -#define STATE(X) (mac_stat[X+1]) - -// Start and Stop bits definition -// Every message sent that does not agree with it will be ignored -// Please avoid this pattern in STATE(X) -#define STBIT0 (0x5B) -#define STBIT1 (0xAD) -#define EDBIT0 (0xA4) -#define EDBIT1 (0x52) - -// Receieve handler -> -// Received message and it's length -typedef void (*rshdlr)(unsigned char* msg,unsigned int len); - -// RSBUS init function -// Setting up UART, DE pin, receieve handler -void rsbus_init(rshdlr); - -// Send something to the rs422 bus -// Length must not exceeds RS_MAX -void rsbus_w(int,unsigned char*,unsigned int); - -// Machine status -> change it to change the auto respond status -// 0 is reserved for machine state specification -// 1-3 used for mac_type specific state -// recommend using SWITCH_STATE & STATE -extern volatile unsigned char mac_stat[4]; - -#endif /* RSBUS_H_ */ +/* + * rsbus.h + * + * Created on: 2014-4-26 + * Author: Tuowen + */ + +// DE RSOUT.RSPIN HIGH ENABLE +// RE LOW ENABLE -> ALWAYS ENABLE +// RECEIVE QUERY -> Conditional FNC call +// Process -> Output (Done in main program) +// SMCLK set to 4MHZ + + +#ifndef RSBUS_H_ +#define RSBUS_H_ + +#include +#include"precomp.h" + +// MAXIMUM length to be send +#define RS_MAX (14) + +#define ST_BUSY (0x04) +#define ST_RUN (0x02) +#define ST_RES (0x01) +#define ST_REST (0x00) + +// Switch the machine to a new state specified above +// This will shown on the network -> must call +#define SWITCH_STATE(STATE) (mac_stat[0]=STATE) +#define MSTATE (mac_stat[0]) + +// Changing the state value (unsigned char) -> +// Available indices 0,1,2 +#define STATE(X) (mac_stat[X+1]) + +// Return current mac state +#define RETSTATE (rsbus_w(0,(unsigned char*)mac_stat,4)) + +// Start and Stop bits definition +// Every message sent that does not agree with it will be ignored +// Please avoid this pattern in STATE(X) +#define STBIT0 (0x5B) +#define STBIT1 (0xAD) +#define EDBIT0 (0xA4) +#define EDBIT1 (0x52) + +// Receieve handler -> +// Received message and it's length +typedef void (*rshdlr)(unsigned char* msg,unsigned int len); + +// RSBUS init function +// Setting up UART, DE pin, receieve handler +void rsbus_init(rshdlr); + +// Send something to the rs422 bus +// Length must not exceeds RS_MAX +void rsbus_w(int,unsigned char*,unsigned int); + +// Machine status -> change it to change the auto respond status +// 0 is reserved for machine state specification +// 1-3 used for mac_type specific state +// recommend using SWITCH_STATE & STATE +extern volatile unsigned char mac_stat[4]; + +#endif /* RSBUS_H_ */ diff --git a/rs422lib/sysctl.c b/rs422lib/sysctl.c index cafcb62..ea05587 100644 --- a/rs422lib/sysctl.c +++ b/rs422lib/sysctl.c @@ -19,8 +19,11 @@ void sysctl_void() } void sysroutine() +// << Drawback: interrupt may happen between else and CPUOFF +// Critical section -> unlikely to have a race condition { - if (syscall>0) + if (!syscall) + _BIS_SR(CPUOFF); switch ((syscall & (-syscall))) // This is used to get the lowest bit { case SYS_BIT7: @@ -56,8 +59,7 @@ void sysroutine() sysarr[0](); break; } - else - _BIS_SR(CPUOFF); + } inline int sys_b2i(int bit) diff --git a/rs422lib/sysctl.h b/rs422lib/sysctl.h index b8301fa..83f82d9 100644 --- a/rs422lib/sysctl.h +++ b/rs422lib/sysctl.h @@ -1,57 +1,61 @@ -/* - * sysctl.h - * - * Created on: 2014-4-26 - * Author: Tuowen - */ - -// Support 8 different syscalls -// Possible improvement -// CPUOFF all the time, wakeup after syscall invoked. - -#ifndef SYSCTL_H_ -#define SYSCTL_H_ - -// Sysctl priority bit -// Lowest first -#define SYS_BIT7 (0x80) -#define SYS_BIT6 (0x40) -#define SYS_BIT5 (0x20) -#define SYS_BIT4 (0x10) -#define SYS_BIT3 (0x08) -#define SYS_BIT2 (0x04) -#define SYS_BIT1 (0x02) -#define SYS_BIT0 (0x01) - -// SYSCALL invocation routine -// Used this in IRQ, also wakes up the cpu -#define SYSCALL_IRQ(X) (syscall|=X,_BIC_SR_IRQ(CPUOFF)) -// Use this in anywhere other than IRQ -// Continuous invocation ? -#define SYSCALL(X) (syscall|=X) - -// Call handler type -// Does't have any input -// Preserve the state in other global variables -// Usage example -> rsbus_syscall() -typedef void (*syshdlr)(); - -// Register call handler -// Always replace old value -void sysctl_reghdlr(unsigned int bit,syshdlr rot); - -// Remove old call handler -// Replace with something useless -void sysctl_rmhdlr(unsigned int bit); - -// Insert it into mainloop -// enabling automatic procedure invocation -void sysroutine(); - -// Setting up the proc base -// Call before usage -void sysctl_init(); - -extern volatile unsigned char syscall; - -#endif /* SYSCTL_H_ */ +/* + * sysctl.h + * + * Created on: 2014-4-26 + * Author: Tuowen + */ + +// Support 8 different syscalls +// Possible improvement +// CPUOFF all the time, wakeup after syscall invoked. + +#ifndef SYSCTL_H_ +#define SYSCTL_H_ + +// Sysctl priority bit +// Lowest first +#define SYS_BIT7 (0x80) +#define SYS_BIT6 (0x40) +#define SYS_BIT5 (0x20) +#define SYS_BIT4 (0x10) +#define SYS_BIT3 (0x08) +#define SYS_BIT2 (0x04) +#define SYS_BIT1 (0x02) +#define SYS_BIT0 (0x01) + +// SYSCALL invocation routine +// Used this in IRQ, also wakes up the cpu +#define SYSCALL_IRQ(X) (syscall|=X,_BIC_SR_IRQ(CPUOFF)) +// Use this in anywhere other than IRQ +// Continuous invocation ? +#define SYSCALL(X) (syscall|=X) + +// Only one stop function +// For IRQ & Main +#define SYSSTOP(X) (syscall&=~X) + +// Call handler type +// Does't have any input +// Preserve the state in other global variables +// Usage example -> rsbus_syscall() +typedef void (*syshdlr)(); + +// Register call handler +// Always replace old value +void sysctl_reghdlr(unsigned int bit,syshdlr rot); + +// Remove old call handler +// Replace with something useless +void sysctl_rmhdlr(unsigned int bit); + +// Insert it into mainloop +// enabling automatic procedure invocation +void sysroutine(); + +// Setting up the proc base +// Call before usage +void sysctl_init(); + +extern volatile unsigned char syscall; + +#endif /* SYSCTL_H_ */ -- cgit v1.2.3-70-g09d2