micropython/drivers/cc3000/src/patch_prog.c

415 wiersze
12 KiB
C

#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");
}