Hi,
I've started working on launchpad and MSP430 (g2553) quite recently, so I'm still learning the basics, and I appreciate any tips you might have.
I've connected my launchpad to a Freescale i.mx233 linux host, and working on a communication protocol between the devices now, and would like to get some advice.
imx only has half-duplex HW SPI, so my plan is to always initiate connections from imx side, using RX interrupt on MSP. If MSP needs to initiate a conversation to the main CPU, it will pull a separate pin up towards imx, to raise an interrupt.
Currently, I am able to send 1 message from [imx] master to MSP, and also read the message back. But only if I use speed no higher than 490KHz. Actually MSP will successfully read the incoming data (though, I haven't tried longer than 20 bytes) even at 2.3MHz (I checked memory content with debugger), but TX won't be able to shift the bytes quick enough after 500KHz.. In the code below while (!(IFG2 & UCA0TXIFG)) //is this wrong?
Can I ask you to take a look at my code, and point out possible stupidities I am doing, which might cause this ? I'm still not entirely clear on how and which clocks I'm supposed to setup in the beginning. My current understanding is that when in slave mode, MSP shouldn't need any other clocks set up than DCOCTL and BCSCTL1.
- But I can't understand why 16MHz processing is not able to handle even 500KHz TX..
- Is it stupid to use USCIAB0RX_VECTOR for also TX stuff ?
- Isn't USCIAB0RX_VECTOR triggered at every clock pulse ? If I would enable TX interrupts, same clock would trigger 2 interrupts ? I was thinking I should try put everything to 1 interrupt handler, as not to burden the uC
- How about __bis_SR_register(GIE); is that a good mode for the uC to be in ?
My code:
#include "msp430g2553.h"
#include <string.h>
#include "stdarg.h"
char cmdbuf[20];
char cmd_index=0;
int size_received=0;
int incoming_data_size=0;
uint8_t upper_byte= 0;
uint8_t lower_byte= 0;
int loop = 0;
int sending = 0;
void main(void)
{
WDTCTL = WDTPW + WDTHOLD; // Stop watchdog timer
DCOCTL = CALDCO_16MHZ; // DCO frequency set to 16 MHz
BCSCTL1 = CALBC1_16MHZ; // DCO range set to 16 MHz
P1DIR |= BIT6; //p1.6 output (green led)
P1DIR |= BIT0; //p1.0 output (red led)
P1SEL = BIT1 + BIT2 + BIT4;
P1SEL2 = BIT1 + BIT2 + BIT4;
//Turn off pullups from P1, needed?
P1REN = 0;
while (P1IN & BIT4); // If clock sig from mstr stays low,
// it is not yet in SPI mode
flash_spi_detected(); // just blink leds
UCA0CTL1 = UCSWRST; // **Put state machine in reset**
UCA0CTL0 |= UCSYNC; //Sync mode = SPI
UCA0CTL0 |= UCMSB; //MSB first
UCA0CTL1 &= ~UCSWRST; // **Initialize USCI state machine**
IE2 |= UCA0RXIE; // Enable USCI0 RX interrupt
UCA0TXBUF = 0x00;
__bis_SR_register(GIE); // Enable interrupts
}
#pragma vector=USCIAB0RX_VECTOR
__interrupt void USCI0RX_ISR(void)
{
if (!sending) {
//First 2 bytes are the incoming transfer size
if (size_received != 2) {
if (size_received == 1) {
lower_byte = UCA0RXBUF;
size_received++;
incoming_data_size = (upper_byte << 8) | lower_byte;
} else {
upper_byte = UCA0RXBUF;
size_received++;
}
} else {
cmdbuf[cmd_index] = UCA0RXBUF;
cmd_index++;
//Transfer complete
if (cmd_index == incoming_data_size) {
sending = 1;
indidate_msg_read(2); //blink leds
//FIXME temporary increment (otherwise first byte will be 0x00 set in main)
while (!(IFG2 & UCA0TXIFG));
UCA0TXBUF = cmdbuf[0];
loop++;
}
} //receiving part
//now every clock push new byte to TXBUF
} else {
while (!(IFG2 & UCA0TXIFG));
UCA0TXBUF = cmdbuf[loop];
loop++;
}
} //RX interrupt
Please don't hesitate to point out any stupidities I might have conjured here :)