diff options
author | Damien George <damien.p.george@gmail.com> | 2014-09-26 00:56:45 +0100 |
---|---|---|
committer | Damien George <damien.p.george@gmail.com> | 2014-09-26 00:56:45 +0100 |
commit | f996d8854f0cdd88446a8a369e1b330c14ea3eb7 (patch) | |
tree | 3cd5949d155bc412e4b28b8c47bb9cd19e51fd0c /drivers/cc3000/src/patch_prog.c | |
parent | 55a5b807937a4be8d57153970d723bc31113b6d4 (diff) | |
download | micropython-f996d8854f0cdd88446a8a369e1b330c14ea3eb7.tar.gz micropython-f996d8854f0cdd88446a8a369e1b330c14ea3eb7.zip |
drivers, cc3k: Move cc3000 driver from stmhal to drivers directory.
Diffstat (limited to 'drivers/cc3000/src/patch_prog.c')
-rw-r--r-- | drivers/cc3000/src/patch_prog.c | 414 |
1 files changed, 414 insertions, 0 deletions
diff --git a/drivers/cc3000/src/patch_prog.c b/drivers/cc3000/src/patch_prog.c new file mode 100644 index 0000000000..fd128928fb --- /dev/null +++ b/drivers/cc3000/src/patch_prog.c @@ -0,0 +1,414 @@ +#include <stdio.h> +#include <string.h> +#include "cc3000_common.h" +#include "nvmem.h" +#include "ccspi.h" +#include "hci.h" +#include "wlan.h" +#include "patch_prog.h" +#define BIT0 0x1 +#define BIT1 0x2 +#define BIT2 0x4 +#define BIT3 0x8 +#define BIT4 0x10 +#define BIT5 0x20 +#define BIT6 0x40 +#define BIT7 0x80 + +static unsigned char ucStatus_Dr; +static unsigned char ucStatus_FW; +static unsigned char return_status = 0xFF; + +static signed char mac_status = -1; +static unsigned char counter = 0; + +// Array to store RM parameters from EEPROM. +static unsigned char cRMParamsFromEeprom[128]; +// Array to store MAC address from EEPROM. +static unsigned char cMacFromEeprom[MAC_ADDR_LEN]; +// Smart Config Prefix +static const char aucCC3000_prefix[] = {'T', 'T', 'T'}; + +static void systick_sleep(unsigned long ms) { + extern void HAL_Delay(volatile uint32_t Delay); + HAL_Delay(ms); +} + +// 2 dim array to store address and length of new FAT +static const unsigned short aFATEntries[2][NVMEM_RM_FILEID + 1] = +/* address */ {{0x50, 0x1f0, 0x390, 0x1390, 0x2390, 0x4390, 0x6390, 0x63a0, 0x63b0, 0x63f0, 0x6430, 0x6830}, +/* length */ {0x1a0, 0x1a0, 0x1000, 0x1000, 0x2000, 0x2000, 0x10, 0x10, 0x40, 0x40, 0x400, 0x200}}; +/* 0. NVS */ +/* 1. NVS Shadow */ +/* 2. Wireless Conf */ +/* 3. Wireless Conf Shadow */ +/* 4. BT (WLAN driver) Patches */ +/* 5. WiLink (Firmware) Patches */ +/* 6. MAC addr */ +/* 7. Frontend Vars */ +/* 8. IP config */ +/* 9. IP config Shadow */ +/* 10. Bootloader Patches */ +/* 11. Radio Module params */ +/* 12. AES128 for smart config */ +/* 13. user file */ +/* 14. user file */ +/* 15. user file */ + +//***************************************************************************** +// +//! sendDriverPatch +//! +//! \param pointer to the length +//! +//! \return none +//! +//! \brief The function returns a pointer to the driver patch: +//! since there is no patch yet - it returns 0 +// +//***************************************************************************** + +static char *sendDriverPatch(unsigned long *Length) +{ + *Length = 0; + return NULL; +} + + +//***************************************************************************** +// +//! sendBootLoaderPatch +//! +//! \param pointer to the length +//! +//! \return none +//! +//! \brief The function returns a pointer to the boot loader patch: +//! since there is no patch yet - it returns 0 +// +//***************************************************************************** + +static char *sendBootLoaderPatch(unsigned long *Length) +{ + *Length = 0; + return NULL; +} + +//***************************************************************************** +// +//! sendWLFWPatch +//! +//! \param pointer to the length +//! +//! \return none +//! +//! \brief The function returns a pointer to the FW patch: +//! since there is no patch yet - it returns 0 +// +//***************************************************************************** + +static char *sendWLFWPatch(unsigned long *Length) +{ + *Length = 0; + return NULL; +} + +//***************************************************************************** +// +//! CC3000_UsynchCallback +//! +//! \param Event type +//! +//! \return none +//! +//! \brief The function handles asynchronous events that come from CC3000 +//! device and operates a LED4 to have an on-board indication +// +//***************************************************************************** + +static void CC3000_UsynchCallback(long lEventType, char * data, unsigned char length) +{ + +} + +//***************************************************************************** +// +//! initDriver +//! +//! \param[in] cRequestPatch 0 to load with EEPROM patches +//! and 1 to load with no patches +//! +//! \return none +//! +//! \brief The function initializes a CC3000 device +//! and triggers it to start operation +// +//***************************************************************************** +static int initDriver(unsigned short cRequestPatch) +{ + // WLAN On API Implementation + wlan_init(CC3000_UsynchCallback, sendWLFWPatch, sendDriverPatch, sendBootLoaderPatch, + ReadWlanInterruptPin, SpiResumeSpi, SpiPauseSpi, WriteWlanPin); + + // Trigger a WLAN device + wlan_start(cRequestPatch); + wlan_smart_config_set_prefix((char*)aucCC3000_prefix); + wlan_ioctl_set_connection_policy(0, 0, 0); + wlan_ioctl_del_profile(255); + + // Mask out all non-required events from CC3000 + wlan_set_event_mask(HCI_EVNT_WLAN_KEEPALIVE| + HCI_EVNT_WLAN_UNSOL_INIT| + HCI_EVNT_WLAN_ASYNC_PING_REPORT); + + //unsolicicted_events_timer_init(); + systick_sleep(100); + return(0); +} + + +//***************************************************************************** +// +//! fat_read_content +//! +//! \param[out] is_allocated array of is_allocated in FAT table:\n +//! an allocated entry implies the address and length of the +//! file are valid. +//! 0: not allocated; 1: allocated. +//! \param[out] is_valid array of is_valid in FAT table:\n +//! a valid entry implies the content of the file is relevant. +//! 0: not valid; 1: valid. +//! \param[out] write_protected array of write_protected in FAT table:\n +//! a write protected entry implies it is not possible to write +//! into this entry. +//! 0: not protected; 1: protected. +//! \param[out] file_address array of file address in FAT table:\n +//! this is the absolute address of the file in the EEPROM. +//! \param[out] file_length array of file length in FAT table:\n +//! this is the upper limit of the file size in the EEPROM. +//! +//! \return on succes 0, error otherwise +//! +//! \brief parse the FAT table from eeprom +// +//***************************************************************************** +static unsigned char __attribute__ ((unused)) +fat_read_content(unsigned char *is_allocated, unsigned char *is_valid, + unsigned char *write_protected, unsigned short *file_address, unsigned short *file_length) +{ + unsigned short index; + unsigned char ucStatus; + unsigned char fatTable[48]; + unsigned char* fatTablePtr = fatTable; + + // + // Read in 6 parts to work with tiny driver + // + for (index = 0; index < 6; index++) + { + ucStatus = nvmem_read(16, 8, 4 + 8*index, fatTablePtr); + fatTablePtr += 8; + } + + fatTablePtr = fatTable; + + for (index = 0; index <= NVMEM_RM_FILEID; index++) + { + *is_allocated++ = (*fatTablePtr) & BIT0; + *is_valid++ = ((*fatTablePtr) & BIT1) >> 1; + *write_protected++ = ((*fatTablePtr) & BIT2) >> 2; + *file_address++ = ((*(fatTablePtr+1)<<8) | (*fatTablePtr)) & (BIT4|BIT5|BIT6|BIT7); + *file_length++ = ((*(fatTablePtr+3)<<8) | (*(fatTablePtr+2))) & (BIT4|BIT5|BIT6|BIT7); + + // + // Move to next file ID + // + fatTablePtr += 4; + } + + return ucStatus; +} + +//***************************************************************************** +// +//! fat_write_content +//! +//! \param[in] file_address array of file address in FAT table:\n +//! this is the absolute address of the file in the EEPROM. +//! \param[in] file_length array of file length in FAT table:\n +//! this is the upper limit of the file size in the EEPROM. +//! +//! \return on succes 0, error otherwise +//! +//! \brief parse the FAT table from eeprom +// +//***************************************************************************** +static unsigned char fat_write_content(unsigned short const *file_address, + unsigned short const *file_length) +{ + unsigned short index = 0; + unsigned char ucStatus; + unsigned char fatTable[48]; + unsigned char* fatTablePtr = fatTable; + + // + // First, write the magic number. + // + ucStatus = nvmem_write(16, 2, 0, (unsigned char*)"LS"); + + for (; index <= NVMEM_RM_FILEID; index++) + { + // + // Write address low char and mark as allocated. + // + *fatTablePtr++ = (unsigned char)(file_address[index] & 0xff) | BIT0; + + // + // Write address high char. + // + *fatTablePtr++ = (unsigned char)((file_address[index]>>8) & 0xff); + + // + // Write length low char. + // + *fatTablePtr++ = (unsigned char)(file_length[index] & 0xff); + + // + // Write length high char. + // + *fatTablePtr++ = (unsigned char)((file_length[index]>>8) & 0xff); + } + + // + // Second, write the FAT. + // Write in two parts to work with tiny driver. + // + ucStatus = nvmem_write(16, 24, 4, fatTable); + ucStatus = nvmem_write(16, 24, 24+4, &fatTable[24]); + + // + // Third, we want to erase any user files. + // + memset(fatTable, 0, sizeof(fatTable)); + ucStatus = nvmem_write(16, 16, 52, fatTable); + + return ucStatus; +} + +void patch_prog_start() +{ + unsigned short index; + unsigned char *pRMParams; + + printf("Initializing module...\n"); + + // Init module and request to load with no patches. + // This is in order to overwrite restrictions to + // write to specific places in EEPROM. + initDriver(1); + + // Read MAC address. + mac_status = nvmem_get_mac_address(cMacFromEeprom); + + return_status = 1; + + printf("Reading RM parameters...\n"); + while ((return_status) && (counter < 3)) { + // Read RM parameters. + // Read in 16 parts to work with tiny driver. + return_status = 0; + pRMParams = cRMParamsFromEeprom; + for (index = 0; index < 16; index++) { + return_status |= nvmem_read(NVMEM_RM_FILEID, 8, 8*index, pRMParams); + pRMParams += 8; + } + counter++; + } + + // If RM file is not valid, load the default one. + if (counter == 3) { + printf("RM is not valid, loading default one...\n"); + pRMParams = (unsigned char *)cRMdefaultParams; + } else { + printf("RM is valid.\n"); + pRMParams = cRMParamsFromEeprom; + } + + return_status = 1; + + printf("Writing new FAT\n"); + while (return_status) { + // Write new FAT. + return_status = fat_write_content(aFATEntries[0], aFATEntries[1]); + } + + return_status = 1; + + printf("Writing RM parameters...\n"); + while (return_status) { + // Write RM parameters. + // Write in 4 parts to work with tiny driver. + return_status = 0; + + for (index = 0; index < 4; index++) { + return_status |= nvmem_write(NVMEM_RM_FILEID, + 32, + 32*index, + (pRMParams + 32*index)); + } + } + + return_status = 1; + + // Write back the MAC address, only if exists. + if (mac_status == 0) { + // Zero out MCAST bit if set. + cMacFromEeprom[0] &= 0xfe; + printf("Writing back MAC address..\n"); + while (return_status) { + return_status = nvmem_set_mac_address(cMacFromEeprom); + } + } + + // Update driver + ucStatus_Dr = 1; + printf("Updating driver patch...\n"); + while (ucStatus_Dr) { + // Writing driver patch to EEPRROM - PROTABLE CODE + // Note that the array itself is changing between the + // different Service Packs. + ucStatus_Dr = nvmem_write_patch(NVMEM_WLAN_DRIVER_SP_FILEID, + drv_length, + wlan_drv_patch); + } + + // Update firmware + ucStatus_FW = 1; + printf("Updating firmware patch...\n"); + while (ucStatus_FW) { + // Writing FW patch to EEPRROM - PROTABLE CODE + // Note that the array itself is changing between the + // different Service Packs. + ucStatus_FW = nvmem_write_patch(NVMEM_WLAN_FW_SP_FILEID, + fw_length, + fw_patch); + } + + printf("Update complete, resetting module\n"\ + "If this doesn't work, reset manually...\n"); + + wlan_stop(); + systick_sleep(500); + + // Re-Init module and request to load with patches. + initDriver(0); + + // If MAC does not exist, it is recommended + // that the user will write a valid mac address. + if (mac_status != 0) { + printf("MAC address is not valid, please write a new one\n"); + } + + // Patch update done + printf("All done, call wlan.patch_version()\n"); +} |