This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

MSP430FR UART

Other Parts Discussed in Thread: MSP430FR5738, MSP430FR6989, MSP430F5438A

I'm now frustrated trying to use the MSP430FR5738 uart.  From what I've read, it's just not possible to determine if the transmit buffer register is ready for another character.

(I've programmed UART code in more than a dozen different processors, so I'm quite familiar with this).

I'm using two 64 byte FIFOs for XMIT arnd RCV. What I need to do is insert characters at the front of the line occasionally, for example XOFF if  the receive FIFO is getting too full or BEL if it is full.   Everything I've tried failed, sometimes even crashing if I fuss with the IFG bit.

Alas, I see no possible solution.  I guess I'll have to monitor the GPIO for xmit data, and if it's in stop bit state for a while, at least I'm sure the transmitter is idle.

This wastes a character time, though.  Too bad the busy bit monitors the receiver also, as the receiver is likely to be busy all the time.

Are there any tricks you know?

Thanks.

  • Hi Hoyt,

    From the MSP430FR57xx Family Users Guide 

    18.3.15.1 eUSCI_A Transmit Interrupt Operation
    The UCTXIFG interrupt flag is set by the transmitter to indicate that UCAxTXBUF is ready to accept another
    character.
    Even if you are not using interrupts you should be able to poll the UCTXIFG flag to determine when the transmit buffer is ready for another character.
    HTH,
    Barry
  • Thanks for your prompt reply.  I am using interrupts, so I do get an interrupt due to UCTXIFG, but that apparently clears it, so it's zero when read inside the interrupt routine, even before reading the vector register.  Even if the interrupt is from the receiever side, TXIFG reads zero whether or not the tx buffer is ready so the only way to get it to set is to put another character into the tx buffer, but maybe that's not ready yet -- problem. 

  • Since your xmit FIFO is implemented in software, it is quite easy to "jump the queue".

    Whenever the rcv FIFO ISR decides that you need to xmit a certain character urgently, it should set a flag for the xmit FIFO ISR to handle it. Your xmit FIFO ISR normally picks up the next character from the FIFO to xmit; but when it sees the flag, it should xmit the special character instead. This essentially let that special character jumps ahead of everything in that xmit FIFO. 

  • That would work unless the transmit fifo was empty. There would be no XMIT interrupt to send the special character and no way to determine if the transmitter was available to kick off a new interrupt stream.

  • Hoyt A. Stearns Jr. said:
    I am using interrupts, so I do get an interrupt due to UCTXIFG, but that apparently clears it, so it's zero when read inside the interrupt routine, even before reading the vector register.  Even if the interrupt is from the receiever side, TXIFG reads zero whether or not the tx buffer is ready so the only way to get it to set is to put another character into the tx buffer, but maybe that's not ready yet -- problem. 

    Well, if you use UCAxIV to discern interrupt source then I do not see any problem. Because logic is: if you get TX interrupt, it signals that TX register is empty. Because only TX IRQ routine is responsible to mark software FIFO as empty, it will be marked as emtpy  when your TX register is empty. So it means that outside IRQ routine in case of empty TX fifo you know that TX register is also empty, you can write into TX register to start TX IRQ's running.

  • This sure gets confusing.  The previous TX interrupt happens, but at that time, there's nothing more to send so that interrupt chain stops,

    meanwhile a receive interrupt happens and it's determined I need to send something, but there's no TX pending. I send the character from inside the ISR, but no subsequent TX ready interrupt happens again.  I think there's something wrong with the behavior. Loading the TX buffer from an ISR doesn't  trigger a new interrupt chain if the interrupt wasn't from the TX interrupt  to begin with -- something strange going on.

  • Hoyt A. Stearns Jr. said:
    meanwhile a receive interrupt happens

    RX int shall not be allowed during TX interrupt. Such way you are safe to check software fifo state from RX interrupt and initiate TX process by TX register write.

    Hoyt A. Stearns Jr. said:
    something strange going on.

    Where? In your head? :D [kidding]

  • After trying lots of different approaches, I'm concluding that the MSP430FR5738/9 UART (shared RX and TX interrupt )  is not usable for robust serial communication without heroic measures and polling, or even if that's possible.  It'll send and receive data OK for a while, then lose the  TX interrupt enable.

    There's no other code running other than the UART code to echo in to out right now.

    I've had to add a few NOPs after ISR entry to prevent crashing ( cache issue? ),

    If you have code that's known to work well on the FR series, please share it with me ( assembly language preferred ).

    I've seen these issues discussed on other forums briefly, but no good solutions are apparent.

    Thanks

  • Hoyt A. Stearns Jr. said:
    If you have code that's known to work well on the FR series, please share it with me ( assembly language preferred ).

    Maybe share yours so we can see that it's hardware problem as you say.

  • Hoyt A. Stearns Jr. said:

    That would work unless the transmit fifo was empty. There would be no XMIT interrupt to send the special character and no way to determine if the transmitter was available to kick off a new interrupt stream.

    For a lot of UARTs, when the transmit fifo is empty, there would be no XMIT interrupt to send the next character -- special or not special. Thus this "problem" is not in "how to jump the queue". It is in "how to handle a XMIT fifo".

    There are lots of ways to kick off a XMIT interrupt stream. The UART in FR57xx actually is a lot nicer than most others in this respect. I do not have any FR57xx at hand. I may be able to modify your assembly code fragments for (a) setting up the UART, (b) putting bytes into XMIT fifo, (c) getting bytes out of RCV fito, and (d) ISR for that UART.

    Can you show me those fragments?

  • Here is my code attached, not working well though: It loses interrupts and somehow adds extra characters to the xmit fifo randomly.

    I appreciate your attention. 

    6232.UARTcode.txt
    ;			--Hoyt A. Stearns Jr.
    ;			--Wed 03/17/2013 
    
    
    RAMbegin	equ		1c00h
    RAMsize		equ		1024
    
    
    ;
    FIFOSIZE		equ	64		; Must be power of 2
    RXOFFTRIGGER	equ	20		; Send XOFF when Receive fifo has < this room
    RXONPT			equ	48		; Send XON when Receive fifo has > this room
    ;
    ;
    XOFF	equ	13h
    XON		equ	11h
    BEL		equ	7
    CtlC	equ	3
    CtlO	equ	15
    
    BIT0	equ	1<<0
    BIT1	equ	1<<1
    BIT2	equ	1<<2
    BIT3	equ	1<<3
    BIT4	equ	1<<4
    BIT5	equ	1<<5
    BIT6	equ	1<<6
    BIT7	equ	1<<7
    BIT8	equ	1<<8
    BIT9	equ	1<<9
    BIT10	equ	1<<10
    BIT11	equ	1<<11
    
    
    /***************Serial communication variables**********/
    
    XOFFsent			equ		BIT0
    SendXOFF			equ		BIT1
    XOFFreceived		equ		BIT2
    CtlOreceived		equ		BIT3
    UARTbreak			equ		BIT4
    TxBusy				equ		BIT5
    RfifoFull			equ		BIT6		//send BEL
    RtsCts				equ		BIT7
    
    ;
    ;
    ;
    ;Mini state machine description for XOFF transmitting process:
    ;			
    ;	SendxOFF		XOFFsent
    ;		0				0	; normal processing
    ;		1				0	; XOFF pending to be sent
    ;		1				1	; XOFF sent, must send an XON when Rfifo room appears.
    ;		0				1	; XON pending to be sent when xmtr ready
    ;
    // RtsCts RfifoFull TxBusy UARTbreak CtlOreceived XOFFreceived SendXOFF XOFFsent
    
    UARTflags:			ds	1
    
    RxInptr				ds	1
    RxOutptr			ds	1
    RxCount				ds	1
    ;
    					even
    RxFifo				ds	FIFOSIZE*2
    ;
    TxInptr				ds	1
    TxOutptr			ds	1
    TxCount				ds	1
    ;
    TxFifo				ds	FIFOSIZE
    ;
    ;
    
    /***************************************************/
    
    reset:
    main:
    		mov.w   #5a80h, &15ch		//Stop watchdog
    
    ; DCOCLK: Internal digitally controlled oscillator (DCO). 
    ; Startup clock system in max. DCO setting 24 MHz 
    
    	    mov.b   #0a5h, &161h			//unlock
       		mov.b   #86h, &162h				// 24MHz
    		mov		#333h, &164h			//set all to dcO 
       		mov		#0, &166h
       		mov.b	#1, &161h
    
    
    
    ;	INT( [ (N/16) - INT(N/16) ] � 16 ); 
    ;
    ; Configure UART pins P2.0 (UCA0TXD) & P2.1 (UCA0RXD)
    ;
    		bis.b   #0x03,	&0x20d  ; P2SEL1 |= BIT0 + BIT1; 
    		and.b   #0xfc,	&0x20b	; P2SEL0 &= ~(BIT0 + BIT1); 
    
    
    		mov		#0000000010110001b,&5c0h
    		mov		#0x0003, &0x5c2	//UCA0CTLW1 200ns deglitch (default)
    		mov		#0x009C, &0x5c6	//UCA0BRW	for 9600 baud, 24MHz clock
    		mov		#0x2241, &0x5c8	//UCA0MCTLW	"
    		bic.b   #0x01,	 &0x5c0	//UCA0CTLW0 &= ~UCSWRST  // release from reset
    	
    
    //Clear RAM
    
    RamClr:	mov	#RAMsize,r11
    ;
    //known pattern for testing uart now
    
    RamClrLoop;
    		sub	#2,r11
    		mov	#4d4eh,RAMbegin(r11)
    		jnz	RamClrLoop
    ;
    	mov.b #0,RxInptr
    	mov.b #0,RxOutptr
    	mov.b #0,RxCount
    	mov.b #0,TxInptr
    	mov.b #0,TxOutptr
    	mov.b #0,TxCount
    	mov.b #0,UARTflags
    
    /*****************Setup stacks and user variables**************/
    
    		mov	#rstack, sp
    
    		bis		#1,&5dah			//Enable UART receive interrupt
    		eint
    
    #define UART_ECHO_TEST
    #if defined UART_ECHO_TEST
    
    		mov		#XON,tos
    		call	#TputIn
    ;
    tloop:	call	#RpullOut			//Wait 'til something in there
    		cmp		#-1,tos
    		jeq		tloop
    
    		
    tloop2:	call	#TputIn
    		jne		tloop
    		jmp		tloop2				//Wait 'til XMIT space available
    #endif
    
    
    /***********Serial transmit*************/
    ;
    ; User side transmit, jeq after return signifies no room
    ; Character input in r7, output is zero flag, set if no more room
    ; Must clear Rx interrupt enable also, 'cuz it fusses with TxFifo
    ;
    TputIn: bic		#3,&5dah			//Clear TX interrupt enable
    		nop							//very necessary
    		nop
    		nop
    ;
    		cmp.b	#FIFOSIZE,&TxCount
    		jeq		tpx					//No room left
    
    		bit.b	#CtlOreceived,&UARTflags
    		jne		tpx
    ;
    ;There is room
    ;
    tp1:	mov.b	&TxInptr, r14
    		mov.b	tos,TxFifo(r14)
    ;
    		inc		r14
    		and		#FIFOSIZE-1,r14
    		mov.b	r14, &TxInptr
    ;
    		inc.b	&TxCount
    ;
    		bit.b	#XOFFreceived,&UARTflags
    		jne		tpx2
    ;
    		bis		#3,&5dah			//re-enable Tx and Rx interrupts
    		bic		#2,sr				//Clear zero flag
    ;
    tpx:	bis		#2,&5dah			//re-enable Tx interrupt
    tpx2:	ret
    ;
    /************************Serial port Function `RpullOut'***********************/ 
    ;
    ; User side getchar.  -1 returned means no char available (NULL is a valid character)
    ;
    ; Output is in r7 (tos), char in high addressed (LSB) byte
    ;
    RpullOut:
    		bic		#1,&5dah				//Clear UART Rx interrupt 
    		nop
    		nop
    		nop
    ;
    		tst.b	&RxCount
    		jeq		L6
    ;
    		dec.b	&RxCount
    ;
    		mov.b	&RxOutptr, r14
    		rla		r14
    		mov		RxFifo(r14),tos
    ;
    		rra		r14						//carry is 0
    		inc		r14
    		and		#FIFOSIZE-1, r14
    		mov.b	r14, &RxOutptr
    ;
    ;	If > RXONPT remaining spaces, send XON on tx interrupt
    ;
    		cmp.b	#FIFOSIZE-RXONPT,&RxCount
    		jne		L5
    ;
    		bic.b	#SendXOFF, &UARTflags	//Clear SendXOFF prepare to send XON
    		bis		#2,&5dah				//Enable  Tx interrupt
    		jmp		L5
    ;
    L6:		mov		#-1,tos
    L5:		bis		#1,&5dah				//Enable UART receive interrupt
    		ret
    
    ;
    /***************************Serial Communiction interrupt**************/
    ;
    uart_isr:
    		pushm.w	#4,r15
    		nop
    		nop
    		nop
    		nop
    ;
    ;all IFG flags were zero when read here, making them unusable in an ISR
    ;
    		mov		&5deh, r15			//Interrupt vector register
    		cmp		#2, r15				//Rx vector
    		jeq		ReceiveISR
    ;
    		cmp		#4, r15				//Tx vector
    		jeq		XmitISR
    ;
    L27:	popm.w	#4,r15
    		reti
    ;
    		//Receiver
    ;
    ReceiveISR:
    		mov		&5cah, r12				//UCA0 status
    		mov		&5cch, r13				//Recv buffer
    		bis		&5cah, r12				//UCA0 status OR in overrun
    		and		#7ch,  r12				//clear bits we're not interested in
    		bit.b	#8,r12					//check break
    		jeq		NoBreak
    ;
    		bis.b	#UARTbreak,&UARTflags	//Set break flag
    		mov.b	#CtlC,r13				//Put CTRL_C into receive character
    NoBreak:
    		tst.b	r12
    		swpb	r12
    		bis.b	r13,r12					//Merge errors to received character
    		jne		SkipTests				//from tst.b above, don't test special
    ;
    ;		Check special cases on error free characters
    ;
    		cmp.b	#XOFF,r13				//XOFF	
    		jeq		GotXoff
    ;
    		cmp.b	#XON,r13				//XON
    		jeq		GotXon
    ;
    		cmp.b	#CtlC,r13				//CTRL_C
    		jeq		GotCtlC
    ;
    		cmp.b	#CtlO,r13				//CTRL_O, send XMIT Chars to /dev/null
    		jeq		GotCtlO
    ;
    		//Check state of receive fifo
    ;
    SkipTests:
    		mov.b	&RxCount, r14	
    		cmp.b	#FIFOSIZE,r14 
    		jhs		DoBEL					//No room
    ;
    ;	If remaining RX space < RXOFFTRIGGER, send XOFF
    ;
    		cmp		#FIFOSIZE-RXOFFTRIGGER, r14
    		jhs		doXOFF
    ;
    ;	Insert char and err into RxFifo
    ;
    		mov.b	&RxInptr, r15
    		rla		r15
    		mov		r12, RxFifo(r15)		//store the character and error bits
    ;
    		rra		r15
    		add.b	#1, r15
    		and		#FIFOSIZE-1, r15
    		mov.b	r15, &RxInptr
    ;
    		add.b	#1, &RxCount
    		jmp		L27
    ;
    ;
    ;
    GotXoff:bis.b	#XOFFreceived,&UARTflags	//XOFF received bit
    		bic		#2,&5dah					//Disable Tx interrupt
    		jmp		L27
    ;
    GotXon:	bic.b	#XOFFreceived,&UARTflags	//clear XOFF received bit
    		jmp		L27
    ;
    GotCtlC:bis.b	#UARTbreak,&UARTflags		//Set UARTbreak
    		jmp		L27
    ;
    GotCtlO:bit.b	#CtlOreceived,&UARTflags	//CtlO toggles
    		jeq		DoCtlO
    ;
    		bic.b	#CtlOreceived,&UARTflags
    		jmp		L27
    ;
    DoCtlO:	bis.b	#CtlOreceived,&UARTflags	//Toggle CTRL_O
    		mov		#0,&TxInptr					//does TxOutptr also, .w
    		mov.b	#0,&TxCount					//Empty the XMIT fifo
    		bic		#2,&5dah					//Disable Tx interrupt
    		jmp		L27
    ;
    ;Here's a big problem: we can't tell if the xmitter is free to load :-(
    ;but if we don't load it and it's idle, tx interrupts stop.
    ;Inside the ISR, the IFG bits seem to always read 0, even before reading the vector reg.
    ;So the XMTR UCTXCPIFG bit is useless here.
    ;
    DoBEL:	tst.b	&TxCount
    		jne		BelLater
    ;
    		mov		#BEL,&5ceh			
    		bis.b	#2,&5dah					//Enable Tx interrupt
    		jmp		L27
    
    BelLater:
    		bis.b	#RfifoFull,&UARTflags		//send BEL when xmtr available
    		jmp		L27
    ;
    ;	If remaining RX space < RXOFFTRIGGER, send XOFF
    ;	(same big problem here)
    ;
    doXOFF:	tst.b	&TxCount
    		jne		XoffLater
    ;
    		mov		#XOFF,&5ceh			
    		bis.b	#2,&5dah					//Enable Tx interrupt
    		jmp		L27
    ;
    XoffLater:
    		bis.b	#SendXOFF, &UARTflags		//Set SendXOFF if not much more room
    		jmp		L27
    
    
    
    //Transmitter
    ;
    ;Mini state machine description for XOFF transmitting process:
    ;			
    ;	SendxOFF		XOFFsent
    ;		0				0	; normal processing
    ;		1				0	; XOFF pending to be sent
    ;		1				1	; XOFF sent, must send an XON when Rfifo room appears.
    ;		0				1	; XON pending to be sent when xmtr ready
    ;
    //UARTflags:
    // RtsCts RfifoFull TxBusy UARTbreak CtlOreceived XOFFreceived SendXOFF XOFFsent
    ;
    //Transmitter
    
    XmitISR:bic.b	#TxBusy, &UARTflags			//Clear TxBusy (not currently used)
    ;
    		mov.b	&UARTflags, r15
    		bit.b	#RfifoFull, r15
    		jne		SendBEL
    ;
    		bit.b	XOFFreceived, r15
    		jne		StopSending
    ;
    		and		#SendXOFF|XOFFsent, r15
    		cmp		#SendXOFF, r15
    		jeq		DoXOFF						//XOFF pending
    ;
    		cmp		#XOFFsent, r15				//XON pending when tx ready
    		jeq		DoXON
    ;
    TestXct:tst.b	&TxCount
    		jne		DoSend
    ;
    StopSending:
    		bic		#2,&5dah					//disable TX interrupts
    		jmp		L27
    ;
    ;		//Send character from TxFIFO
    ;
    DoSend:	mov.b	&TxOutptr, r15
    		mov.b	TxFifo(r15),r14				//Collect byte as word
    		bis.b	#TxBusy,&UARTflags
    		mov.w	r14,&5ceh					//Send it out
    ;
    		inc.b	r15
    		and.b	#FIFOSIZE-1, r15
    		mov.b	r15, &TxOutptr
    ;
    		dec.b	&TxCount
    		jne		L27
    ;
    		bic		#2,&5dah					//disable TX interrupts, Tx fifo was empty
    		jmp		L27
    ;
    ;
    SendBEL:
    		bic.b	#RfifoFull,&UARTflags
    		bis.b	#TxBusy,&UARTflags
    ;
    		mov		#BEL, &5ceh
    		jmp		TestXct
    ;
    ;
    DoXOFF:	bis.b	#TxBusy,&UARTflags
    		mov		#XOFF, &5ceh				//XOFF -> Tx buffer
    		bis.b	#XOFFsent, &UARTflags		//Set XOFFsent
    		jmp		TestXct
    ;
    DoXON:	bis.b	#TxBusy,&UARTflags
    		mov		#XON, &5ceh					//XON -> Tx buffer
    		bic.b	#XOFFsent, &UARTflags		//Clear XOFFsent
    		jmp		TestXct
    ;
    		nop
    ;
    /*********************************************************************/
    ; Interrupt Vectors
    
            rseg    INTVEC
    
    intvecs: dc16 nullirq    ; $FF80  -  reserved 
    			org 0fff0h
             dc16 uart_isr	 	;	 $FFF0  -  eUSCI_A0 rx,tx 
    			org 0fffeh
             dc16 reset			;	 $FFFE  -  reset 
            end
    
    

  • 7607.UARTcode.txt
    ;			--Hoyt A. Stearns Jr.
    ;			--Wed 03/17/2013 
    
    
    RAMbegin	equ		1c00h
    RAMsize		equ		1024
    
    
    ;
    FIFOSIZE		equ	64		; Must be power of 2
    RXOFFTRIGGER	equ	20		; Send XOFF when Receive fifo has < this room
    RXONPT			equ	48		; Send XON when Receive fifo has > this room
    ;
    ;
    XOFF	equ	13h
    XON		equ	11h
    BEL		equ	7
    CtlC	equ	3
    CtlO	equ	15
    
    BIT0	equ	1<<0
    BIT1	equ	1<<1
    BIT2	equ	1<<2
    BIT3	equ	1<<3
    BIT4	equ	1<<4
    BIT5	equ	1<<5
    BIT6	equ	1<<6
    BIT7	equ	1<<7
    BIT8	equ	1<<8
    BIT9	equ	1<<9
    BIT10	equ	1<<10
    BIT11	equ	1<<11
    
    
    /***************Serial communication variables**********/
    
    XOFFsent			equ		BIT0
    SendXOFF			equ		BIT1
    XOFFreceived		equ		BIT2
    CtlOreceived		equ		BIT3
    UARTbreak			equ		BIT4
    TxBusy				equ		BIT5
    RfifoFull			equ		BIT6		//send BEL
    RtsCts				equ		BIT7
    
    ;
    ;
    ;
    ;Mini state machine description for XOFF transmitting process:
    ;			
    ;	SendxOFF		XOFFsent
    ;		0				0	; normal processing
    ;		1				0	; XOFF pending to be sent
    ;		1				1	; XOFF sent, must send an XON when Rfifo room appears.
    ;		0				1	; XON pending to be sent when xmtr ready
    ;
    // RtsCts RfifoFull TxBusy UARTbreak CtlOreceived XOFFreceived SendXOFF XOFFsent
    
    UARTflags:			ds	1
    
    RxInptr				ds	1
    RxOutptr			ds	1
    RxCount				ds	1
    ;
    					even
    RxFifo				ds	FIFOSIZE*2
    ;
    TxInptr				ds	1
    TxOutptr			ds	1
    TxCount				ds	1
    ;
    TxFifo				ds	FIFOSIZE
    ;
    ;
    
    /***************************************************/
    
    reset:
    main:
    		mov.w   #5a80h, &15ch		//Stop watchdog
    
    ; DCOCLK: Internal digitally controlled oscillator (DCO). 
    ; Startup clock system in max. DCO setting 24 MHz 
    
    	    mov.b   #0a5h, &161h			//unlock
       		mov.b   #86h, &162h				// 24MHz
    		mov		#333h, &164h			//set all to dcO 
       		mov		#0, &166h
       		mov.b	#1, &161h
    
    
    
    ;	INT( [ (N/16) - INT(N/16) ] � 16 ); 
    ;
    ; Configure UART pins P2.0 (UCA0TXD) & P2.1 (UCA0RXD)
    ;
    		bis.b   #0x03,	&0x20d  ; P2SEL1 |= BIT0 + BIT1; 
    		and.b   #0xfc,	&0x20b	; P2SEL0 &= ~(BIT0 + BIT1); 
    
    
    		mov		#0000000010110001b,&5c0h
    		mov		#0x0003, &0x5c2	//UCA0CTLW1 200ns deglitch (default)
    		mov		#0x009C, &0x5c6	//UCA0BRW	for 9600 baud, 24MHz clock
    		mov		#0x2241, &0x5c8	//UCA0MCTLW	"
    		bic.b   #0x01,	 &0x5c0	//UCA0CTLW0 &= ~UCSWRST  // release from reset
    	
    
    //Clear RAM
    
    RamClr:	mov	#RAMsize,r11
    ;
    //known pattern for testing uart now
    
    RamClrLoop;
    		sub	#2,r11
    		mov	#4d4eh,RAMbegin(r11)
    		jnz	RamClrLoop
    ;
    	mov.b #0,RxInptr
    	mov.b #0,RxOutptr
    	mov.b #0,RxCount
    	mov.b #0,TxInptr
    	mov.b #0,TxOutptr
    	mov.b #0,TxCount
    	mov.b #0,UARTflags
    
    /*****************Setup stacks and user variables**************/
    
    		mov	#rstack, sp
    
    		bis		#1,&5dah			//Enable UART receive interrupt
    		eint
    
    #define UART_ECHO_TEST
    #if defined UART_ECHO_TEST
    
    		mov		#XON,tos
    		call	#TputIn
    ;
    tloop:	call	#RpullOut			//Wait 'til something in there
    		cmp		#-1,tos
    		jeq		tloop
    
    		
    tloop2:	call	#TputIn
    		jne		tloop
    		jmp		tloop2				//Wait 'til XMIT space available
    #endif
    
    
    /***********Serial transmit*************/
    ;
    ; User side transmit, jeq after return signifies no room
    ; Character input in r7, output is zero flag, set if no more room
    ; Must clear Rx interrupt enable also, 'cuz it fusses with TxFifo
    ;
    TputIn: bic		#3,&5dah			//Clear TX interrupt enable
    		nop							//very necessary
    		nop
    		nop
    ;
    		cmp.b	#FIFOSIZE,&TxCount
    		jeq		tpx					//No room left
    
    		bit.b	#CtlOreceived,&UARTflags
    		jne		tpx
    ;
    ;There is room
    ;
    tp1:	mov.b	&TxInptr, r14
    		mov.b	tos,TxFifo(r14)
    ;
    		inc		r14
    		and		#FIFOSIZE-1,r14
    		mov.b	r14, &TxInptr
    ;
    		inc.b	&TxCount
    ;
    		bit.b	#XOFFreceived,&UARTflags
    		jne		tpx2
    ;
    		bis		#3,&5dah			//re-enable Tx and Rx interrupts
    		bic		#2,sr				//Clear zero flag
    ;
    tpx:	bis		#1,&5dah			//re-enable Rx interrupt
    tpx2:	ret
    ;
    /************************Serial port Function `RpullOut'***********************/ 
    ;
    ; User side getchar.  -1 returned means no char available (NULL is a valid character)
    ;
    ; Output is in r7 (tos), char in high addressed (LSB) byte
    ;
    RpullOut:
    		bic		#1,&5dah				//Clear UART Rx interrupt 
    		nop
    		nop
    		nop
    ;
    		tst.b	&RxCount
    		jeq		L6
    ;
    		dec.b	&RxCount
    ;
    		mov.b	&RxOutptr, r14
    		rla		r14
    		mov		RxFifo(r14),tos
    ;
    		rra		r14						//carry is 0
    		inc		r14
    		and		#FIFOSIZE-1, r14
    		mov.b	r14, &RxOutptr
    ;
    ;	If > RXONPT remaining spaces, send XON on tx interrupt
    ;
    		cmp.b	#FIFOSIZE-RXONPT,&RxCount
    		jne		L5
    ;
    		bic.b	#SendXOFF, &UARTflags	//Clear SendXOFF prepare to send XON
    		bis		#2,&5dah				//Enable  Tx interrupt
    		jmp		L5
    ;
    L6:		mov		#-1,tos
    L5:		bis		#1,&5dah				//Enable UART receive interrupt
    		ret
    
    ;
    /***************************Serial Communiction interrupt**************/
    ;
    uart_isr:
    		pushm.w	#4,r15
    		nop
    		nop
    		nop
    		nop
    ;
    ;all IFG flags were zero when read here, making them unusable in an ISR
    ;
    		mov		&5deh, r15			//Interrupt vector register
    		cmp		#2, r15				//Rx vector
    		jeq		ReceiveISR
    ;
    		cmp		#4, r15				//Tx vector
    		jeq		XmitISR
    ;
    L27:	popm.w	#4,r15
    		reti
    ;
    		//Receiver
    ;
    ReceiveISR:
    		mov		&5cah, r12				//UCA0 status
    		mov		&5cch, r13				//Recv buffer
    		bis		&5cah, r12				//UCA0 status OR in overrun
    		and		#7ch,  r12				//clear bits we're not interested in
    		bit.b	#8,r12					//check break
    		jeq		NoBreak
    ;
    		bis.b	#UARTbreak,&UARTflags	//Set break flag
    		mov.b	#CtlC,r13				//Put CTRL_C into receive character
    NoBreak:
    		tst.b	r12
    		swpb	r12
    		bis.b	r13,r12					//Merge errors to received character
    		jne		SkipTests				//from tst.b above, don't test special
    ;
    ;		Check special cases on error free characters
    ;
    		cmp.b	#XOFF,r13				//XOFF	
    		jeq		GotXoff
    ;
    		cmp.b	#XON,r13				//XON
    		jeq		GotXon
    ;
    		cmp.b	#CtlC,r13				//CTRL_C
    		jeq		GotCtlC
    ;
    		cmp.b	#CtlO,r13				//CTRL_O, send XMIT Chars to /dev/null
    		jeq		GotCtlO
    ;
    		//Check state of receive fifo
    ;
    SkipTests:
    		mov.b	&RxCount, r14	
    		cmp.b	#FIFOSIZE,r14 
    		jhs		DoBEL					//No room
    ;
    ;	If remaining RX space < RXOFFTRIGGER, send XOFF
    ;
    		cmp		#FIFOSIZE-RXOFFTRIGGER, r14
    		jhs		doXOFF
    ;
    ;	Insert char and err into RxFifo
    ;
    		mov.b	&RxInptr, r15
    		rla		r15
    		mov		r12, RxFifo(r15)		//store the character and error bits
    ;
    		rra		r15
    		add.b	#1, r15
    		and		#FIFOSIZE-1, r15
    		mov.b	r15, &RxInptr
    ;
    		add.b	#1, &RxCount
    		jmp		L27
    ;
    ;
    ;
    GotXoff:bis.b	#XOFFreceived,&UARTflags	//XOFF received bit
    		bic		#2,&5dah					//Disable Tx interrupt
    		jmp		L27
    ;
    GotXon:	bic.b	#XOFFreceived,&UARTflags	//clear XOFF received bit
    		jmp		L27
    ;
    GotCtlC:bis.b	#UARTbreak,&UARTflags		//Set UARTbreak
    		jmp		L27
    ;
    GotCtlO:bit.b	#CtlOreceived,&UARTflags	//CtlO toggles
    		jeq		DoCtlO
    ;
    		bic.b	#CtlOreceived,&UARTflags
    		jmp		L27
    ;
    DoCtlO:	bis.b	#CtlOreceived,&UARTflags	//Toggle CTRL_O
    		mov		#0,&TxInptr					//does TxOutptr also, .w
    		mov.b	#0,&TxCount					//Empty the XMIT fifo
    		bic		#2,&5dah					//Disable Tx interrupt
    		jmp		L27
    ;
    ;Here's a big problem: we can't tell if the xmitter is free to load :-(
    ;but if we don't load it and it's idle, tx interrupts stop.
    ;Inside the ISR, the IFG bits seem to always read 0, even before reading the vector reg.
    ;So the XMTR UCTXCPIFG bit is useless here.
    ;
    DoBEL:	tst.b	&TxCount
    		jne		BelLater
    ;
    		mov		#BEL,&5ceh			
    		bis.b	#2,&5dah					//Enable Tx interrupt
    		jmp		L27
    
    BelLater:
    		bis.b	#RfifoFull,&UARTflags		//send BEL when xmtr available
    		jmp		L27
    ;
    ;	If remaining RX space < RXOFFTRIGGER, send XOFF
    ;	(same big problem here)
    ;
    doXOFF:	tst.b	&TxCount
    		jne		XoffLater
    ;
    		mov		#XOFF,&5ceh			
    		bis.b	#2,&5dah					//Enable Tx interrupt
    		jmp		L27
    ;
    XoffLater:
    		bis.b	#SendXOFF, &UARTflags		//Set SendXOFF if not much more room
    		jmp		L27
    
    
    
    //Transmitter
    ;
    ;Mini state machine description for XOFF transmitting process:
    ;			
    ;	SendxOFF		XOFFsent
    ;		0				0	; normal processing
    ;		1				0	; XOFF pending to be sent
    ;		1				1	; XOFF sent, must send an XON when Rfifo room appears.
    ;		0				1	; XON pending to be sent when xmtr ready
    ;
    //UARTflags:
    // RtsCts RfifoFull TxBusy UARTbreak CtlOreceived XOFFreceived SendXOFF XOFFsent
    ;
    //Transmitter
    
    XmitISR:bic.b	#TxBusy, &UARTflags			//Clear TxBusy (not currently used)
    ;
    		mov.b	&UARTflags, r15
    		bit.b	#RfifoFull, r15
    		jne		SendBEL
    ;
    		bit.b	XOFFreceived, r15
    		jne		StopSending
    ;
    		and		#SendXOFF|XOFFsent, r15
    		cmp		#SendXOFF, r15
    		jeq		DoXOFF						//XOFF pending
    ;
    		cmp		#XOFFsent, r15				//XON pending when tx ready
    		jeq		DoXON
    ;
    TestXct:tst.b	&TxCount
    		jne		DoSend
    ;
    StopSending:
    		bic		#2,&5dah					//disable TX interrupts
    		jmp		L27
    ;
    ;		//Send character from TxFIFO
    ;
    DoSend:	mov.b	&TxOutptr, r15
    		mov.b	TxFifo(r15),r14				//Collect byte as word
    		bis.b	#TxBusy,&UARTflags
    		mov.w	r14,&5ceh					//Send it out
    ;
    		inc.b	r15
    		and.b	#FIFOSIZE-1, r15
    		mov.b	r15, &TxOutptr
    ;
    		dec.b	&TxCount
    		jne		L27
    ;
    		bic		#2,&5dah					//disable TX interrupts, Tx fifo was empty
    		jmp		L27
    ;
    ;
    SendBEL:
    		bic.b	#RfifoFull,&UARTflags
    		bis.b	#TxBusy,&UARTflags
    ;
    		mov		#BEL, &5ceh
    		jmp		L27
    ;
    ;
    DoXOFF:	bis.b	#TxBusy,&UARTflags
    		mov		#XOFF, &5ceh				//XOFF -> Tx buffer
    		bis.b	#XOFFsent, &UARTflags		//Set XOFFsent
    		jmp		L27
    ;
    DoXON:	bis.b	#TxBusy,&UARTflags
    		mov		#XON, &5ceh					//XON -> Tx buffer
    		bic.b	#XOFFsent, &UARTflags		//Clear XOFFsent
    		jmp		L27
    ;
    		nop
    ;
    /*********************************************************************/
    ; Interrupt Vectors
    
            rseg    INTVEC
    
    intvecs: dc16 nullirq    ; $FF80  -  reserved 
    			org 0fff0h
             dc16 uart_isr	 	;	 $FFF0  -  eUSCI_A0 rx,tx 
    			org 0fffeh
             dc16 reset			;	 $FFFE  -  reset 
            end
    
    

    I've made a couple of corrections. please look at this code instead of previous upload.  It still won't work well with screen loads of text, but it's ok for

    normal terminal interactions.

  • Your code is quite complex and I am slow. So it will take me a while to go through it.

    You are using XON/XOFF flow control. If there is a transmission error for the XON/XOFF, the consequence is fatal. You may need to implement a safety net for that. But that is not your current problem. I think your current problem is in the details of your current code.

    According to the description of the UART in FR57xx, there is a register bit for transmit complete. It can even generate an interrupt. Is there a hardware bug and it does not work?

    Various IFG bits are capable of generating an interrupt request if the corresponding IE bit is set. When a particular interrupt request is granted, the IV register is automatically set to indelicate which IFG interrupt is now granted and that IFG is automatically cleared. Access to other registers may also clear that IFG. I think you may not be fully aware of the above.

    I currently cannot access FR57xx chip and can only read the specs.

  • Thanks for your suggestions.  I did know about other interrupts, but now I see I can use the TX ready interrupt to set a flag to give permission to load the TX buffer if I can guarantee it hasn't been loaded before I see the flag somehow.  About XON/XOFF I'll add some kind of timeout, although if the system hangs, we'll probably just reboot..

    Note, TX complete and all other flags  in IFG is zero inside an interrupt routine, at least they were in my tests.

  • In my own FIFO, I handle the TX side this way:

    when the TX interrupt is called but the queue is empty (or, if the ISR reads the last byte from FIFO into TXBUF, both situations work), the ISR clears the IE bit. (if you use the IV register and the IFG bit has been cleared, you can manually set it again). So when the ISR exits, no more interrupts happen, but the IFG bit is still set.

    When the putch funciton adds a bayte to the FIFO (or, in your case, sets the flag for XOFF or XON), it always sets the IE bit. If the TX isn't ready for a new byte (the TX chain still active), nothing happens. If TX has stopped before, it will immediately start sicne the IFG bit is still set and as soon as the IE bit gets set too, an interrupt happens. Then the ISR can determine whether to send XON/XOFF or continue sending the new FIFO content.

    It works as well if the RX ISR is setting the flag for XOFF and sets TXIE. Or if the getch() function that reads from the RX FIFO sets the flag for XON and sets TXIE. It's not limited to the putch() function.

  • Thanks for your analysis and response.  I'll get back to that soon and try.

  • FYI, I did add IFG setting as you suggested, but still not reliable, so I added another "NOP" after commands that disable TX interrupt and voila! it works.

    There's a total of 4 noops after clearing the interrupt enable in the user side Txputin() function.  Maybe that has something to do with me running at 24MHz..

  • Due to instruciton prefetch, a NOP is required after clearing GIE before doing a critical operation. Also, setting and clearing (or v.v.) GIE must not direcly follow each other (which may happen due to automatic inlining of small functions)

    But four NOP? There must be some racing condition in your code.

  • Regarding the necessity of "nop"s, here's another case that got me:

    jmp foo

    .

    .

    foo:nop               <----------This nop is essential! otherwise the zero flag won't set even if r7 == 0.

            tst r7

           jz somewhere

    What conditions require these nops?

  • Hoyt A. Stearns Jr. said:
    What conditions require these nops?

    Apparently this is a case of misuse of the debugger or misinterpretation of the results.

    A breakpoint is hit when the processor fetches the instruciton with the breakpoint. This does not only mean that the instruction hasn't been executed yet, it also means that the previous instruciton likely hasn't executed yet due to instruction prefetching.

    This nop isn't required for proper processor funciton, but just because you misplaced your breakpoint and didn't fully understand how the debugger works and what implications it has to set a breakpoint.
    You're not the only one who were mistaken here. It is a common mistunderstandign that a debugger will stop the world turning, freeze the processor mid-operation and tell you the momentary state. This is sometimes true for an emulated processor/virtual machine/interpreted code.
    However, the MSP is optimized for best performance on lowest power, not for easiest debugging.

  • Thanks for the analysis.  I'm pretty sure, however, that the reason I put a breakpoint there to begin with was the code didn't  detect the zero and crashed.

    I'll try again without the nop and the IAR  debugger not attached.  Does a disabled breakpoint cause the issue?

  • Hoyt A. Stearns Jr. said:
    Does a disabled breakpoint cause the issue?

    A disabled breakpoint is nonexistent for the MSP. It's just a 'bookmark' in the debugger configuration and has no effect on the target.

  • My debugging update:

    Apparently,a  "jmp" in my function caused crashing I'm guessing due to it being on a "page" boundary, because

    by moving it in memory, it now works fine (the jmps are to close by locations).  This has happened before, so the question is:

    What's a good way to ensure that jmps in the code are in safe places, other than manual inspecitons of the map and relocatiing code?

    ( My analysis could be wrong -- it was just a hunch).

  • Never mind, I found a jmp into an invisible macro causing the problem. Sorry for the posting.

  • Hi jens-Michael,

    I have read your posts. They are good and informative.

    I have one problem , I am using MSP430FR6989 EVM board. And on that I am trying Default UART loopback Test. The Output Of the loopback Is not able to detect on the terminal as per said.

    can you please Help me in this problem.?
    If you need any more information , tell me.

    Thanks,
    Hinesh
  • What exactly do you mean with 'output of the loopback is not able to detect on the terminal'? What is your setup (hardware/software), what do you expect (and why) and what do you observe?

    The loopback connects the UART's internal RX shift register input to the TX shift register output rather than the RX pin. So if you are sending something, you're receiving it at the same time. Of course with some delay (due to the double-buffering) between writing to TXBUF and receiving the byte in RXBUF.
  • Hi Jens,

    Thanks for reply.

    H/w

    using MSP430FR6989 EVM connected to pc via usb-serial converter.

    I want to send data from one terminal(of EVM connected to pc ) and I wanted back to pc on other terminal(usb-serial).

    my S/W

    #include <msp430.h>

    int main(void)
    {
      WDTCTL = WDTPW | WDTHOLD;                 // Stop Watchdog

      // Configure GPIO
      P2SEL0 |= BIT0 | BIT1;                    // USCI_A0 UART operation
      P2SEL1 &= ~(BIT0 | BIT1);

      // Disable the GPIO power-on default high-impedance mode to activate
      // previously configured port settings
      PM5CTL0 &= ~LOCKLPM5;

      // Startup clock system with max DCO setting ~8MHz
      CSCTL0_H = CSKEY >> 8;                    // Unlock clock registers
      CSCTL1 = DCOFSEL_3 | DCORSEL;             // Set DCO to 8MHz
      CSCTL2 = SELA__VLOCLK | SELS__DCOCLK | SELM__DCOCLK;
      CSCTL3 = DIVA__1 | DIVS__1 | DIVM__1;     // Set all dividers
      CSCTL0_H = 0;                             // Lock CS registers

      // Configure USCI_A0 for UART mode
      UCA0CTLW0 = UCSWRST;                     
      UCA0CTLW0 |= UCSSEL__SMCLK;               // CLK = SMCLK
      // Baud Rate calculation
      // 8000000/(16*9600) = 52.083
      // Fractional portion = 0.083
        // UCBRFx = int ( (52.083-52)*16) = 1
      UCA0BR0 = 52;                             // 8000000/16/9600
      UCA0BR1 = 0x00;
      UCA0MCTLW |= UCOS16 | UCBRF_1 | 0x4900;
      UCA0CTLW0 &= ~UCSWRST;                    // Initialize eUSCI
      UCA0IE |= UCRXIE;                         // Enable USCI_A0 RX interrupt

      __bis_SR_register(LPM3_bits | GIE);       // Enter LPM3, interrupts enabled
      __no_operation();                         // For debugger
    }

    #if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
    #pragma vector=USCI_A0_VECTOR
    __interrupt void USCI_A0_ISR(void)
    #elif defined(__GNUC__)
    void __attribute__ ((interrupt(USCI_A0_VECTOR))) USCI_A0_ISR (void)
    #else
    #error Compiler not supported!
    #endif
    {
      switch(__even_in_range(UCA0IV, USCI_UART_UCTXCPTIFG))
      {
        case USCI_NONE: break;
        case USCI_UART_UCRXIFG:
          while(!(UCA0IFG&UCTXIFG));
          UCA0TXBUF = UCA0RXBUF;
          __no_operation();
          break;
        case USCI_UART_UCTXIFG: break;
        case USCI_UART_UCSTTIFG: break;
        case USCI_UART_UCTXCPTIFG: break;
      }
    }

    After the whole connection when I can send data on EVM but not able to receive PC terminal.

    I want to do loopback test on this device.

    Thanks.

    Hinesh

  • Assuming you are using P2.0 and P2.1 as UART TxD and RxD, your code is okay. It will receive incoming 3V UART serial data at 9600 b/s with 8 data bits and no parity, and transmit the same out.

    But I do not know the EMV you use. Is P2.0 and P2.1 connected to another 3V UART and eventually to/from PC COM Port? That is, I do not know the rest of your "loop". If any link of the rest of you "loop" is not what you think it is, your "loopback" will not work.

    To test the rest of your "loop", you could disconnect P2.0 and P2.1 from them and place a jumper wire between those points. If this does not work, then the rest of your "loop" is definitely not what you think it is, or is broken.
  • Hi,

    The "loop" is simple.

    From Controller the pc terminal is connected via usb-serial (3v UART). There is no loop in between.
    I am sending data from pc to controller, And as per my code , that data should be RX by the pc without change.

    But When I am sending data , I am not able to RX any on Pc. But I will Surely do the connection once to ensure no break in between.

    Thanks,
    Hinesh
  • Okay, so I misunderstood the 'loopback', assuming you mean the internal UART loopback feature.

    It's pointless to go into LPM3 if you use SMCLK for the UART, If the UART does an unconditional request for SMCLK, then the maximum LPM is LPM1. If it doesn't, you go into LMP3 but SMCLK is disabled and the UART doesn't receive anything. Which would be an explanation of why you're not getting an echo. Well, conditional SMCLK request is the default in CSCTL6, so this shouldn't be a problem. YOu only should know that you won't get LPM3 but only LPM1 when looking at the power consumption :)

    It's also very bad style (i'd even call it illegal) to have a busy-waiting loop inside the ISR. It is, however, not critical in this situation, as you're sending at the same speed as receiving, so the loopback code in the ISR will never have to wait at all. But as soon as you're trying to send something on your own, you'll get into trouble with this construct. For a real application, even if it implements an echo like this, you'll need to use an interrupt-operated output buffer, so incoming bytes are added to the output buffer, interleaved with anything you main code might send. And sending them to TXBUF is done win the TX interrupt.

    Do you have an LED attached? You might want to toggle it inside the ISR. So you can see whether the MSP receives data (and just does not properly send back= or doe snot receive anything at all (and therefore has nothing to send back).
    Of course it would be good to have a logic analyzer (like the saleae logic) attached to RX and TX. Then you could see what signals are coming (if at all) and their timing (in case of baudrate problems).

    It's also possible that you need to connect DSR and DTR on your USB/SER converter. Some terminal programs set DTR and don't send anything at all if they don't get DSR back from the attached device.

    Of course it's also possible that either your USB/SER converter or the MSP have their timing off, so the MSP won't receive bytes but rather get framing errors. Or that there is some misconfiguraiton of your terminal program(s). If I'm getting this right, you are sending from terminal program one to the MSP and want to receive the answer through a different RS232 connection on a second terminal program? Are you sure you got the hardware wired correctly then?
  • HI Jens-Michael Gross,

    First of all I wanted to thank you for look in to problem.
    And I might say., Very descriptive Answer. :-)


    Yes, From the Hardware point, Everything is properly connected( I double checked it .) and the baud is set properly in PC terminal.

    You also understood correctly that I wanted to send from PC terminal -> MSP430FR6989 -> usb-serial Converter -> Terminal(serial's terminal).

    I agree the ISR is very Unprofessional, It will just for the testing purpose for now for end application to work.

    I will change the LPM3 to LPM1 and also look in SMCLK.

    Do you have any sample for this ( I mean you have tested successfully ) , If yes than I can Try to find that My code is wrong or H/W is.?

    Thank you for the understanding and detail answer.

    Thanks,

    Hinesh

  • I never used this particular chip or EVM.
    I have written library code (which belongs to my employer) that handles four independent UARTs in full duplex at the same time (for the MSP430F5438A) using 8 ring buffers, ISRs and a function set bases on the standard fgetch/fputch etc. With the UART number as stream ID. On the hardware side, however, I always had either an RS485 or RS232 Transceiver attached, and in all my applications, one UART goes to one transceiver for both directions.

    I'm a bit unsure about the PC->6989 direction. Which EVM do you use? So I can take a look at the internal schematics.

    You can try to replace entering LPM1/3 with a loop tat checks for TXIFG set and then writes a character to TXBUF. If your second terminal gets an endless row of these characters, then you know that this direction is working. You may expand this to send a string (one character at a time) once it is working.

    The best thing would of course be to check the RX and TX signals right at the MSP pins with a logic analyzer. It iwll tell you what't coming in and going out, independently of possible software problems.

    When in doubt, reduce the doubt to one thing. This reduces the possibilities to two: yes or no. The more variables are still in the game, the more (2^n) possible combinations and therefore reasons for failure you have.
  • Hi Janes,

    I ma using MSP430FR6989 EVM . The Technical Details can be found from below.

    Thanks,

    Hinesh

  • Hinesh Gohel said:
    Yes, From the Hardware point, Everything is properly connected( I double checked it .)

    The hardware includes the EMV board. JMG does not know what that is. I do not know either. I think you made the same mistake twice when you checked it. 

  • Hinesh Gohel said:

    Hi Janes,

    I ma using MSP430FR6989 EVM . The Technical Details can be found from below.

    MSP430FR6989 | MSP430FRxx FRAM | Ultra-low Power | Description & parametrics

    www.ti.com
    Download a datasheet or document on TIs MSP430FR6989 Ultra-low Power, from the MSP430FRxx FRAM collection of analog and digital product folders.# Added

    Thanks,

    Hinesh

    That URL points to the MSP430FR6989 chip, not the EVM board.

  • Hi old_Yellow_cow,

    I am sorry for pointing the chip of MSP.

    Please find below link for the EVM

    www.ti.com/.../msp-exp430fr6989.

    Please consider this link for EVM.


    Thanks,
    Hinesh
  • Thanks. But the new pointer does not work either.
    I cannot find any EVM from TI that uses MSP430FR6989.

    Is your board a LaunchPad? (www.ti.com/.../msp-exp430fr6989

    Or, is it a Water Meter? (www.ti.com/.../tidu487.pdf)
  • Hi old_yellow_cow,

    Yes it's Launchpad. I have tried to Edit the link many time but was not able to.

    please check this link.


    Thanks,

    Hinesh

  • Eons ago (Oct 14), I said:

    old_cow_yellow said:
    Assuming you are using P2.0 and P2.1 as UART TxD and RxD, your code is okay. It will receive incoming 3V UART serial data at 9600 b/s with 8 data bits and no parity, and transmit the same out.

    But I do not know the EMV you use. Is P2.0 and P2.1 connected to another 3V UART and eventually to/from PC COM Port? That is, I do not know the rest of your "loop". If any link of the rest of you "loop" is not what you think it is, your "loopback" will not work.

    To test the rest of your "loop", you could disconnect P2.0 and P2.1 from them and place a jumper wire between those points. If this does not work, then the rest of your "loop" is definitely not what you think it is, or is broken.



    Well, I still say: "Assuming you are using P2.0 and P2.1 as UART TxD and RxD, your code is okay."

    Not "good", but "okay" for the intended loop test.

    As for my question: "Is P2.0 and P2.1 connected to another 3V UART and eventually to/from PC COM Port?", I have the answer now.

    On that LaunchPad, P2.0 and P2.1 end up connected to J1 pin 8 and J2 pin 19 respectively and eventually to/from nowhere. There was no "loop" at all.

    Consider use UCA1 (instead of UCA0) and connect via P3.4 and P3.5 (instead of P2.0 and P2.1).
  • Hi old_cow_yellow,

    I am using P2.0 and P2.1 of EVM as UART Tx and Rx (UCA0). And from that the Rx and Tx  goes to Usb-> serial Converter-> PC.

    Basically this is the loop. And I have tried with Changing of Pins(I have used P4.2 and P4.3.  ) and bit changes on Software.


    As result Its was working.  Need to modify more and work on it.


    Thank you and JMG for looking in to my problem and advice.

    will be needing more advice on this as I go deep in my project.

    Thank you,

    Hinesh

  • P3.4 and P3.5 are internally connected to the FET and from there routed to the applicaiton UART (virtual COM port) on the PC. This is USCIA1.
    UASCIA0 is by default on P2.0 and P2.1, which is probably connected to the separate USB/SER converter.
    This converter has its own virtual COM port.

    P4.2 and P4.3 are by default UCB1SOMI and UCB1CLK, unless you mapped them differently. So I'm a bit puzzled. But if it's working for you now, then fine.

    One advice for future questions: be _very_ detailed when describing your setup. We can't see what you have before you, we only see your words. So 'draw' a detailed picture with your description. You don't have to pay for every letter you type. So write rather more then less, to avoid being ambiguous.
  • Hi ,


    I am working on the I2C of MSP430FR6989 (Same EVM as above,). I am interfacing ADXL375 on I2C with MSP430 EVM.
    My code is as below. (Same as the Example code but the slave address is changed).


    int main(void)
    {
      WDTCTL = WDTPW | WDTHOLD;

      // Configure GPIO
      P1OUT &= ~BIT0;                           // Clear P1.0 output latch
      P1DIR |= BIT0;                            // For LED
      P1SEL0 |= BIT6 | BIT7;                    // I2C pins

      // Disable the GPIO power-on default high-impedance mode to activate
      // previously configured port settings
      PM5CTL0 &= ~LOCKLPM5;

      // Configure USCI_B0 for I2C mode
      UCB0CTLW0 |= UCSWRST;                     // Software reset enabled
      UCB0CTLW0 |= UCMODE_3 | UCMST | UCSYNC;   // I2C mode, Master mode, sync
      UCB0CTLW1 |= UCASTP_2;                    // Automatic stop generated
                                                // after UCB0TBCNT is reached
      UCB0BRW = 0x0008;                         // baudrate = SMCLK / 8
      UCB0TBCNT = 0x0005;                       // number of bytes to be received
      UCB0I2CSA = 0x001D;                       // Slave address
      UCB0CTL1 &= ~UCSWRST;
      UCB0IE |= UCRXIE | UCNACKIE | UCBCNTIE;

      while (1)
      {
        __delay_cycles(2000);
        while (UCB0CTL1 & UCTXSTP);             // Ensure stop condition got sent
        UCB0CTL1 |= UCTXSTT;                    // I2C start condition

        __bis_SR_register(LPM0_bits | GIE);     // Enter LPM0 w/ interrupt
      }
    }

    #if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
    #pragma vector = USCI_B0_VECTOR
    __interrupt void USCI_B0_ISR(void)
    #elif defined(__GNUC__)
    void __attribute__ ((interrupt(USCI_B0_VECTOR))) USCI_B0_ISR (void)
    #else
    #error Compiler not supported!
    #endif
    {
      switch(__even_in_range(UCB0IV, USCI_I2C_UCBIT9IFG))
      {
        case USCI_NONE:
            break;         // Vector 0: No interrupts
        case USCI_I2C_UCALIFG:
            break;         // Vector 2: ALIFG
        case USCI_I2C_UCNACKIFG:                // Vector 4: NACKIFG
          UCB0CTL1 |= UCTXSTT;                  // I2C start condition
          break;
        case USCI_I2C_UCSTTIFG:  break;         // Vector 6: STTIFG
        case USCI_I2C_UCSTPIFG:  break;         // Vector 8: STPIFG
        case USCI_I2C_UCRXIFG3:  break;         // Vector 10: RXIFG3
        case USCI_I2C_UCTXIFG3:  break;         // Vector 12: TXIFG3
        case USCI_I2C_UCRXIFG2:  break;         // Vector 14: RXIFG2
        case USCI_I2C_UCTXIFG2:  break;         // Vector 16: TXIFG2
        case USCI_I2C_UCRXIFG1:  break;         // Vector 18: RXIFG1
        case USCI_I2C_UCTXIFG1:  break;         // Vector 20: TXIFG1
        case USCI_I2C_UCRXIFG0:                 // Vector 22: RXIFG0
          RXData = UCB0RXBUF;                   // Get RX data
          __bic_SR_register_on_exit(LPM0_bits); // Exit LPM0
          break;
        case USCI_I2C_UCTXIFG0:  break;         // Vector 24: TXIFG0
        case USCI_I2C_UCBCNTIFG:                // Vector 26: BCNTIFG
          P1OUT ^= BIT0;                        // Toggle LED on P1.0
          break;
        case USCI_I2C_UCCLTOIFG: break;         // Vector 28: clock low timeout
        case USCI_I2C_UCBIT9IFG: break;         // Vector 30: 9th bit
        default: break;
      }
    }

    My problem is , When I run the code in CCSv6. I am not getting any ack from device.
    The H/W connection is checked here. Suggest me if I am going in any wrong direction?


    Thanks,

    Hinesh

  • The usual three suspects when the sampel code does nto work:
    1) missing or not strong enough pull-up resistors on SCL and SDA
    2) missing GND connection between master and slave (yes, the "2-wire bus" needs actually 3 wires)
    3) wrong slave address.

    Note that the slave address does NOT contain the R/W bit. It only contians the upper 7 bits of the start byte, right jsutified. The R/W bit is added by the USCI based on the UCTR bit when starting a read or writ etransfer.
    So if a slave is accessed with 0x1c and 0x1d, then its slave address is 0x0e.
  • Hi Jens,


    Thanks for Reply.,

    1)  missing or not strong enough pull-up resistors on SCL and SDA
    A:- Pull up is added of 10k for interfacing ADXL375

    2) missing GND connection between master and slave (yes, the "2-wire bus" needs actually 3 wires)
    A:- GND is also connected (At First Only I have connected)

    3) wrong slave address.
    A:- As per data-sheet when CS pin and ALT pin is high The address should be 0x1D.

    (I have also tried 0x0e and other register for write combination to check  )

    But Still I am not values at USCI while checking with breakpoints.


    Can You help me out in this matter,

    Thanks,

    Hinesh



  • Hinesh Gohel said:
    1)  missing or not strong enough pull-up resistors on SCL and SDA
    A:- Pull up is added of 10k for interfacing ADXL375

    Depending on bus speed and line capacitance/impedance, it might be not strong enough. For 100kHz, sometimes 4k7 are required, for 400kHz, often 1k is needed.

    You wote "(Same as the Example code but the slave address is changed)" so if the code doesn't work, it must be either the change slave address, the external hardware or the example code was not meant for this CPU (in which case you normally should get lots of compile errors). Since usually, published sample code works )even though it is not always suitable as a base for own code).

    According to the datasheet, the I2C address is indeed 0x1d, but by pulling the ALT ADDRESS pin to GND, it can be 0x53. Leaves the hardware as primary suspect.Are you sure that both, ALT and CS are tied to VccIO and not connected to an MSP pin? If the device runs in SPI mode (because the EVM is built so that the MSP can switch modes by I/O and oyur code does not configure this I/O), then it won't of course react to I2C signals.

    Tracing the I2C signals with a logic analyzer and a scope (for the actual voltage levels an waveform) would be the next step for debugging your system. However, this can't be done through a forum.

  • Hi Jens-Michael Gross,

    Thanks for Reply,

    "Depending on bus speed and line capacitance/impedance, it might be not strong enough. For 100kHz, sometimes 4k7 are required, for 400kHz, often 1k is needed."

    I have added 4k7 pull up as previously 10k was not working. And Yes, I am very much sure about ALT ADDRESS pin is connected to VccIO of EVM not to MSP.

    And Yes After Checking All the H/W and S/W When It was not working, I have took Scope for Checking the Signals.

    And At The End I was able To Make it work for the I2C, I have took another Break-out board of ADXL345 (Having Same Reg. Configuration as ADXL375).
    So I am sure from F/W and H/W side. Now Will be doing for ADXL375 EVM that I was previously working on.


    Will be posting here more questions., As I go in deep for MSP. :-)

    Thanks,

    Hinesh

  • Hi jeans-Michal Gross,

    I wanted to work on DMA for data Transfer over UART from FRAM. Could you redirect me for any example for the DMA configuration or If you can Enlighten me for using of DMA in Program.


    Thanks,
    Hinesh
  • This is a quite unrelated question and should go into a separate thread (which I wouldn't read anymore, I'm only here because I already participated in this thread and get the notifications)

    However...
    DMA is straightforward. If you want to copy data from FRAM/RAM/FLASH to UART, it is simple: state transfer mode (byte/byte), incrementing soure address, static destination address, give the addresses and the number of bytes and use the UART IFG bit as trigger.
    Works for UART as well as for SPI or I2C
    However, this won't work as easily for I2C receive, as there you need to set UCTXSTP on the last byte. So you need to make your DMA one byte short and handle the last byte with polling/interrupt. You can't have interrupts and DMA (the IE bit must be clear to have the DMA react on the IFG bit).
    And when sending I2C with DMA, you need to take care of the slave probably not answering or you getting a NACK. You'll need to also set a timeout, so you can wake up when the DMA interrupt (notification for DMA transfer done) doesn't come. (in theory, it may also happen on I2C receive, but there is no way to know that the (slave) sender won't send more, so eventually youll get the numbe rof bytes you requested, even if dummy bytes.
    When using FRAM as destination, keep in mind that it must be writable.

    One more thing, you can't copy words to bytes or bytes to words. The DMA won't split a word read (e.g. from ADC) to two byte transfers or assemble two bytes (from UART) to one word (for writing to DAC). A word-to-byte will result in the MSB being dropped and a byte-to-word willr esult in the MSB being written 0.
  • Hi Jens-Michael Gross,

    Thank you for the Answer.


    I have initiated successfully DMA transfer over UART(After number of tries though ;- )    ).

    Thanks,

    Hinesh

  • HI

    In my project I am using MSP430FR6989 and For That I am collecting data in FRAM and using DMA I wanted to sent over UART.

    But As I try to send the data , The data That I am receiving over UART is Not What I Sent. I have Checked The buffer and Also I am Filling Buffer with my known data to verify. But Still I am not able to get the Perfect data.

    Below Is my code snippet and buffer That I am using to Initialize DMA and sending of data over UART.
    And I am using UART TX Interrupt flag for sending data over UART, So I can assure that the Packet once sent over uart than only UART is ready for another. So No loss of data.

    unsigned char const ubuffer[600]={"1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25"};

    void DMA_vTx(unsigned short Sourceaddress , unsigned short length)
    {
    //DMACTL0 = DMA0TSEL__UCA0TXIFG;
    DMA0CTL = DMADT_1 | DMASBDB| DMASRCINCR_3 | DMAIE| DMALEVEL_L;
    DMA0SA = (__SFR_FARPTR)(unsigned int ) Sourceaddress; /*DMA Source Address*/
    DMA0DA = (__SFR_FARPTR)(unsigned int )&UCA0TXBUF; /*DMA Destination Address*/
    DMA0SZ = length; /*DMA Transfer Block size*/
    DMA0CTL |= DMAEN;
    UCA0IFG |= 0x02;
    DMA0CTL |= DMAREQ;



    };
    DMA_vTx(ubuffer,600);

    My UART boad rate is set for 460800. So It's high speed that I can configure on the other side.

    Thanks,
    Hinesh

**Attention** This is a public forum