Fork to see if I can get working

Dependencies:   BufferedSerial OneWire WinbondSPIFlash libxDot-dev-mbed5-deprecated

Fork of xDotBridge_update_test20180823 by Matt Briggs

Files at this revision

API Documentation at this revision

Comitter:
mbriggs_vortex
Date:
Mon Nov 13 09:50:49 2017 -0700
Parent:
77:176e3eb8f712
Child:
79:69c4f03c0f86
Commit message:
Committing code so far for getting bootloader to work.

Changed in this revision

WinbondSPIFlash.lib Show annotated file Show diff for this revision Revisions of this file
xDotBridge/inc/SerialTermMgr.h Show annotated file Show diff for this revision Revisions of this file
xDotBridge/inc/bootloader.h Show annotated file Show diff for this revision Revisions of this file
xDotBridge/src/SerialTermMgr.cpp Show annotated file Show diff for this revision Revisions of this file
xDotBridge/src/main.cpp Show annotated file Show diff for this revision Revisions of this file
--- a/WinbondSPIFlash.lib	Wed May 17 16:41:56 2017 -0600
+++ b/WinbondSPIFlash.lib	Mon Nov 13 09:50:49 2017 -0700
@@ -1,1 +1,1 @@
-http://developer.mbed.org/users/mbriggs_vortex/code/WinbondSPIFlash/#3bb82c1d3aeb
+https://developer.mbed.org/users/mbriggs_vortex/code/WinbondSPIFlash/#5dcaed12578a
--- a/xDotBridge/inc/SerialTermMgr.h	Wed May 17 16:41:56 2017 -0600
+++ b/xDotBridge/inc/SerialTermMgr.h	Mon Nov 13 09:50:49 2017 -0700
@@ -17,8 +17,10 @@
 const uint8_t TERM_TIMEOUT = 30; // In seconds
 
 const float XMODEM_TIMEOUT = 10.0;
+const unsigned char MAX_TIMEOUTS = 6; // multiple by TIMEOUT above.  60 total seconds
 const uint16_t FLASH_BIN_OFFSET = 256; // Skip first flash page
 const uint16_t XMODEM_PACKET_SIZE = 128;
