XMMC and i2c
I am having a good time playing with the Propeller GCC beta. I’ve been trying to make use of the XMMC memory model. I am using a C3 board and SimpleIDE 0-8-5 for OSX.
The cog_c_toggle demo works if I set the SimpleIDE memory model to XMMC and the board type C3-SDXMMC or C3F-SDXMMC. However if I take a working C program (compiled for LMM) that is reading a DS1307 RTC using the i2c buss and compile it using the same parameters it hangs on the “i2c_open();” Should the i2c functions work in XMMC?
Thanks.
Mark
The cog_c_toggle demo works if I set the SimpleIDE memory model to XMMC and the board type C3-SDXMMC or C3F-SDXMMC. However if I take a working C program (compiled for LMM) that is reading a DS1307 RTC using the i2c buss and compile it using the same parameters it hangs on the “i2c_open();” Should the i2c functions work in XMMC?
Thanks.
Mark

Comments
If you're using the SD to store XMMC memory then the XMM driver will be accessing the i2c bus. This is could be a problem. I'm not familiar enough with the internal workings of the XMM drivers and i2c code to be able to say whether there is any way to make the combination work.
Will your code fit in hub memory in CMM mode?
Eric
When you say you're using i2c_open, do you mean i2cOpen? I'm not familiar with i2c_open.
Thanks,
David
Thanks for your help.
/** * @file t2.c * Test inteface to DS1307 RTC * This is the main t2 program start point. */ #include <stdio.h> #include <unistd.h> #include <string.h> #include <time.h> #include "DS1307.h" #include <propeller.h> /* interface routines to hook DS1307 into system time routines */ void gettime(struct timeval *); void settime(struct timeval *); int main(void) { time_t tim; int i; printf("start test program\n"); /* set globals to point to my time routines */ _rtc_gettime = gettime; _rtc_settime = settime; printf("system globals reasigned to DS1307 access routines\n"); /* start clock */ startRTC(); printf("RTC started\n"); /* read the time */ for (;;) { tim=time(NULL); struct tm *now=localtime(&tim); printf("Date is %d/%02d/%02d ",now->tm_mon+1, now->tm_mday,now->tm_year+1900); printf("Time is %02d:%02d ", now->tm_hour, now->tm_min); printf("Seconds since ... %d\n",mktime(now)); usleep(200000); } return; }//////////////////////////////////////////////////////////////////////////////// /// DS1307.C /// /// Driver for Real Time Clock /// /// /// //////////////////////////////////////////////////////////////////////////////// #include "DS1307.h" #include <stdio.h> #include <propeller.h> #include <string.h> #include <sys/rtc.h> char bin2bcd(char binary_value); char bcd2bin(char bcd_value); /* i2c buss stuff */ I2C *bus; uint8_t buffer[DS1307_DATE_TIME_BYTE_COUNT]; /* DS1307 stuff */ struct tm td; struct timeval tv; /*start up DS1307*/ void startRTC() { printf("before i2c_open\n"); bus = i2c_open(); printf("%i returned form i2c_open\n",bus); return; } /* read the ds1307 data registers */ void RTCread(I2C *bus, uint8_t *bptr) { /* select the data registers */ if (i2cWrite(bus, DS1307_I2C_WRITE_ADDR, 0, 1, TRUE) != 0) printf("Write failed\n"); usleep(2000000); /* read the data registers */ if (i2cRead(bus, DS1307_I2C_READ_ADDR, &bptr[0], DS1307_DATE_TIME_BYTE_COUNT, TRUE) != 0) printf("Read failed\n"); return; } /* over ride sysem default for reading the time, load tm structure structure */ void gettime(struct timeval *tv) { /* select the data registers */ if (i2cWrite(bus, DS1307_I2C_WRITE_ADDR, 0, 1, TRUE) != 0) printf("Write failed\n"); usleep(2000000); /* read the data registers */ if (i2cRead(bus, DS1307_I2C_READ_ADDR, &buffer[0], DS1307_DATE_TIME_BYTE_COUNT, TRUE) != 0) printf("Read failed\n"); td.tm_sec = bcd2bin(buffer[DS1307_SECONDS_REG]); td.tm_min = bcd2bin(buffer[DS1307_MINUTES_REG]); td.tm_hour = bcd2bin(buffer[DS1307_HOURS_REG]); td.tm_wday = bcd2bin(buffer[DS1307_DAY_OF_WEEK_REG]); td.tm_mday = bcd2bin(buffer[DS1307_DATE_REG]); td.tm_mon = bcd2bin(buffer[DS1307_MONTH_REG])-1; td.tm_year = bcd2bin(buffer[DS1307_YEAR_REG])+ 100; tv->tv_sec = mktime(&td); return; } /* try and open the i2c buss */ I2C * i2c_open(void) { I2C *bus; /* open i2c buss */ printf("about to call i2c_open\n"); if (!(bus = (I2C *)i2cBootOpen())) printf("error: can't boot open i2c bus\n"); else printf("i2c buss opened\n"); return bus; } /* sleep */ void sleep(seconds) { int time,i; time = CNT; for (i=0;i<seconds;i++) { time += CLKFREQ; waitcnt(time); } return; } /* convert binary to binary coded decimal */ char bin2bcd(char binary_value) { char temp; char retval; temp = binary_value; retval = 0; while(1) { /* Get the tens digit by doing multiple subtraction */ /* of 10 from the binary value */ if(temp >= 10) { temp -= 10; retval += 0x10; } else // Get the ones digit by adding the remainder. { retval += temp; break; } } return(retval); } /* conver binary coded decimal to binary */ /* Input range - 00 to 99 */ char bcd2bin(char bcd_value) { char temp; temp = bcd_value; /* Shifting upper digit right by 1 is same as multiplying by 8 */ temp >>= 1; /* Isolate the bits for the upper digit */ temp &= 0x78; /* Now return: (Tens * 8) + (Tens * 2) + Ones */ return(temp + (temp >> 2) + (bcd_value & 0x0f)); } /* not implemented */ void settime(struct timeval *tv) { tv->tv_sec = 0; tv->tv_usec = 0; return; }The problem with XMMC running from EEPROM is that it uses I2C for fetching code. This can result in a conflict with other devices that use I2C.
One way around this problem is to prepend all of the I2C functions with: HUBTEXT
I.E:
HUBTEXT void RTCread(I2C *bus, uint8_t *bptr)
{
...
}
HUBTEXT will cause any such function to live in HUB RAM so that the I2C bus is not used for fetching code while the I2C is being accessed.
The functions RTCread, i2cRead, i2cWrite, and maybe gettime are all candidates for being HUBTEXT.
The call that is failing is i2cBootOpen, the i2c_open is my wrapper - sorry. This does not seem to change the behavior. I'm wondering if I should open an i2c bus on different pins? I have been using 28/29 with i2CBootOpen.
Thanks for the comments.
Below is a very simple attempt to open the i2c buss on pins 28/29. I got rid of all the DS1307 stuff. All it does is a i2cOpen. It works fine complied with LMM, but it never returns from the i2cOpen if I use XMMC. I get the same result using i2cBootOpen.
What should the last parameter of the i2cOpen be? I found an example that used 400000 so that is what I tried. Is there something that I should be reading to get more background?
#include <stdio.h> #include <i2c.h> /* i2c buss stuff */ I2C *bus; I2C_COGDRIVER cdriver; void openbus() { I2C_COGDRIVER *CD; CD = &cdriver; printf("before i2copen\n"); /* open i2c buss */ if(!(bus = (I2C *)i2cOpen(CD, 28, 29, 400000))) printf("error: can't open i2c bus\n"); else printf("i2c buss opened\n"); return; } int main(void) { printf("start XMMC test program\n"); /* open i2c buss */ openbus(); return; }Thanks for trying to help me out.mark