void main(void) { WDTCTL = WDTPW + WDTHOLD; // Stop the watchdog __enable_interrupt(); // Enable general interrupts Board_init(); // Configure's the F5529 EXP board's I/Os // Initialize power/clocks for use with USB SetVCore(3); // The USB module requires that VCore be set to highest setting, independent of MCLK freq ClockUSB(); disk_initialize(0); // SD-cards must go through a setup sequence after powerup. This FatFs call does this. USB_init(); // Initializes the USB API, and prepares the USB module to detect USB insertion/removal events USB_setEnabledEvents(kUSB_allUsbEvents); // Enable all USB events // The data interchange buffer (used when handling SCSI READ/WRITE) is declared by the application, and // registered with the API using this function. This allows it to be assigned dynamically, giving // the application more control over memory management. USBMSC_registerBufInfo(&RW_dataBuf[0], NULL, sizeof(RW_dataBuf)); // The API maintains an instance of the USBMSC_RWbuf_Info structure. If double-buffering were used, it would // maintain one for both the X and Y side. (This version of the API only supports single-buffering, // so only one structure is maintained.) This is a shared resource between the API and application; the // application must request the pointers. RWbuf_info = USBMSC_fetchInfoStruct(); // USBMSC_updateMediaInfo() must be called prior to USB connection. We check if the card is present, and if so, pull its size // and bytes per block. // LUN0 mediaInfo.mediaPresent = 0x01; // The medium is present, because internal flash is non-removable. mediaInfo.mediaChanged = 0x00; // It can't change, because it's in internal memory, which is always present. mediaInfo.writeProtected = 0x00; // It's not write-protected mediaInfo.lastBlockLba = 774; // 774 blocks in the volume. (This number is also found twice in the volume itself; see mscFseData.c. They should match.) mediaInfo.bytesPerBlock = BYTES_PER_BLOCK; // 512 bytes per block. (This number is also found in the volume itself; see mscFseData.c. They should match.) USBMSC_updateMediaInfo(0, &mediaInfo); // LUN1 if(detectCard()) mediaInfo.mediaPresent = kUSBMSC_MEDIA_PRESENT; else mediaInfo.mediaPresent = kUSBMSC_MEDIA_NOT_PRESENT; mediaInfo.mediaChanged = 0x00; mediaInfo.writeProtected = 0x00; disk_ioctl(0,GET_SECTOR_COUNT,&mediaInfo.lastBlockLba); // Returns the number of blocks (sectors) in the media. mediaInfo.bytesPerBlock = BYTES_PER_BLOCK; // Block size will always be 512 USBMSC_updateMediaInfo(1, &mediaInfo); // At compile-time for this demo, there will be one file on the volume. The root directory and data cluster // for this file need to be initialized. //flashWrite_LBA(Root_Dir, (BYTE*)Root_Dir_init); //flashWrite_LBA(Data559, (BYTE*)Data559_init); // Configure Timer_A0 to prompt detection of the SD card every second TA0CCTL0 = CCIE; // Enable interrupt TA0CCR0 = 32768; // Clock will be 32kHz, so we set the int to occur when it counts to 32768 TA0CTL = TASSEL_1 + MC_1 + TACLR; // ACLK = 32kHz, up mode, clear TAR... go! // If USB is already connected when the program starts up, then there won't be a USB_handleVbusOnEvent(). // So we need to check for it, and manually connect if the host is already present. if (USB_connectionInfo() & kUSB_vbusPresent) { if (USB_enable() == kUSB_succeed) { USB_reset(); USB_connect(); } } while(1) { BYTE ReceiveError=0, SendError=0; WORD count; switch(USB_connectionState()) { case ST_USB_DISCONNECTED: __bis_SR_register(LPM3_bits + GIE); // Enter LPM3 until VBUS-on event // Check if the reason we woke was a button press; and if so, log a new piece of data. if(fS1ButtonEvent) { // Build string char str[14] = "Data entry #0\n"; str[12] = logCnt++; // Number the entries 0 through....? memcpy(RW_dataBuf, Data559, BYTES_PER_BLOCK); // Copy data block 559 from flash to RAM buffer memcpy(&RW_dataBuf[DataCnt], str, sizeof(str)); // Write the new entry to the RAM buffer flashWrite_LBA((PBYTE)Data559, RW_dataBuf); // Copy it back to flash DataCnt += sizeof(str); // Increment the index past the new entry if((DataCnt + sizeof(str)>= BYTES_PER_BLOCK)) // Roll index back to 0, if no more room in the block DataCnt = 0; fS1ButtonEvent = 0; } break; case ST_USB_CONNECTED_NO_ENUM: break; case ST_ENUM_ACTIVE: // Call USBMSC_poll() to initiate handling of any received SCSI commands. Disable interrupts // during this function, to avoid conflicts arising from SCSI commands being received from the host // AFTER decision to enter LPM is made, but BEFORE it's actually entered (in other words, avoid // sleeping accidentally). __disable_interrupt(); if((USBMSC_poll() == kUSBMSC_okToSleep) && (!bDetectCard)) { __bis_SR_register(LPM0_bits + GIE); // Enable interrupts atomically with LPM0 entry } __enable_interrupt(); // If the API needs the application to process a buffer, it will keep the CPU awake by returning kUSBMSC_processBuffer // from USBMSC_poll(). The application should then check the 'operation' field of all defined USBMSC_RWbuf_Info // structure instances. If any of them is non-null, then an operation needs to be processed. A value of // kUSBMSC_READ indicates the API is waiting for the application to fetch data from the storage volume, in response // to a SCSI READ command from the USB host. After the application does this, it must indicate whether the // operation succeeded, and then close the buffer operation by calling USBMSC_bufferProcessed(). while(RWbuf_info->operation == kUSBMSC_READ) { switch(RWbuf_info->lun) { case 0: RWbuf_info->returnCode = Read_LBA(RWbuf_info->lba, RWbuf_info->bufferAddr, RWbuf_info->lbCount); // Fetch a block from the medium, using file system emulation USBMSC_bufferProcessed(); // Close the buffer operation break; case 1: read_LUN1(); break; } } // Everything in this section is analogous to READs. Reference the comments above. while(RWbuf_info->operation == kUSBMSC_WRITE) { switch(RWbuf_info->lun) { case 0: RWbuf_info->returnCode = Write_LBA(RWbuf_info->lba, RWbuf_info->bufferAddr, RWbuf_info->lbCount); // Write the block to the medium, using file system emulation USBMSC_bufferProcessed(); // Close the buffer operation break; case 1: write_LUN1(); break; } } // Every second, the Timer_A ISR sets this flag. The checking can't be done from within the timer ISR, because the // checking enables interrupts, and this is not a recommended practice due to the risk of nested interrupts. if(bDetectCard) { checkInsertionRemoval(); bDetectCard = 0x00; // Clear the flag, until the next timer ISR } if(bHID_DataReceived_event) //Message is received from HID application { bHID_DataReceived_event = FALSE; // Clear flag early -- just in case execution breaks below because of an error count = hidReceiveDataInBuffer((BYTE*)dataBuffer,BUFFER_SIZE,HID0_INTFNUM); strncat(wholeString," \r\nRx->",7); strncat(wholeString,(char*)dataBuffer,count); strncat(wholeString," \r\n ",4); if(cdcSendDataInBackground((BYTE*)wholeString,strlen(wholeString),CDC0_INTFNUM,1)) // Send message to other CDC App { SendError = 0x01; break; } memset(wholeString,0,MAX_STR_LENGTH); // Clear wholeString } if(bCDC_DataReceived_event) //Message is received from CDC application { bCDC_DataReceived_event = FALSE; // Clear flag early -- just in case execution breaks below because of an error cdcReceiveDataInBuffer((BYTE*)wholeString,MAX_STR_LENGTH,CDC0_INTFNUM); ASCII(wholeString); if(hidSendDataInBackground((BYTE*)wholeString,strlen(wholeString),HID0_INTFNUM,1)) // Send message to HID App { SendError = 0x01; // Something went wrong -- exit break; } memset(wholeString,0,MAX_STR_LENGTH); // Clear wholeString } break; case ST_ENUM_SUSPENDED: __bis_SR_register(LPM3_bits + GIE); // Enter LPM3, until a resume or VBUS-off event break; case ST_ENUM_IN_PROGRESS: break; case ST_ERROR: break; default:; } if(ReceiveError || SendError) { //TO DO: User can place code here to handle error } } }
void MassStorage(void) { buttonsPressed = 0; SFRIE1 &= ~OFIE; disk_initialize(0); // Initialize Disk Drive #0 SFRIE1 |= OFIE; DEBUG("Init clock\r\n"); ClockUSB(); DEBUG("Init USB\r\n"); USB_init(); // Initialize the USB module P1OUT |= BIT1; // Enable all USB events USB_setEnabledEvents(kUSB_allUsbEvents); // Clal Initialization Function DEBUG("Init MSC\r\n"); msc_Init(); P1OUT |= BIT2; // If USB is already connected when the program starts up, then there won't be a // USB_handleVbusOnEvent(). // So we need to check for it, and manually connect if the host is already present. if (USB_connectionInfo() & kUSB_vbusPresent) { if (USB_enable() == kUSB_succeed) { USB_reset(); USB_connect(); P1OUT |= BIT3; } } while (1) { switch (USB_connectionState()) { DEBUG("Connection state: %u\r\n", USB_connectionState()); case ST_USB_DISCONNECTED: //__bis_SR_register(LPM3_bits + GIE); // Enter LPM3 until VBUS-on event _NOP(); break; case ST_USB_CONNECTED_NO_ENUM: break; case ST_ENUM_ACTIVE: msc_Loop(); break; case ST_ENUM_SUSPENDED: //__bis_SR_register(LPM3_bits + GIE); // Enter LPM3, until a resume or VBUS-off // event break; case ST_ENUM_IN_PROGRESS: break; case ST_ERROR: break; default:; } } DEBUG("Done with MassStorage\r\n"); buttonsPressed = 0; Board_ledOff(LED_ALL); USB_disable(); SFRIE1 &= ~OFIE; Init_FLL_Settle(25000, 762); // Return to normal clock settings SFRIE1 |= OFIE; }