+//const char NEW_CODE [] = "NEWCODE0";
 
 enum ScreenId {
     mainScreenId,
@@ -48,6 +50,7 @@
     void inputEnterProgMode (char in);
     void printEnterProgMode();
     bool xmodem2Flash();
+    void writeBootloaderCtrlPage(uint32_t nBytes);
 public:
     SerialTermMgr(BaseboardIO *bbio, WinbondSPIFlash *flash, float fwVersion);
     void regSerial (BufferedSerial *pc) {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/xDotBridge/inc/bootloader.h	Mon Nov 13 09:50:49 2017 -0700
@@ -0,0 +1,189 @@
+/*
+ * bootloader.h
+ *
+ *  Created on: Nov 12, 2017
+ *      Author: mbriggs
+ */
+
+#ifndef XDOTBRIDGE_INC_BOOTLOADER_H_
+#define XDOTBRIDGE_INC_BOOTLOADER_H_
+
+const char NEW_CODE [] = "NEWCODE0";
+const char END0LINE [] = "END0LINE";
+#define XDOT_FLASH_START       0x08000000
+#define XDOT_FLASH_SIZE        0x00040000
+#define XDOT_SECTOR_SIZE	   4096
+#define BOOTLOADER_OFFSET 	   81920 // 80 KB
+//#define APPLICATION_ADDRESS    XDOT_FLASH_START
+#define APPLICATION_ADDRESS    XDOT_FLASH_START+BOOTLOADER_OFFSET
+#define PAGE_SIZE			   256
+
+//FLASH_ProcessTypeDef pFlash;
+__attribute__( ( section(".data") ) )
+void writeBootLoaderReprogramDone(WinbondSPIFlash *flash)
+{
+	// This should always be less than 256 bytes
+	const uint32_t zero = 0;
+	const unsigned int ctrlSize = sizeof(END0LINE)+sizeof(uint32_t);
+	char buf[ctrlSize];
+	std::memcpy(buf, END0LINE, sizeof(END0LINE));
+	std::memcpy(buf+sizeof(END0LINE), &zero, sizeof(zero));
+	// TODO add reprogram counter just for fun
+
+	// Copy to first page of flash
+    flash->writeStream(0, buf, sizeof(buf));
+}
+
+__attribute__( ( section(".data") ) )
+uint32_t readBootLoaderCtrlPage(WinbondSPIFlash *flash)
+{
+	const unsigned int ctrlSize = sizeof(NEW_CODE)+sizeof(uint32_t);
+	char buf[ctrlSize];
+    flash->readStream(0, buf, sizeof(buf));
+	uint32_t nBytes = 0;
+	char ctrlCode[sizeof(NEW_CODE)];
+	// This should always be less than 256 bytes
+	std::memcpy(&ctrlCode, buf, sizeof(NEW_CODE));
+	std::memcpy(&nBytes, buf+sizeof(NEW_CODE), sizeof(nBytes));
+	// TODO add reprogram counter just for fun
+
+	// Check NEW_CODE str
+	for (unsigned int i=0;i<sizeof(NEW_CODE);i++) {
+		if (ctrlCode[i] != NEW_CODE[i]) {
+			return 0;
+		}
+	}
+
+	// Copy to first page of flash
+    return nBytes;
+}
+
+//__attribute__( ( section(".data")) )
+//HAL_StatusTypeDef RAM_HAL_FLASH_Unlock(void)
+//{
+//  if (HAL_IS_BIT_SET(FLASH->PECR, FLASH_PECR_PRGLOCK))
+//  {
+//    /* Unlocking FLASH_PECR register access*/
+//    if(HAL_IS_BIT_SET(FLASH->PECR, FLASH_PECR_PELOCK))
+//    {
+//      WRITE_REG(FLASH->PEKEYR, FLASH_PEKEY1);
+//      WRITE_REG(FLASH->PEKEYR, FLASH_PEKEY2);
+//    }
+//
+//    /* Unlocking the program memory access */
+//    WRITE_REG(FLASH->PRGKEYR, FLASH_PRGKEY1);
+//    WRITE_REG(FLASH->PRGKEYR, FLASH_PRGKEY2);
+//  }
+//  else
+//  {
+//    return HAL_ERROR;
+//  }
+//
+//  return HAL_OK;
+//}
+//
+//__attribute__( ( section(".data")) )
+//HAL_StatusTypeDef RAM_HAL_FLASH_Program(uint32_t TypeProgram, uint32_t Address, uint64_t Data)
+//{
+//  HAL_StatusTypeDef status = HAL_ERROR;
+//
+//  /* Process Locked */
+//  __HAL_LOCK(&pFlash);
+//
+//  /* Check the parameters */
+//  assert_param(IS_FLASH_TYPEPROGRAM(TypeProgram));
+//  assert_param(IS_FLASH_PROGRAM_ADDRESS(Address));
+//
+//  /* Wait for last operation to be completed */
+//  status = FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE);
+//
+//  if(status == HAL_OK)
+//  {
+//    /* Clean the error context */
+//    pFlash.ErrorCode = HAL_FLASH_ERROR_NONE;
+//
+//    /*Program word (32-bit) at a specified address.*/
+//    *(__IO uint32_t *)Address = Data;
+//
+//    /* Wait for last operation to be completed */
+//    status = FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE);
+//  }
+//
+//  /* Process Unlocked */
+//  __HAL_UNLOCK(&pFlash);
+//
+//  return status;
+//}
+//
+//__attribute__( ( section(".data")) )
+//HAL_StatusTypeDef RAM_HAL_FLASH_Lock(void)
+//{
+//  /* Set the PRGLOCK Bit to lock the FLASH Registers access */
+//  SET_BIT(FLASH->PECR, FLASH_PECR_PRGLOCK);
+//
+//
+//  return HAL_OK;
+//}
+
+__attribute__( ( section(".data") ) )
+void copyNewProgram ()
+{
+	uint32_t nBytes, updateBytes;
+    WinbondSPIFlash *flash = new WinbondSPIFlash(SPI_MOSI, SPI_MISO, SPI_SCK, SPI_NSS);
+    char *charbuf = new char [PAGE_SIZE];
+	HAL_FLASH_Unlock();
+
+    flash->releaseFromPowerDown();
+
+	nBytes = readBootLoaderCtrlPage(flash);
+
+	if (nBytes > 0) {
+//		printf("flash read address %lu\r\n", readBootLoaderCtrlPage);
+//		printf("Updating main application %lu bytes...\r\n", nBytes);
+
+		uint32_t nBytesCopied=0;
+		unsigned int pageIdx=0;
+		while (nBytesCopied < nBytes){
+//	    	printf("Start read %d.\r\n", us_ticker_read());
+			flash->readStream(pageIdx*PAGE_SIZE, charbuf, PAGE_SIZE);
+
+//	    	printf("Stop read, start erase %d.\r\n", us_ticker_read());
+			// Erase page
+			// Erasing may not be required but it seems like good practice
+			FLASH_EraseInitTypeDef eraseStruct;
+			eraseStruct.TypeErase = FLASH_TYPEERASE_PAGES;
+			eraseStruct.NbPages = 1;
+			eraseStruct.PageAddress = APPLICATION_ADDRESS+nBytesCopied;
+		//	eraseStruct.PageAddress = 0x0801E000; // Sector 30, Page 478
+
+			uint32_t eraseError;
+			if (HAL_FLASHEx_Erase(&eraseStruct, &eraseError) != HAL_OK) {
+//				printf("Error erasing flash. \r\n");
+			}
+
+//	    	printf("Stop erase, start write %d.\r\n", us_ticker_read());
+			// Write page
+			for (unsigned int i=0;i<(PAGE_SIZE/sizeof(uint32_t));i++) {
+				if (HAL_FLASH_Program(TYPEPROGRAM_WORD, APPLICATION_ADDRESS+nBytesCopied,
+						*((uint32_t *)(charbuf+sizeof(uint32_t)*i))) != HAL_OK) {
+//					printf("Error programming flash. \r\n");
+				}
+				nBytesCopied += sizeof(uint32_t);
+			}
+//	    	printf("Stop write %d.\r\n", us_ticker_read());
+			pageIdx++;
+			printf("%lu / %lu\r\n", nBytesCopied, nBytes);
+		}
+		HAL_FLASH_Lock();
+	}
+
+	// FIXME add some prints and checking code
+
+    flash->powerDown();
+    delete flash;
+
+//    printf("Restarting main application...\r\n");
+	NVIC_SystemReset();
+}
+
+#endif /* XDOTBRIDGE_INC_BOOTLOADER_H_ */
--- a/xDotBridge/src/SerialTermMgr.cpp	Wed May 17 16:41:56 2017 -0600
+++ b/xDotBridge/src/SerialTermMgr.cpp	Mon Nov 13 09:50:49 2017 -0700
@@ -7,6 +7,7 @@
 
 #include "SerialTermMgr.h"
 #include "UserInterface.h"
+#include "bootloader.h"
 
 extern Serial pc;
 const char ACK = 0x06;
@@ -22,6 +23,7 @@
     mCurrScreen = mainScreenId;
     mBbio = bbio;
     mFlash = flash;
+
 }
 void SerialTermMgr::printScreen()
 {
@@ -242,6 +244,7 @@
     uint8_t csum = 0;
     unsigned char pktIdx = 0;
     time_t lastValidInput = 0;
+    unsigned char nTimeouts = 0;
     while (1) {
         // Send a NAK if a packet is not received within timeout period
         if ((time(NULL)-lastValidInput) > XMODEM_TIMEOUT){
@@ -249,39 +252,41 @@
             pktIdx = 0;
             mPc->printf("%c", NAK); // Send NAK
             lastValidInput = time(NULL);
-            // TODO need to timeout of XMODEM
+            nTimeouts++;
+            if (nTimeouts >= MAX_TIMEOUTS) {
+                mPc->printf("Programming timed out.\r\n");
+                pc.printf("Programming timed out.\r\n");
+                break;
+            }
+
         }
         if (mPc->readable()) {
             packetBuf[pktIdx++] = mPc->getc();
             if (pktIdx == 1 && packetBuf[0] == EOT) {
                 lastValidInput = time(NULL);
                 mPc->printf("%c", ACK); // Last ACK
+                mPc->printf("Success.\r\n");
+                pc.printf("Success on xmodem.  Reset in progress.\r\n");
+                writeBootloaderCtrlPage(packetNum*XMODEM_PACKET_SIZE);
+//				copyNewProgram();
+
                 wait(0.01);
-                mPc->printf("Success.\r\n");
-                pc.printf("Success on xmodem.\r\n");
+				mFlash->powerDown();
+                NVIC_SystemReset();
+				// Should never get here because of reset.
                 break;
             }
             else if (pktIdx >= 132) {
                 lastValidInput = time(NULL);
+                nTimeouts = 0; // Clear n timeouts with new packet
                 csum = 0;
-//                pc.printf("Got full packet.\r\n");
-//                pc.printf("Header SOH: %02X, Packet #%02X, inv #%02x\r\n", packetBuf[0], packetBuf[1], packetBuf[2]);
                 for (int i=3; i<131; i++) {
-//                    pc.printf("%02X", packetBuf[i]);
                     csum += packetBuf[i];
                 }
                 pktIdx = 0;
-//                pc.printf("\r\ncsum = %d (%02X). Got %d (%02X)\r\n", csum, csum, packetBuf[131], packetBuf[131]);
                 if ((csum == packetBuf[131]) && (packetBuf[0] == SOH) &&
                     (packetBuf[1] == ((uint8_t)packetNum)) && (((uint8_t)~packetBuf[2]) == ((uint8_t)packetNum))) {
-//                    if (packetBuf[1] == packetNum) {
-//                        pc.printf("One works.\r\n");
-//                    }
-//                    if (((uint8_t)~packetBuf[2]) == packetNum) {
-//                        pc.printf("Two works.\r\n");
-//                    }
-//                    pc.printf("%02X == %02X\r\n", packetNum, (uint8_t)~packetBuf[2]);
-                    mFlash->writeStream(FLASH_BIN_OFFSET+packetNum*XMODEM_PACKET_SIZE, packetBuf+3, XMODEM_PACKET_SIZE);
+                    mFlash->writeStream(FLASH_BIN_OFFSET+(packetNum-1)*XMODEM_PACKET_SIZE, packetBuf+3, XMODEM_PACKET_SIZE);
                     mPc->printf("%c", ACK);
                     packetNum++;
                 }
@@ -296,3 +301,16 @@
 
     return true;
 }
+
+void SerialTermMgr::writeBootloaderCtrlPage(uint32_t nBytes)
+{
+	// This should always be less than 256 bytes
+	const unsigned int ctrlSize = sizeof(NEW_CODE)+sizeof(nBytes);
+	char buf[ctrlSize];
+	std::memcpy(buf, NEW_CODE, sizeof(NEW_CODE));
+	std::memcpy(buf+sizeof(NEW_CODE), &nBytes, sizeof(nBytes));
+	// TODO add reprogram counter just for fun
+
+	// Copy to first page of flash
+    mFlash->writeStream(0, buf, sizeof(buf));
+}
--- a/xDotBridge/src/main.cpp	Wed May 17 16:41:56 2017 -0600
+++ b/xDotBridge/src/main.cpp	Mon Nov 13 09:50:49 2017 -0700
@@ -17,14 +17,18 @@
 
 #define RX_SEQ_LOG 1
 
-const float BridgeVersion = 1.01;
+const float BridgeVersion = 99.99;
+
+// 232 Pins
+const PinName SER_TERM_TX = UART_TX;
+const PinName SER_TERM_RX = UART_RX;
 
 #ifndef __TEST__ // Exclude code for tests
 Serial pc(USBTX, USBRX);
 //RawSerial outPc(UART_TX, UART_RX);
 //Serial *outPc;
 BufferedSerial *outPc;
-InterruptIn uart1RxIntIn (UART_RX);
+InterruptIn uart1RxIntIn (SER_TERM_RX);
 
 //// Serial interrupts / buffer code
 //const int buffer_size = 255;
@@ -85,6 +89,11 @@
     pairBtnIntFlag = true;
 }
 
+void testFunc() {
+	const uint32_t test=0xDEADBEEF;
+	printf("%d", test);
+}
+
 int main() {
     CommProtocolPeerBrute *protocol = new CommProtocolPeerBrute();
     BaseboardIO *bbio = new BaseboardIO();
@@ -208,6 +217,8 @@
     while (true) {
 //        myLogInfo("Start of loop time %d", us_ticker_read());
         ledPatterns.turnOff();
+		bbio->serialRx(true); // FIXME find a better home
+		bbio->serialTx(false); // FIXME only turn on during TX
 
         // Pair logic and switch sampling
         if (pairBtnIntFlag) {
@@ -293,10 +304,11 @@
 
         // Serial Terminal
         if (uartRxFlag) {
+            pc.printf("Got RX Int\r\n");
             uart1RxIntIn.disable_irq();
 //            pc.printf("Got uart flag!!!\r\n");
             uartRxFlag = false;
-            outPc = new BufferedSerial(UART1_TX, UART1_RX);
+            outPc = new BufferedSerial(SER_TERM_TX, SER_TERM_RX);
             outPc->baud(TERM_BAUD);
             serialTermMgr.regSerial(outPc);
             char c;