For a project I am connecting two MSP's (MSP430FR6989) with each other, one as a master (of which the code has been given and I cannot change a lot about it, so I cannot use SPI) and one as a slave. The slave one will just act as a memory extension to the master (who will write an address and data to the slave). There are many ways of "solving" this, however my hand was forced in how to do it.
The master will write an address to the slave, and he will also pull one pin high (doesn't do anything on the slave) and another low (will cause an interrupt on the slave). These pins are respectively 3.0 and 3.1. Depending on which pin is pulled low, the slave will either read the data from the master and store it in the address the master has given, or it will look at the address and write the data stored at this address to the master.
As you can imagine, a lot of timing problems occur when you just do this (data doesn't stay on the pins long enough, etc.). I tried to solve this by using the pin 3.2. The master will only read if that pin is pulled High(it will basically poll the entire time since the master need not do anything else in this time). The same thing happens (about ish) when writing. The master will push this pin Low again
The pieces for the code of the master are:
void write(uint16_t address, uint8_t data){
splitAndWriteAddress(address); // splits up the address over the available pins in ports and writes it.
P2DIR |= 0xFF; // set dataIO in write mode
P3OUT |= BIT1; // deactivate read mode
P3OUT &= ~BIT0; // activate write mode
P2OUT = data; // write data
while(!(P3IN & BIT2)){
__no_operation();
}
P3OUT |= BIT0; // deactivate write mode
P3DIR |= BIT2;
P3OUT &= ~BIT2;
P3DIR &= ~BIT2;
//P2DIR |= 0x00; // set dataIO in read mode
}
uint8_t read(uint16_t address){
uint8_t data = 0x00;
splitAndWriteAddress(address);
P2DIR &= 0x00; // set dataIO in read mode
P3OUT |= BIT0; // deactivate write mode
P3OUT &= ~BIT1; // activate read mode
while(!(P3IN & BIT2)){
__no_operation();
}
data = P2IN;
P3OUT |= BIT1; // deactivate read mode
P3DIR |= BIT2;
P3OUT &= ~BIT2;
P3DIR &= ~BIT2;
return data;
}
And for the slave I have made an interrupt:
#if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
#pragma vector=PORT3_VECTOR
__interrupt void Port_3(void)
#elif defined(__GNUC__)
void __attribute__ ((interrupt(PORT3_VECTOR))) Port_3 (void)
#else
#error Compiler not supported!
#endif
{
/*
* 4 usable RAM sections:
* 1. D --> 1800h 'till 187Fh
* 2. C --> 1880h 'till 18FFh
* 3. B --> 1900h 'till 187Fh
* 4. A --> 1980h 'till 19FFh
*/
uint16_t volatile * address = (uint16_t *) getAddress(); // gets the address from the ports
P3DIR |= BIT2;
if(P3IFG & BIT0){
P2DIR &= 0x00; // put in read mode
*address = P2IN;
P3OUT |= BIT2;
}
//WRITE
if(P3IFG & BIT1){ //could be an else
P2DIR |= 0xFF; // put in write mode
P2OUT = *address;
P3OUT |= BIT2;
}
P3DIR &= ~BIT2;
P3IFG=0; // set all flags to 0
}
When debugging, everything works fine (I test using an UART connection) , but when running as normal (in release mode), it does not anymore (the data and address are all given through correctly). This makes me think that it is still a timing error, however I don't know how and why.
I was also thinking that I should be able to do it without using that port 3.2, but I have not tried it yet, because I think there will also be some major timing issues there which I don't know how to solve right now.
If more code is needed please ask, but those are just about the only ones that matter I think.
With kind regards.