diff --git a/.github/.cSpellWords.txt b/.github/.cSpellWords.txt new file mode 100644 index 0000000..0b83de3 --- /dev/null +++ b/.github/.cSpellWords.txt @@ -0,0 +1,1317 @@ + +acceptmbox +ACCEPTMBOX +accomodate +accoring +acesses +aclient +additinal +Additionaly +Adleman +Adpu +adres +Adrss +aesni +AESNI +AHBCR +ahbwritewaitinterval +ahbwritewaitunit +algorihtmic +ALIGMENT +Alligned +alogortihm +Alpar +ALPAR +alread +alwasy +AMBA +Amira +Ammendment +Anack +ANACK +apdu +Apdu +APDU +APDUCOMM +apdus +APDUs +APDU's +APDUV +applicaiton +approximative +Arbtn +argvp +ARIBTARY +armv +assym +Assym +Assymmetric +asym +Asym +asymetric +asymm +Asymm +ASYMM +asymmkey +ATONEGOTIATION +ATQA +ATRFD +Atrribute +attestaion +attribtes +attst +Attst +ATTST +authenticat +autonego +avialable +avoidng +awrseqindex +awrseqnumber +AXECCREFPEM +BADOUTOFMEMORY +baed +Barreto +BARRETO +BBOOL +B'EN'ETEAU +Bhargavan +biais +bkpt +BKPT +Bleichenbacher's +BMCR +boundry +bptr +breif +bufer +BVIC +byted +bytestorecv +caam +CAAM +Cachable +cahced +caluate +calulating +Catr +CBCDR +cbmc +CBMC +cbor +Cbor +CBOR +CCGR +ccid +Ccid +CCID +ccide +CCIDs +CCLAN +CCOSR +CDEC +CDMA +cerdtials +certficiates +CERTIFCATES +CESR +cexpectednumberofparameters +CFGDTCMSZ +CHALLANGE +charac +CHCONSTL +CHHLSE +chkey +chnage +Chnl +CKIL +CLCOK +cleard +cliip +CLKCFG +CLKO +CLKS +CLKSOURCE +CLRAHBRXBUF +CLRAHBTXBUF +cmac +Cmac +CMAC +Cmdk +cmse +CMSE +cmsis +CMSIS +CNST +Cntx +cofactor +commmand +commuication +communicatation +compilant +Conditionaly +CONDTIONS +confg +CONFICT +configcmdseqs +configurat +conly +Connnection +convertdertopemformat +convertpemtoder +coreid +coremqtt +CORON +correclty +couter +coutermeasueres +coverity +CPCL +CPDU +cplc +Cplc +CPLC +cpsid +cpsie +Credentialnfo +credtialstate +critial +crls +Cryptombedtls +Crypyto +crytpo +Crytpo +Csession +cspadsettingoverride +csrs +CSRS +cssetuptime +CUST +customisation +Customisation +customlut +cyphertext +cyrptogrpahic +Daemen +DATAW +DATSZ +DBICR +Dcap +DCDC +dcdx +deactive +DEBUGF +Decription +deinitializes +Deinitializes +delceration +delimitor +demostration +demultiplexing +Derviation +descritpor +desctription +Deteceted +devicemodetpe +devleoper +dgst +dgug +dhmlen +DHMLEN +differnt +digestbyname +Dindex +DLMS +DMBEDTLS +Docuemntation +doent +doesnt +dqspadsettingoverride +drbg +Drbg +DRBG +Dsmr +DTCM +DTCMSZ +dtype +DWNLD +eccgfp +ecdaa +ECDAA +ecdh +Ecdh +ECDH +ecdhctx +Ecdsakey +ecdsasigner +echci +ecid +ecjpake +ECJPAKE +Ecka +ECKA +Eckabit +eckey +ECKEY +eckeypair +ecount +ecparameters +ecparams +ecpubkey +ECPUBLICKEY +ecrt +Ecrt +ecrypto +EDDSA +EDEV +EEPROM +egovaccelerators +EGOVACCELERATORS +ehci +Ehci +EHCI +EMBSE +emsa +EMSA +emvl +EMVL +EMVSIM +Endiannes +ENDOPOINT +enets +ENTEROPI +ENTERQPI +ephemral +equivlant +ERDF +ERRIRQ +esdsa +esdsaigner +ESEC +Espressif +ethernetif +ETHERNETIF +ethip +Euicc +evkb +EVKB +evkbmimxrt +evkmimx +evkmimxrt +evnet +exaple +exceeed +Exhange +EXITQPI +exmaple +explictily +Exponenciation +exponentiaton +Expresso +Expsosed +EXTCLK +extented +faild +familiy +fdata +FDIS +Feistel +fetchup +fileb +Findex +fira +FIRALITE +FLASHIAP +flashm +Flexio +FLEXIO +FLEXSPIA +flexspirootclk +fnet +fout +Fout +frdm +FRDM +frdmk +FROHF +fromisr +FRTOS +fsanitize +Fsci +Fsdi +fucntion +Funciton +gapplet +gctx +gdir +GDIR +gecc +GECC +geerator +genertor +genral +GETCPLC +gfile +ghlse +GMAC +gmaster +gmbedtls +GNUCC +gnxpese +GPCNT +GPCS +gpdata +gpio +Gpio +GPIO +GPIOA +grsa +Gruss +gsss +gtimer +gusleep +gvar +gxlen +gylen +halfclkfornonreadcmd +Hanle +happn +hasle +havege +HAVEGE +HCASN +HEADR +HEDABOU +hkdf +Hkdf +HKDF +HKDK +HLCRYPT +hlse +Hlse +HLSE +HLSEAPI +hlseret +HSRUN +hwaddr +HWADDR +hwcrypto +hyst +Hyst +IACR +iapfun +iblock +Iblock +ICCPOWERON +idendntifiers +idntifier +idobj +ifindiscards +ifinoctets +ifoutdiscards +ifouterrors +ifoutoctets +ifsc +Ifsc +IFSC +IFSD +IICIF +impelementation +implemetation +implemntation +implmentation +IMXRT +IMXRTXXX +IMXRTYYYY +increament +inded +indentifier +indicaated +initialzie +Initilaize +initilialized +Initilising +initilization +inoffset +Insufficinet +INTEN +Interm +internaly +Intialise +Inversed +INVQ +IOCR +iomuxc +Iomuxc +IOMUXC +IOSB +IOSSDATALAT +ipcmd +IPCMD +ipcmdserialclkfreq +IPCR +ipinreceives +ipoutrequests +ipriority +IPSR +IPTXDAT +iqmp +iret +IRQN +IRQS +isbufferable +ISSI +ISSN +isuniformblocksize +jcop +Jcop +JCOP +jcopx +jitp +JITP +jitr +Jitr +JITR +jrcp +JRCP +jrcplib +jrcpv +jrif +jsmn +JSMN +jsmntok +jsoneq +Kalycito +Karthikeyan +kboot +KBOOT +kbps +kbyte +kbytes +Kbytes +kconfig +kestore +khci +Khci +KHCI +kinv +klass +koblitz +Koblitz +KOBLITZ +KOCHER +ksdk +KSDK +kvstore +KVSTORE +laready +laso +lasr +lcdif +Lcdif +LCDIF +LDRH +lefover +lengh +Lengh +lenght +Lenght +Lengthn +lenth +lhash +licc +Licc +litte +lnger +lnumtries +localip +locl +logicaly +loopif +lpathcount +LPBYTE +lpcip +LPCIP +lpcxpresso +LPCXPRESSO +lpspi +Lpspi +LPSPI +lpthread +Lpuart +LPUART +lset +lutcustomseq +lutcustomseqenable +lvds +LVDS +lwipopts +LWIPOPTS +MANAG +mannual +MAXASYMKEYLENGTH +maxfd +maxium +Maxium +mbed +Mbed +MBED +mbedcrypto +MBEDCRYPTO +mbedpkaltctx +MBEDTLD +MBEDTLSSL +mbedts +MCFGR +MCIMX +MCLK +mctx +mcuboot +Mcuboot +MCUBOOT +MCU's +mcux +Mcux +MCUX +mcuxpresso +MCUXPRESSO +mdctx +mdinfo +mdio +MDIO +MDLM +mebd +mebdtls +memeory +memoy +memp +MEMP +Menezes +merkle +Merkle +MFDF +Mfinish +mflash +MFLASH +mifare +Mifare +MIFARE +Mimick +MIMXRT +MINASYMKEYLENGTH +miscelaneous +misra +MISRA +mmcau +MMCAU +modn +Modulde +moduls +MODX +montogomery +mosquitto +Mosquitto +MOVS +mpis +mqtt +Mqtt +MQTT +mqttbadparameter +mqttconnected +mqttexample +mqttnotconnected +MQTT's +mqttsuccess +MRDR +MSTCTL +msticks +MSTSTSTPERR +msvcrt +msvcrtd +MTDR +Mustapha +mutliple +mwlog +myargv +mynewt +myrand +NACKADR +NACKDAT +nacked +Naehrig +NAEHRIG +neable +necesarily +NEEDCLK +needexitnocmdmode +needrestorenocmdmode +negotation +netif +NETIF +netifapi +NFCA +NISTK +nistp +NISTP +NOASSERT +NOCLOSE +nohc +Nohc +nomalloc +nonoadjacent +noout +normalised +NSPE +NVIC +NXCONF +NXEC +NXENSURE +nxpese +NXPNCI +nxpnfcrdlib +NXPNFCRDLIB +NXPRT +NXSCP +Oadjacent +Obect +OBEX +occured +octat +Oftags +oliveri +Oliveri +onego +Oorschot +OOSEQ +OPTIM +OPTSA +ordern +OSCNT +ossl +otaexample +otamqttsuccess +otapalsuccess +OTFAD +Outgoung +outpubufferlength +Outx +overisght +paased +packetid +pake +PAKE +palpnprotos +papplet +parame +pareameters +pauth +pauthctx +pbits +pbkeylen +pbuff +pbuffer +pbufs +Pbufs +PBUFS +pcbs +PCCA +pccmdintprocesscommand +pccommand +pccommandinput +pccommandstring +pcdestination +pcertificatepath +pchannl +pchelpstring +pchip +pcks +PCKS +pclabelname +pclientcertlabel +pclientidentifier +pcmac +pcname +pcommandbuffer +pcommandbufferindex +pcommandcontext +pcommandtorelease +pcommandtosend +pconsoleinput +PCONTEXT +pcoutputbuffer +pcsc +PCSC +pcsclite +pcservercertificate +pctopic +pctopicfilter +pcurrpcb +pcurve +pcwritebuffer +pdata +pdecrypted +pdek +pderived +pdev +pdfalse +pdpass +PDRUNCFG +pdyn +penc +pencrypted +perclk +Perclk +PERCLK +Perfom +periph +Periph +PERIPH +periphmux +perso +Perso +PERSO +pestablishedconnection +pfilecontext +phash +phbal +PHESECID +PHESESTATUS +PHESESTBLOWER +PHESESTSHL +PHESESTVAL +PHESETYPES +phhal +PHHAL +phkdf +PHNXPESE +PHNXPESEPROTO +phost +phostname +phyksz +PICC +PINEL +pirng +pkha +PKHA +pkparse +pkwrite +plaform +Plaform +platf +Platf +PLATF +platfscp +PLATFSCP +plls +pmac +pmeth +pmethods +pmore +pmqttagentcontext +pmsg +pmsgctx +pnetworkcontext +pnetworkcredentials +pnxpese +pobj +PODF +portabilty +PORTSZ +poutnumestablishedconnections +poutnumtcpopenports +poutnumudpopenports +pouttcpportsarray +poutudpportsarray +poweron +ppassword +pprivatekeylabel +ppublishinfo +ppuc +ppvcontext +ppxidletaskstackbuffer +ppxtimertaskstackbuffer +prandom +preceivedcommand +Precitec +preperiph +presponse +prfx +primality +Primality +PRIVDEFENA +PRJECT +procedue +PROCTOCL +prootca +Proro +protocl +provisiong +PRSWL +PRTOL +prvgeneraterandombytes +prvgettimems +prvincomingpublish +prvkey +PRVKEY +prvupdatedeltacallback +prvupdaterejectedcallback +Psakey +pshared +Pskg +psslcontext +ptaskparam +ptun +pubuf +pucdata +puchash +pucmsg +pucpayload +pucrandom +pucreadbuffer +pucreceivebuffer +pucsig +Purnank +pval +pvarg +pvctx +pvincomingpublishcallbackcontext +pvmetricsreport +pvparam +pvparameters +pvportcalloc +pvportmalloc +pvrng +PWDN +pwer +pxbuffer +pxcerthandle +pxcertificate +pxcertificatecontext +pxcommand +pxcommandcontext +pxcommandinterpreter +pxcommandtoregister +pxctx +pxmqttcontext +pxnetworkcontext +pxnetworkrecv +pxnetworksend +pxnext +pxparams +pxpublishcallback +pxpublishinfo +pxreturninfo +pxsiglen +pxsubscriptioncontext +pxthread +pxtlscontext +Pxxx +PYHSICAL +qinv +QINV +Qxxx +ransceive +RAPDU +RASR +RBAR +rcon +RCON +rcrt +Rcrt +reacheable +READID +readsampleclksrc +reasing +reasonnable +receivetimeoutms +recevied +RECIEVE +recieved +Recieved +reco +RECO +recvmbox +RECVMBOX +refernce +referneced +remoteip +RENC +renego +RENEGO +Reponse +reponsed +requets +requiste +Requistie +resouces +resoures +Resynch +RESYNCH +resynchronished +retieved +Retreieve +retruend +retvak +REVOCERY +revovery +Rfbo +Rframe +RFRAME +RIHN +Rijmen +Rmac +RMAC +rnack +RNACK +RNAK +RNGA +rodata +roolback +rootca +ROOTCA +rootcasize +RROUND +rsaes +RSAES +rsassa +RSASSA +rsma +RSSN +RSTG +RWDS +RXBD +RXBUFF +RXEMPTY +Rxframe +rxlen +RXREADY +safly +sbox +SCARD +SCARDCONTEXT +SCARDHANDLE +SCCOM +SCCOMSERIAL +SCCOMSOCKET +Schwarz +SCII +SCIIC +sclk +SCLK +sclkpadsettingoverride +SCPO +SCPP +SCSPI +scsv +SCSV +sdcard +SDCARD +sdpv +SDRAMCR +S'ebastien +Sebd +SECG +SECK +SECO +secp +Secp +SECP +segger +Segger +seggerrtt +selectitvely +semc +Semc +SEMC +SENC +sendtimeoutms +seperate +seperatly +sepolicies +SEPRATOR +Seqs +serialclkfreq +servinfo +sesion +seucre +sflash +sflashpadtype +sframe +Sframe +SFRAME +shoudl +signining +signiture +signiutre +simulatenously +simulateously +simw +SIMW +Singature +sligtly +slotid +slve +SMAC +smbus +SMBUS +smcom +SMCOM +SMCOMJRCP +SMCOMPCSC +SMCOMPN +SMCOMSCI +SMCOMT +SNEP +sobj +sockapdu +Soll +spdif +Spdif +SPDIF +spdy +specifiedecdomain +SRMAC +SRST +srtp +SRTP +sscp +SSCP +sscpprop +SSLV +sssapisdll +sssapisw +ssse +sssftr +SSSFTR +stefano +Stefano +Storgae +STRCH +stringop +stringz +Structrues +strucute +strucutre +submoduled +subsciption +subsrcibed +succes +SUCCES +succesful +succesfull +succesfully +Successed +sucesseding +summands +symm +Symm +SYMM +symmkey +Synbolic +SYSCLK +SYSMPU +systme +sytem +Sytem +szbin +tansient +TCCKST +TCCKTS +tdes +TDES +tenenancy +Tera +Teraterm +thare +theoritical +theortical +timeoutinms +timeoutms +TLSC +TOKDNEEN +TOLERENCE +totoal +TPDU +tpkey +trainsient +transceive +Transceive +TRANSCEIVE +transcive +Transcive +transed +trng +TRNG +truely +TUNN +TXAK +TXBD +TXBUFF +TXCAL +txrx +TXRX +Uboot +uccount +UCOSII +UCOSIII +ucqos +ucrt +UDBL +udpated +UICC +UIDL +uihashlen +Uinquie +ulbytesreceived +ulbytessent +ulclienttoken +ulcurrentversion +ulevk +ulglobalentrytimems +ullocalipaddr +ulnextsubscribemessageid +ulnotification +ulnotificationvalue +ulnumpubsubtasks +ulpacketsreceived +ulpacketssent +ulrecievedtoken +ulremoteipaddr +ulservercertificatelength +ulsize +ulvaluelen +unaccelerated +Unallocate +Unblind +unblinded +Unblinding +unconf +Unconfigure +unefficiently +Unhexify +unitl +UNLCOK +unprotect +UNPROTECT +Unstall +uplayer +USART +Usbfs +Usbh +Usbhs +USBHS +USBHSD +USBHSH +Usbhsl +USBMPU +Usdhc +USDHC +uslocalport +usremoteport +ustopicfilterlength +UWBIOT +uxpriority +uxstacksize +valdidation +validiy +valus +vapplicationgetidletaskmemory +vapplicationgettimertaskmemory +varaibles +varibale +varifies +Vbat +VBAT +vccorlib +vccorlibd +vcom +Vcom +VCOM +VDIV +verbsity +Verfiication +Verfying +verif +VLAUE +vloggingprintf +vportfree +VREF +vsel +Vsel +VSEL +vsimplesubscribepublishtask +VTOR +WATSONP +wcrt +Wcrt +wctx +whan +Whle +WINRT +Withmbed +WITHOUTSEQN +WITHSEQN +WNCMD +WSADATA +wtls +WTLS +wuth +Xbar +xcleansession +xcryptcbc +xcryptecb +xecparams +xecpoint +Xevent +xhelpcommand +xlength +xmanageresubscription +xmbedsslconfig +xmbedsslctx +xmdalg +xmetricsreportlength +xmodulus +xnetworkrecv +xnetworksend +xored +xotapalresetdevice +xoutputbufferlen +xparameternumber +xpayloadlength +Xpfd +Xpresso +xprop +xpublicexponent +xpublickeytype +xqos +xrandomlength +xreadlength +xreceivelength +xresult +xreturn +xreturned +xreturnstatus +xsession +xstatetowait +xtal +Xtal +XTAL +XTALOSC +xtaskcreate +xtasknotify +xtea +XTEA +xtemplate +xthingnamelength +xtickstowait +xtlschandshakesuccessful +xtopicfilterlength +xtopiclength +xtra +xtrue +xwritebufferlen +yotta +YOTTA +zeroize +ZEROIZE +zvyed diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index fbab545..df81448 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -10,37 +10,18 @@ jobs: spell-check: runs-on: ubuntu-latest steps: - - name: Checkout Parent Repo - uses: actions/checkout@v2 - with: - ref: main - repository: FreeRTOS/CI-CD-Github-Actions - path: actions - name: Clone This Repo - uses: actions/checkout@v2 + uses: actions/checkout@v4 + - name: Run spellings check + uses: FreeRTOS/CI-CD-Github-Actions/spellings@main with: - ref: ${{ github.event.pull_request.head.sha }} - path: ./NXPRef - - name: Install spell - run: | - sudo apt-get install spell - sudo apt-get install util-linux - - name: Check spelling - run: | - PATH=$PATH:actions/spellings/tools - # Make sure that the portable directory is not included in the spellcheck. - sed -i "s/-iname \\\\\*.\[ch\] -o/-not -path \\\*Middleware\\\\\/NXP\\\* -iname \\\\\*.\[ch\] -o/g" actions/spellings/tools/find-unknown-comment-words - find-unknown-comment-words --directory NXPRef/ --lexicon NXPRef/lexicon.txt - if [ "$?" = "0" ]; then - exit 0 - else - exit 1 - fi + path: ./ + link-verifier: runs-on: ubuntu-latest steps: - name: Clone This Repo - uses: actions/checkout@v2 + uses: actions/checkout@v4 - name: Run link verifier uses: FreeRTOS/CI-CD-Github-Actions/link-verifier@main with: @@ -51,7 +32,7 @@ jobs: formatting: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: Install Uncrustify run: sudo apt-get install uncrustify - name: Run Uncrustify @@ -78,9 +59,9 @@ jobs: git-secrets: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: Checkout awslabs/git-secrets - uses: actions/checkout@v2 + uses: actions/checkout@v4 with: repository: awslabs/git-secrets ref: master @@ -91,3 +72,17 @@ jobs: run: | git-secrets --register-aws git-secrets --scan + + verify-manifest: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + submodules: true + fetch-depth: 0 + + - name: Run manifest verifier + uses: FreeRTOS/CI-CD-GitHub-Actions/manifest-verifier@main + with: + path: ./ + fail-on-incorrect-version: true \ No newline at end of file diff --git a/.gitmodules b/.gitmodules index 8ac0b83..ada8d8a 100644 --- a/.gitmodules +++ b/.gitmodules @@ -25,9 +25,6 @@ [submodule "Middleware/FreeRTOS/pkcs11"] path = Middleware/FreeRTOS/pkcs11 url = https://github.com/amazon-freertos/pkcs11.git -[submodule "Middleware/AWS/ota"] - path = Middleware/AWS/ota - url = https://github.com/aws/ota-for-aws-iot-embedded-sdk [submodule "Middleware/tinycbor"] path = Middleware/tinycbor url = https://github.com/intel/tinycbor.git @@ -49,3 +46,9 @@ [submodule "Middleware/FreeRTOS/tests"] path = Middleware/FreeRTOS/tests url = https://github.com/FreeRTOS/FreeRTOS-Libraries-Integration-Tests.git +[submodule "Middleware/AWS/mqtt-stream"] + path = Middleware/AWS/mqtt-stream + url = https://github.com/aws/aws-iot-core-mqtt-file-streams-embedded-c +[submodule "Middleware/AWS/jobs"] + path = Middleware/AWS/jobs + url = https://github.com/aws/Jobs-for-AWS-IoT-embedded-sdk.git diff --git a/.mcuxpressoide_packages_support/MIMXRT1062xxxxB_support/MIMXRT1060_dir_part.xml b/.mcuxpressoide_packages_support/MIMXRT1062xxxxB_support/MIMXRT1060_dir_part.xml new file mode 100644 index 0000000..b7735f3 --- /dev/null +++ b/.mcuxpressoide_packages_support/MIMXRT1062xxxxB_support/MIMXRT1060_dir_part.xml @@ -0,0 +1,10 @@ + + + + diff --git a/.mcuxpressoide_packages_support/MIMXRT1062xxxxB_support/MIMXRT1060_list.xml b/.mcuxpressoide_packages_support/MIMXRT1062xxxxB_support/MIMXRT1060_list.xml new file mode 100644 index 0000000..14ba535 --- /dev/null +++ b/.mcuxpressoide_packages_support/MIMXRT1062xxxxB_support/MIMXRT1060_list.xml @@ -0,0 +1,4 @@ + + + + diff --git a/.mcuxpressoide_packages_support/MIMXRT1062xxxxB_support/MIMXRT1062_internal.xml b/.mcuxpressoide_packages_support/MIMXRT1062xxxxB_support/MIMXRT1062_internal.xml new file mode 100644 index 0000000..53ad435 --- /dev/null +++ b/.mcuxpressoide_packages_support/MIMXRT1062xxxxB_support/MIMXRT1062_internal.xml @@ -0,0 +1,38 @@ + + + + + + MIMXRT1062xxxxB + MIMXRT1060 + NXP + + + + + + + + + Cortex-M7 + Cortex-M + + + diff --git a/.mcuxpressoide_packages_support/MIMXRT1062xxxxB_support/crt_directory.dtd b/.mcuxpressoide_packages_support/MIMXRT1062xxxxB_support/crt_directory.dtd new file mode 100644 index 0000000..1bf38a8 --- /dev/null +++ b/.mcuxpressoide_packages_support/MIMXRT1062xxxxB_support/crt_directory.dtd @@ -0,0 +1,88 @@ + + + + + + + + + + + + + + + + + diff --git a/.mcuxpressoide_packages_support/MIMXRT1062xxxxB_support/crt_infolist.dtd b/.mcuxpressoide_packages_support/MIMXRT1062xxxxB_support/crt_infolist.dtd new file mode 100644 index 0000000..396f962 --- /dev/null +++ b/.mcuxpressoide_packages_support/MIMXRT1062xxxxB_support/crt_infolist.dtd @@ -0,0 +1,279 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.mcuxpressoide_packages_support/MIMXRT1062xxxxB_support/info.properties b/.mcuxpressoide_packages_support/MIMXRT1062xxxxB_support/info.properties new file mode 100644 index 0000000..97b0b28 --- /dev/null +++ b/.mcuxpressoide_packages_support/MIMXRT1062xxxxB_support/info.properties @@ -0,0 +1,7 @@ +#MCUXpresso IDE part support +#Thu Feb 29 14:14:00 PST 2024 +sdk.id=SDK_2.x_MIMXRT1060-EVKB +sdk.build=801 2024-01-15 +device.version=1.0.0 +sdk.version=2.15.000 +device.id=MIMXRT1062xxxxB diff --git a/.mcuxpressoide_packages_support/crt_directory.dtd b/.mcuxpressoide_packages_support/crt_directory.dtd new file mode 100644 index 0000000..1bf38a8 --- /dev/null +++ b/.mcuxpressoide_packages_support/crt_directory.dtd @@ -0,0 +1,88 @@ + + + + + + + + + + + + + + + + + diff --git a/.mcuxpressoide_packages_support/crt_directory.xml b/.mcuxpressoide_packages_support/crt_directory.xml new file mode 100644 index 0000000..a0b9670 --- /dev/null +++ b/.mcuxpressoide_packages_support/crt_directory.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/.mcuxpressoide_packages_support/crt_infolist.dtd b/.mcuxpressoide_packages_support/crt_infolist.dtd new file mode 100644 index 0000000..396f962 --- /dev/null +++ b/.mcuxpressoide_packages_support/crt_infolist.dtd @@ -0,0 +1,279 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.mcuxpressoide_packages_support/info.properties b/.mcuxpressoide_packages_support/info.properties new file mode 100644 index 0000000..55d7b8d --- /dev/null +++ b/.mcuxpressoide_packages_support/info.properties @@ -0,0 +1,5 @@ +#MCUXpresso IDE +#Thu Feb 29 14:14:00 PST 2024 +product.name=MCUXpresso IDE v11.9.0 [Build 2144] [2024-01-05] +product.version=11.9.0 +product.build=2144 diff --git a/.mcuxpressoide_packages_support/readme.txt b/.mcuxpressoide_packages_support/readme.txt new file mode 100644 index 0000000..00460b7 --- /dev/null +++ b/.mcuxpressoide_packages_support/readme.txt @@ -0,0 +1,2 @@ +This folder is automatically created and contains the SDK part support for the IDE +*** DO NOT REMOVE OR MODIFY, YOUR CHANGES WILL BE OVERWRITTEN ON SDK REFRESH *** \ No newline at end of file diff --git a/GSG.md b/GSG.md index ba101d4..8f5d509 100644 --- a/GSG.md +++ b/GSG.md @@ -88,7 +88,7 @@ Many of these steps are automated in production environments. [Configuration basics](https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-quickstart.html) to configure the basic settings (security credentials, the default AWS output format and the default AWS Region) that AWS CLI uses to interact with AWS. -* A serial terminal application, such as [Tera Term](https://ttssh2.osdn.jp/index.html.en). +* A serial terminal application, such as [Tera Term](https://teratermproject.github.io/index-en.html). ## 2 Hardware and Software Setup @@ -312,10 +312,9 @@ Follow the steps below to set up an AWS account and provision the device: ![Image](https://user-images.githubusercontent.com/45887168/161142361-68eac8fa-8482-439d-bf90-e602cc5a28cd.png) -1. Copy the PEM certificate from the terminal console and save to a file. Log into your AWS account, go to the AWS IoT Console, choose "Secure", choose - "Certificates", and then choose "Create". Next to "Use my certificate" choose "Get started". On - "Select a CA" choose "Next". On "Register existing device certificates", choose "Select certificates" and - select the PEM file you just created. Select "Activate all" then choose "Register certificates". +1. Copy the PEM certificate from the terminal console and save to a file. Log into your AWS account, go to the AWS IoT Console, choose "Security", choose + "Certificates", and then click on the drop down "Add Certificate" and choose "Register Certificate". Choose "CA is not registered with AWS IoT" and + select the PEM file you just created. Select "Activate" then choose "Register". For more detailed instructions, see [Register a client certificate signed by an unregistered CA (console)](https://docs.aws.amazon.com/iot/latest/developerguide/manual-cert-registration.html#manual-cert-registration-console-noca). ![Image](https://user-images.githubusercontent.com/45887168/161153139-dae3151c-48f3-4d42-a47a-8f839777b425.png) @@ -480,7 +479,7 @@ perform OTA updates. 1. Import the code-signing certificate, private key, and certificate chain into the AWS Certificate Manager. ``` - aws acm import-certificate --certificate fileb://ecdsasigner.crt --private-key fileb://ecdsasigner.key + aws acm import-certificate --certificate fileb://ecdsasigner.crt --private-key fileb://ecdsasigner.key --region= ``` 1. Confirm the ARN for your certificate. You need this ARN when you create an OTA update job. @@ -865,4 +864,4 @@ For more information, `.\devicetester_win_x86-64.exe help` will show all availab When you run IDT, a `results/uuid` directory is generated that will contain all the logs and other information associated with your test run. This allows you to debug any failures. -*Note: Please run qualification test without provision mode (set appmainPROVISIONING_MODE to 0 in [app_main.c](./examples/evkbmimxrt1060/test/app_main.c)).* \ No newline at end of file +*Note: Please run qualification test without provision mode (set appmainPROVISIONING_MODE to 0 in [app_main.c](./examples/evkbmimxrt1060/test/app_main.c)).* diff --git a/Middleware/AWS/device-defender b/Middleware/AWS/device-defender index 9896700..7059e19 160000 --- a/Middleware/AWS/device-defender +++ b/Middleware/AWS/device-defender @@ -1 +1 @@ -Subproject commit 989670043d46dc104477957cdc0ce263218dae0a +Subproject commit 7059e199149a540471b484b710a51fc665636f22 diff --git a/Middleware/AWS/device-shadow b/Middleware/AWS/device-shadow index 250821f..268a5a2 160000 --- a/Middleware/AWS/device-shadow +++ b/Middleware/AWS/device-shadow @@ -1 +1 @@ -Subproject commit 250821f043d2d080547270b43f01d53c7d52640a +Subproject commit 268a5a276d3c3f451575b5a042b4e8ad53f134b6 diff --git a/Middleware/AWS/jobs b/Middleware/AWS/jobs new file mode 160000 index 0000000..3ce91f5 --- /dev/null +++ b/Middleware/AWS/jobs @@ -0,0 +1 @@ +Subproject commit 3ce91f56427653705891a8668568cb247b97905f diff --git a/Middleware/AWS/mqtt-stream b/Middleware/AWS/mqtt-stream new file mode 160000 index 0000000..05ff5dc --- /dev/null +++ b/Middleware/AWS/mqtt-stream @@ -0,0 +1 @@ +Subproject commit 05ff5dc55a8591360664557f78ae1d71d696d201 diff --git a/Middleware/AWS/ota b/Middleware/AWS/ota deleted file mode 160000 index f976089..0000000 --- a/Middleware/AWS/ota +++ /dev/null @@ -1 +0,0 @@ -Subproject commit f9760892ba152f2c9104d08192ea5ffbbf9fa8ea diff --git a/Middleware/FreeRTOS/backoffAlgorithm b/Middleware/FreeRTOS/backoffAlgorithm index 8818bed..3cc0bf8 160000 --- a/Middleware/FreeRTOS/backoffAlgorithm +++ b/Middleware/FreeRTOS/backoffAlgorithm @@ -1 +1 @@ -Subproject commit 8818bed40e57215fda8efa4b7fd33f7ae2c80d65 +Subproject commit 3cc0bf8c4d41d7cd7aa2f1ded5075c87bf6b2bbb diff --git a/Middleware/FreeRTOS/coreJSON b/Middleware/FreeRTOS/coreJSON index 5b31f4c..e3b7663 160000 --- a/Middleware/FreeRTOS/coreJSON +++ b/Middleware/FreeRTOS/coreJSON @@ -1 +1 @@ -Subproject commit 5b31f4c37a034911a4992fd415f8177a75014946 +Subproject commit e3b7663f6392d8c10e8db57506ec37e4801b145a diff --git a/Middleware/FreeRTOS/coreMQTT b/Middleware/FreeRTOS/coreMQTT index 6d5641b..3f4cedc 160000 --- a/Middleware/FreeRTOS/coreMQTT +++ b/Middleware/FreeRTOS/coreMQTT @@ -1 +1 @@ -Subproject commit 6d5641b8a2f410470134d9bfe8ee71e3d83a565e +Subproject commit 3f4cedc1ad027d76b2f00c2f83481b212b7a8632 diff --git a/Middleware/FreeRTOS/corePKCS11 b/Middleware/FreeRTOS/corePKCS11 index 781f577..a923b21 160000 --- a/Middleware/FreeRTOS/corePKCS11 +++ b/Middleware/FreeRTOS/corePKCS11 @@ -1 +1 @@ -Subproject commit 781f5774948fa8e6427be544b1bf1ad512ae9e90 +Subproject commit a923b213d33c6538e92ba3c7971b2d859f881afb diff --git a/Middleware/FreeRTOS/kernel b/Middleware/FreeRTOS/kernel index def7d2d..dbf7055 160000 --- a/Middleware/FreeRTOS/kernel +++ b/Middleware/FreeRTOS/kernel @@ -1 +1 @@ -Subproject commit def7d2df2b0506d3d249334974f51e427c17a41c +Subproject commit dbf70559b27d39c1fdb68dfb9a32140b6a6777a0 diff --git a/Middleware/FreeRTOS/lwip_osal/src/sys_arch.c b/Middleware/FreeRTOS/lwip_osal/src/sys_arch.c index 0ad48d4..aabeb1e 100644 --- a/Middleware/FreeRTOS/lwip_osal/src/sys_arch.c +++ b/Middleware/FreeRTOS/lwip_osal/src/sys_arch.c @@ -62,7 +62,7 @@ #include "core_pkcs11.h" #ifndef errno -int errno = 0; +volatile int errno = 0; #endif /* diff --git a/Middleware/FreeRTOS/mqtt-agent-interface/freertos_command_pool.c b/Middleware/FreeRTOS/mqtt-agent-interface/freertos_command_pool.c index 584b508..7e97cf3 100644 --- a/Middleware/FreeRTOS/mqtt-agent-interface/freertos_command_pool.c +++ b/Middleware/FreeRTOS/mqtt-agent-interface/freertos_command_pool.c @@ -37,6 +37,9 @@ #include "FreeRTOS.h" #include "semphr.h" +/* Demo Specific configs. */ +#include "core_mqtt_config.h" + /* Header include. */ #include "freertos_command_pool.h" #include "freertos_agent_message.h" diff --git a/Middleware/FreeRTOS/tests b/Middleware/FreeRTOS/tests index 4ec8241..692d509 160000 --- a/Middleware/FreeRTOS/tests +++ b/Middleware/FreeRTOS/tests @@ -1 +1 @@ -Subproject commit 4ec8241acf2beede601d230f9bd51636df60e240 +Subproject commit 692d509221b7f71d42551ed6c7b8a524b039a44f diff --git a/cspell.config.yaml b/cspell.config.yaml new file mode 100644 index 0000000..d0b90eb --- /dev/null +++ b/cspell.config.yaml @@ -0,0 +1,32 @@ +--- +$schema: https://raw.githubusercontent.com/streetsidesoftware/cspell/main/cspell.schema.json +version: '0.2' +# Allows things like stringLength +allowCompoundWords: true + +# Read files not to spell check from the git ignore +useGitignore: true + +# Language settings for C +languageSettings: + - caseSensitive: false + enabled: true + languageId: c + locale: "*" + +# Add a dictionary, and the path to the word list +dictionaryDefinitions: + - name: freertos-words + path: '.github/.cSpellWords.txt' + addWords: true + +dictionaries: + - freertos-words + +# Paths and files to ignore +ignorePaths: + - 'dependency' + - 'docs' + - 'ThirdParty' + - 'History.txt' + - './Middleware/NXP/hostLib/mbedtls' diff --git a/examples/common/mqtt_agent/mqtt_agent_task.c b/examples/common/mqtt_agent/mqtt_agent_task.c index 3729ec1..999c7e3 100644 --- a/examples/common/mqtt_agent/mqtt_agent_task.c +++ b/examples/common/mqtt_agent/mqtt_agent_task.c @@ -66,6 +66,8 @@ #include "core_pkcs11_config.h" +#include "core_mqtt_config.h" + /* MQTT library includes. */ #include "core_mqtt.h" @@ -88,6 +90,12 @@ /* Includes MQTT Agent Task management APIs. */ #include "mqtt_agent_task.h" +/* Includes MQTT wrapper used in the OTA demo. */ +#include "mqtt_wrapper.h" + +/* Include required to pass unsolicited publishes to the OTA demo. */ +#include "ota_demo.h" + /** * @brief Dimensions the buffer used to serialize and deserialize MQTT packets. * @note Specified in bytes. Must be large enough to hold the maximum @@ -108,26 +116,26 @@ * @brief Timeout for receiving CONNACK after sending an MQTT CONNECT packet. * Defined in milliseconds. */ -#define mqttexampleCONNACK_RECV_TIMEOUT_MS ( 2000U ) +#define mqttexampleCONNACK_RECV_TIMEOUT_MS ( 2000U ) /** * @brief The maximum number of retries for network operation with server. * The configuration is set to retry forever. MQTT agent will retry in an infinite loop until * its connected to broker. */ -#define RETRY_MAX_ATTEMPTS ( BACKOFF_ALGORITHM_RETRY_FOREVER ) +#define RETRY_MAX_ATTEMPTS ( BACKOFF_ALGORITHM_RETRY_FOREVER ) /** * @brief The maximum back-off delay (in milliseconds) for retrying failed operation * with server. */ -#define RETRY_MAX_BACKOFF_DELAY_MS ( 5000U ) +#define RETRY_MAX_BACKOFF_DELAY_MS ( 5000U ) /** * @brief The base back-off delay (in milliseconds) to use for network operation retry * attempts. */ -#define RETRY_BACKOFF_BASE_MS ( 500U ) +#define RETRY_BACKOFF_BASE_MS ( 500U ) /** * @brief The maximum time interval in seconds which is allowed to elapse @@ -138,12 +146,13 @@ * absence of sending any other Control Packets, the Client MUST send a * PINGREQ Packet. *//*_RB_ Move to be the responsibility of the agent. */ -#define mqttexampleKEEP_ALIVE_INTERVAL_SECONDS ( 60U ) +#define mqttexampleKEEP_ALIVE_INTERVAL_SECONDS ( 60U ) /** * @brief Socket send and receive timeouts to use. Specified in milliseconds. */ -#define mqttexampleTRANSPORT_SEND_RECV_TIMEOUT_MS ( 750 ) +#define mqttexampleTRANSPORT_SEND_TIMEOUT_MS ( 750 ) +#define mqttexampleTRANSPORT_RECV_TIMEOUT_MS ( 0 ) /** * @brief Configuration is used to turn on or off persistent sessions with MQTT broker. @@ -152,19 +161,19 @@ * will be stored by the broker and resend to device, when it comes back online. * */ -#define mqttexamplePERSISTENT_SESSION_REQUIRED ( 0 ) +#define mqttexamplePERSISTENT_SESSION_REQUIRED ( 0 ) /** * @brief Used to convert times to/from ticks and milliseconds. */ -#define mqttexampleMILLISECONDS_PER_SECOND ( 1000U ) -#define mqttexampleMILLISECONDS_PER_TICK ( mqttexampleMILLISECONDS_PER_SECOND / configTICK_RATE_HZ ) +#define mqttexampleMILLISECONDS_PER_SECOND ( 1000U ) +#define mqttexampleMILLISECONDS_PER_TICK ( mqttexampleMILLISECONDS_PER_SECOND / configTICK_RATE_HZ ) /** * @brief The MQTT agent manages the MQTT contexts. This set the handle to the * context used by this demo. */ -#define mqttexampleMQTT_CONTEXT_HANDLE ( ( MQTTContextHandle_t ) 0 ) +#define mqttexampleMQTT_CONTEXT_HANDLE ( ( MQTTContextHandle_t ) 0 ) /** * @brief Event Bit corresponding to an MQTT agent state. @@ -180,6 +189,8 @@ */ #define mqttexampleEVENT_BITS_ALL ( ( EventBits_t ) ( ( 1ULL << MQTT_AGENT_NUM_STATES ) - 1U ) ) + +#define MQTT_AGENT_NOTIFY_IDX ( 3U ) /*-----------------------------------------------------------*/ /** @@ -584,8 +595,8 @@ static BaseType_t prvCreateTLSConnection( NetworkContext_t * pxNetworkContext ) pcBrokerEndpoint, ulBrokerPort, &xNetworkCredentials, - mqttexampleTRANSPORT_SEND_RECV_TIMEOUT_MS, - mqttexampleTRANSPORT_SEND_RECV_TIMEOUT_MS ); + mqttexampleTRANSPORT_RECV_TIMEOUT_MS, + mqttexampleTRANSPORT_SEND_TIMEOUT_MS ); if( xNetworkStatus == TLS_TRANSPORT_SUCCESS ) { @@ -729,13 +740,21 @@ static void prvIncomingPublishCallback( MQTTAgentContext_t * pMqttAgentContext, * handle it as an unsolicited publish. */ if( xPublishHandled != true ) { - /* Ensure the topic string is terminated for printing. This will over- - * write the message ID, which is restored afterwards. */ - pcLocation = ( char * ) &( pxPublishInfo->pTopicName[ pxPublishInfo->topicNameLength ] ); - cOriginalChar = *pcLocation; - *pcLocation = 0x00; - LogWarn( ( "WARN: Received an unsolicited publish from topic %s", pxPublishInfo->pTopicName ) ); - *pcLocation = cOriginalChar; + xPublishHandled = otaDemo_handleIncomingMQTTMessage( pxPublishInfo->pTopicName, + pxPublishInfo->topicNameLength, + pxPublishInfo->pPayload, + pxPublishInfo->payloadLength ); + + if( xPublishHandled != true ) + { + /* Ensure the topic string is terminated for printing. This will over- + * write the message ID, which is restored afterwards. */ + pcLocation = ( char * ) &( pxPublishInfo->pTopicName[ pxPublishInfo->topicNameLength ] ); + cOriginalChar = *pcLocation; + *pcLocation = 0x00; + LogWarn( ( "WARN: Received an unsolicited publish from topic %s", pxPublishInfo->pTopicName ) ); + *pcLocation = cOriginalChar; + } } } @@ -760,6 +779,14 @@ static char * prvKVStoreGetString( KVStoreKey_t xKey ) return pcValue; } + +/*-----------------------------------------------------------*/ + +MQTTAgentContext_t * xGetMqttAgentHandle( void ) +{ + return &xGlobalMqttAgentContext; +} + /*-----------------------------------------------------------*/ void prvMQTTAgentTask( void * pvParameters ) @@ -842,6 +869,10 @@ void prvMQTTAgentTask( void * pvParameters ) * which could be a disconnect. If an error occurs the MQTT context on * which the error happened is returned so there is an attempt to * clean up and reconnect. */ + + /* Set the MQTT context to be used by the MQTT wrapper. */ + mqttWrapper_setCoreMqttContext( &( xGlobalMqttAgentContext.mqttContext ) ); + prvSetMQTTAgentState( MQTT_AGENT_STATE_CONNECTED ); xMQTTStatus = MQTTAgent_CommandLoop( &xGlobalMqttAgentContext ); @@ -1033,6 +1064,31 @@ static void prvSetMQTTAgentState( MQTTAgentState_t xAgentState ) /*-----------------------------------------------------------*/ +static void prvSubscribeRqCallback( MQTTAgentCommandContext_t * pxCommandContext, + MQTTAgentReturnInfo_t * pxReturnInfo ) +{ + TaskHandle_t xTaskHandle = ( struct tskTaskControlBlock * ) pxCommandContext; + + configASSERT( pxReturnInfo ); + + if( xTaskHandle != NULL ) + { + uint32_t ulNotifyValue = ( pxReturnInfo->returnCode & 0xFFFFFF ); + + if( pxReturnInfo->pSubackCodes ) + { + ulNotifyValue += ( pxReturnInfo->pSubackCodes[ 0 ] << 24 ); + } + + ( void ) xTaskNotifyIndexed( xTaskHandle, + MQTT_AGENT_NOTIFY_IDX, + ulNotifyValue, + eSetValueWithOverwrite ); + } +} + +/*-----------------------------------------------------------*/ + BaseType_t xMQTTAgentInit( configSTACK_DEPTH_TYPE uxStackSize, UBaseType_t uxPriority ) { @@ -1177,3 +1233,69 @@ void vRemoveMQTTTopicFilterCallback( const char * pcTopicFilter, } xSemaphoreGive( xSubscriptionsMutex ); } + +MQTTStatus_t MqttAgent_SubscribeSync( const char * pcTopicFilter, + uint16_t uxTopicFilterLength, + MQTTQoS_t xRequestedQoS, + IncomingPubCallback_t pxCallback, + void * pvCallbackCtx ) +{ + BaseType_t xMQTTCallbackAdded; + MQTTStatus_t xResult; + + xMQTTCallbackAdded = xAddMQTTTopicFilterCallback( pcTopicFilter, + uxTopicFilterLength, + pxCallback, + pvCallbackCtx, + pdFALSE ); + + if( xMQTTCallbackAdded == pdTRUE ) + { + MQTTSubscribeInfo_t xSubInfo = + { + .qos = xRequestedQoS, + .pTopicFilter = pcTopicFilter, + .topicFilterLength = uxTopicFilterLength + }; + + MQTTAgentSubscribeArgs_t xSubArgs = + { + .pSubscribeInfo = &xSubInfo, + .numSubscriptions = 1 + }; + + /* The block time can be 0 as the command loop is not running at this point. */ + MQTTAgentCommandInfo_t xCommandParams = + { + .blockTimeMs = portMAX_DELAY, + .cmdCompleteCallback = prvSubscribeRqCallback, + .pCmdCompleteCallbackContext = ( void * ) ( xTaskGetCurrentTaskHandle() ) + }; + + ( void ) xTaskNotifyStateClearIndexed( NULL, MQTT_AGENT_NOTIFY_IDX ); + + /* Enqueue subscribe to the command queue. These commands will be processed only + * when command loop starts. */ + xResult = MQTTAgent_Subscribe( &xGlobalMqttAgentContext, &xSubArgs, &xCommandParams ); + + if( xResult == MQTTSuccess ) + { + uint32_t ulNotifyValue = 0; + + if( xTaskNotifyWaitIndexed( MQTT_AGENT_NOTIFY_IDX, + 0x0, + 0xFFFFFFFF, + &ulNotifyValue, + portMAX_DELAY ) ) + { + xResult = ( ulNotifyValue & 0x00FFFFFF ); + } + else + { + xResult = MQTTKeepAliveTimeout; + } + } + } + + return 0; +} diff --git a/examples/common/mqtt_agent/mqtt_agent_task.h b/examples/common/mqtt_agent/mqtt_agent_task.h index 0530388..160638e 100644 --- a/examples/common/mqtt_agent/mqtt_agent_task.h +++ b/examples/common/mqtt_agent/mqtt_agent_task.h @@ -127,4 +127,12 @@ void vRemoveMQTTTopicFilterCallback( const char * pcTopicFilter, uint16_t usTopicFilterLength ); +MQTTAgentContext_t * xGetMqttAgentHandle( void ); + +MQTTStatus_t MqttAgent_SubscribeSync( const char * pcTopicFilter, + uint16_t uxTopicFilterLength, + MQTTQoS_t xRequestedQoS, + IncomingPubCallback_t pxCallback, + void * pvCallbackCtx ); + #endif /* ifndef _MQTT_AGENT_TASK_H_ */ diff --git a/examples/common/mqtt_wrapper/mqtt_wrapper.c b/examples/common/mqtt_wrapper/mqtt_wrapper.c new file mode 100644 index 0000000..ae78fef --- /dev/null +++ b/examples/common/mqtt_wrapper/mqtt_wrapper.c @@ -0,0 +1,249 @@ +/* + * Copyright Amazon.com, Inc. and its affiliates. All Rights Reserved. + * SPDX-License-Identifier: MIT + * + * Licensed under the MIT License. See the LICENSE accompanying this file + * for the specific language governing permissions and limitations under + * the License. + */ + +#include +#include + +#include "mqtt_wrapper.h" +#include "ota_demo.h" + +#define MQTT_AGENT_NOTIFY_IDX ( 2 ) + +static MQTTContext_t * globalCoreMqttContext = NULL; + +#define MAX_THING_NAME_SIZE 128U +static char globalThingName[ MAX_THING_NAME_SIZE + 1 ]; +static size_t globalThingNameLength = 0U; + +/** + * @brief Defines the structure to use as the command callback context in this + * demo. + */ +struct MQTTAgentCommandContext +{ + MQTTStatus_t xReturnStatus; + TaskHandle_t xTaskToNotify; +}; + +static void handleIncomingMQTTMessage( char * topic, + size_t topicLength, + uint8_t * message, + size_t messageLength ) + +{ + bool messageHandled = otaDemo_handleIncomingMQTTMessage( topic, + topicLength, + message, + messageLength ); + + if( !messageHandled ) + { + printf( "Unhandled incoming PUBLISH received on topic, message: " + "%.*s\n%.*s\n", + ( unsigned int ) topicLength, + topic, + ( unsigned int ) messageLength, + ( char * ) message ); + } +} + +void mqttWrapper_setCoreMqttContext( MQTTContext_t * mqttContext ) +{ + globalCoreMqttContext = mqttContext; +} + +MQTTContext_t * mqttWrapper_getCoreMqttContext( void ) +{ + assert( globalCoreMqttContext != NULL ); + return globalCoreMqttContext; +} + +void mqttWrapper_setThingName( char * thingName, + size_t thingNameLength ) +{ + assert( thingNameLength <= MAX_THING_NAME_SIZE ); + strncpy( globalThingName, thingName, MAX_THING_NAME_SIZE ); + globalThingNameLength = thingNameLength; +} + +void mqttWrapper_getThingName( char * thingNameBuffer, + size_t * thingNameLength ) +{ + assert( globalThingName[ 0 ] != 0 ); + + memcpy( thingNameBuffer, globalThingName, globalThingNameLength ); + thingNameBuffer[ globalThingNameLength ] = '\0'; + *thingNameLength = globalThingNameLength; +} + +bool mqttWrapper_connect( char * thingName, + size_t thingNameLength ) +{ + MQTTConnectInfo_t connectInfo = { 0 }; + MQTTStatus_t mqttStatus = MQTTSuccess; + bool sessionPresent = false; + + assert( globalCoreMqttContext != NULL ); + + connectInfo.pClientIdentifier = thingName; + connectInfo.clientIdentifierLength = thingNameLength; + connectInfo.pUserName = NULL; + connectInfo.userNameLength = 0U; + connectInfo.pPassword = NULL; + connectInfo.passwordLength = 0U; + connectInfo.keepAliveSeconds = 60U; + connectInfo.cleanSession = true; + mqttStatus = MQTT_Connect( globalCoreMqttContext, + &connectInfo, + NULL, + 5000U, + &sessionPresent ); + return mqttStatus == MQTTSuccess; +} + +bool mqttWrapper_isConnected( void ) +{ + bool isConnected = false; + + assert( globalCoreMqttContext != NULL ); + isConnected = globalCoreMqttContext->connectStatus == MQTTConnected; + return isConnected; +} + +static void prvPublishCommandCallback( MQTTAgentCommandContext_t * pCmdCallbackContext, + MQTTAgentReturnInfo_t * pReturnInfo ) +{ + TaskHandle_t xTaskHandle = ( struct tskTaskControlBlock * ) pCmdCallbackContext->xTaskToNotify; + + + if( xTaskHandle != NULL ) + { + uint32_t ulNotifyValue = MQTTSuccess; /* ( pxReturnInfo->returnCode & 0xFFFFFF ); */ +/* */ +/* if( pxReturnInfo->pSubackCodes ) */ +/* { */ +/* ulNotifyValue += ( pxReturnInfo->pSubackCodes[ 0 ] << 24 ); */ +/* } */ + + ( void ) xTaskNotifyIndexed( xTaskHandle, + MQTT_AGENT_NOTIFY_IDX, + ulNotifyValue, + eSetValueWithOverwrite ); + } +} + +bool mqttWrapper_publish( char * topic, + size_t topicLength, + uint8_t * message, + size_t messageLength ) +{ + bool success = false; + + assert( globalCoreMqttContext != NULL ); + + success = mqttWrapper_isConnected(); + + if( success ) + { + MQTTStatus_t mqttStatus = MQTTSuccess; + /* TODO: This should be static or should we wait? */ + static MQTTPublishInfo_t pubInfo = { 0 }; + MQTTAgentContext_t * xAgentHandle = xGetMqttAgentHandle(); + pubInfo.qos = 0; + pubInfo.retain = false; + pubInfo.dup = false; + pubInfo.pTopicName = topic; + pubInfo.topicNameLength = topicLength; + pubInfo.pPayload = message; + pubInfo.payloadLength = messageLength; + + MQTTAgentCommandContext_t xCommandContext = + { + .xTaskToNotify = xTaskGetCurrentTaskHandle(), + .xReturnStatus = MQTTIllegalState, + }; + + MQTTAgentCommandInfo_t xCommandParams = + { + .blockTimeMs = 1000, + .cmdCompleteCallback = prvPublishCommandCallback, + .pCmdCompleteCallbackContext = &xCommandContext, + }; + + ( void ) xTaskNotifyStateClearIndexed( NULL, MQTT_AGENT_NOTIFY_IDX ); + + mqttStatus = MQTTAgent_Publish( xAgentHandle, + &pubInfo, + &xCommandParams ); + + if( mqttStatus == MQTTSuccess ) + { + uint32_t ulNotifyValue = 0; + + if( xTaskNotifyWaitIndexed( MQTT_AGENT_NOTIFY_IDX, + 0x0, + 0xFFFFFFFF, + &ulNotifyValue, + portMAX_DELAY ) ) + { + mqttStatus = ( ulNotifyValue & 0x00FFFFFF ); + } + else + { + mqttStatus = MQTTKeepAliveTimeout; + } + } + + success = mqttStatus == MQTTSuccess; + } + + return success; +} + +void handleIncomingPublish( void * pvIncomingPublishCallbackContext, + MQTTPublishInfo_t * pxPublishInfo ) +{ + char * topic = NULL; + size_t topicLength = 0U; + uint8_t * message = NULL; + size_t messageLength = 0U; + + topic = ( char * ) pxPublishInfo->pTopicName; + topicLength = pxPublishInfo->topicNameLength; + message = ( uint8_t * ) pxPublishInfo->pPayload; + messageLength = pxPublishInfo->payloadLength; + handleIncomingMQTTMessage( topic, topicLength, message, messageLength ); +} + +bool mqttWrapper_subscribe( char * topic, + size_t topicLength ) +{ + bool success = false; + + assert( globalCoreMqttContext != NULL ); + + success = mqttWrapper_isConnected(); + + if( success ) + { + MQTTStatus_t mqttStatus = MQTTSuccess; + + mqttStatus = MqttAgent_SubscribeSync( topic, + topicLength, + 0, + handleIncomingPublish, + NULL ); + + configASSERT( mqttStatus == MQTTSuccess ); + + success = mqttStatus == MQTTSuccess; + } + + return success; +} diff --git a/examples/common/mqtt_wrapper/mqtt_wrapper.h b/examples/common/mqtt_wrapper/mqtt_wrapper.h new file mode 100644 index 0000000..8d0ed33 --- /dev/null +++ b/examples/common/mqtt_wrapper/mqtt_wrapper.h @@ -0,0 +1,43 @@ +/* + * Copyright Amazon.com, Inc. and its affiliates. All Rights Reserved. + * SPDX-License-Identifier: MIT + * + * Licensed under the MIT License. See the LICENSE accompanying this file + * for the specific language governing permissions and limitations under + * the License. + */ + +#ifndef MQTT_WRAPPER_H +#define MQTT_WRAPPER_H + +#include "FreeRTOS.h" +#include "task.h" + +#include "core_mqtt.h" +#include "core_mqtt_agent.h" +#include "mqtt_agent_task.h" + +void mqttWrapper_setCoreMqttContext( MQTTContext_t * mqttContext ); + +MQTTContext_t * mqttWrapper_getCoreMqttContext( void ); + +void mqttWrapper_setThingName( char * thingName, + size_t thingNameLength ); + +void mqttWrapper_getThingName( char * thingNameBuffer, + size_t * thingNameLength ); + +bool mqttWrapper_connect( char * thingName, + size_t thingNameLength ); + +bool mqttWrapper_isConnected( void ); + +bool mqttWrapper_publish( char * topic, + size_t topicLength, + uint8_t * message, + size_t messageLength ); + +bool mqttWrapper_subscribe( char * topic, + size_t topicLength ); + +#endif /* ifndef MQTT_WRAPPER_H */ diff --git a/examples/common/ota/ota_demo.h b/examples/common/ota/ota_demo.h new file mode 100644 index 0000000..80f8438 --- /dev/null +++ b/examples/common/ota/ota_demo.h @@ -0,0 +1,133 @@ +/* + * Copyright Amazon.com, Inc. and its affiliates. All Rights Reserved. + * SPDX-License-Identifier: MIT + * + * Licensed under the MIT License. See the LICENSE accompanying this file + * for the specific language governing permissions and limitations under + * the License. + */ + +#ifndef OTA_DEMO_H +#define OTA_DEMO_H + +#include +#include + +#include "MQTTFileDownloader.h" +#include "MQTTFileDownloader_defaults.h" + +#define OTA_DATA_BLOCK_SIZE mqttFileDownloader_CONFIG_BLOCK_SIZE +#define JOB_DOC_SIZE 2048U + +typedef enum OtaEvent +{ + OtaAgentEventStart = 0, /*!< @brief Start the OTA state machine */ + OtaAgentEventRequestJobDocument, /*!< @brief Event for requesting job document. */ + OtaAgentEventReceivedJobDocument, /*!< @brief Event when job document is received. */ + OtaAgentEventCreateFile, /*!< @brief Event to create a file. */ + OtaAgentEventRequestFileBlock, /*!< @brief Event to request file blocks. */ + OtaAgentEventReceivedFileBlock, /*!< @brief Event to trigger when file block is received. */ + OtaAgentEventCloseFile, /*!< @brief Event to trigger closing file. */ + OtaAgentEventActivateImage, /*!< @brief Event to activate the new image. */ + OtaAgentEventSuspend, /*!< @brief Event to suspend ota task */ + OtaAgentEventResume, /*!< @brief Event to resume suspended task */ + OtaAgentEventUserAbort, /*!< @brief Event triggered by user to stop agent. */ + OtaAgentEventShutdown, /*!< @brief Event to trigger ota shutdown */ + OtaAgentEventMax /*!< @brief Last event specifier */ +} OtaEvent_t; + +/** + * @brief OTA Agent states. + * + * The current state of the OTA Task (OTA Agent). + */ +typedef enum OtaState +{ + OtaAgentStateNoTransition = -1, + OtaAgentStateInit = 0, + OtaAgentStateReady, + OtaAgentStateRequestingJob, + OtaAgentStateWaitingForJob, + OtaAgentStateCreatingFile, + OtaAgentStateRequestingFileBlock, + OtaAgentStateWaitingForFileBlock, + OtaAgentStateClosingFile, + OtaAgentStateSuspended, + OtaAgentStateShuttingDown, + OtaAgentStateStopped, + OtaAgentStateAll +} OtaState_t; + +/** + * @brief The OTA Agent event and data structures. + */ + +typedef struct OtaDataEvent +{ + uint8_t data[ OTA_DATA_BLOCK_SIZE * 2 ]; /*!< Buffer for storing event information. */ + size_t dataLength; /*!< Total space required for the event. */ + bool bufferUsed; /*!< Flag set when buffer is used otherwise cleared. */ +} OtaDataEvent_t; + +typedef struct OtaJobEventData +{ + uint8_t jobData[ JOB_DOC_SIZE ]; + size_t jobDataLength; +} OtaJobEventData_t; + +/** + * @brief Application version structure. + * + */ +typedef struct +{ + /* MISRA Ref 19.2.1 [Unions] */ + /* More details at: https://github.com/aws/ota-for-aws-iot-embedded-sdk/blob/main/MISRA.md#rule-192 */ + /* coverity[misra_c_2012_rule_19_2_violation] */ + union + { +#if ( defined( __BYTE_ORDER__ ) && defined( __ORDER_LITTLE_ENDIAN__ ) && ( __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ ) ) || ( __little_endian__ == 1 ) || WIN32 || ( __BYTE_ORDER == __LITTLE_ENDIAN ) + struct version + { + uint16_t build; /*!< @brief Build of the firmware (Z in firmware version Z.Y.X). */ + uint8_t minor; /*!< @brief Minor version number of the firmware (Y in firmware version Z.Y.X). */ + + uint8_t major; /*!< @brief Major version number of the firmware (X in firmware version Z.Y.X). */ + } x; /*!< @brief Version number of the firmware. */ +#elif ( defined( __BYTE_ORDER__ ) && defined( __ORDER_BIG_ENDIAN__ ) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ ) || ( __big_endian__ == 1 ) || ( __BYTE_ORDER == __BIG_ENDIAN ) + struct version + { + uint8_t major; /*!< @brief Major version number of the firmware (X in firmware version X.Y.Z). */ + uint8_t minor; /*!< @brief Minor version number of the firmware (Y in firmware version X.Y.Z). */ + + uint16_t build; /*!< @brief Build of the firmware (Z in firmware version X.Y.Z). */ + } x; /*!< @brief Version number of the firmware. */ +#else /* if ( defined( __BYTE_ORDER__ ) && defined( __ORDER_LITTLE_ENDIAN__ ) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ ) || ( __little_endian__ == 1 ) || WIN32 || ( __BYTE_ORDER == __LITTLE_ENDIAN ) */ +#error "Unable to determine byte order!" +#endif /* if ( defined( __BYTE_ORDER__ ) && defined( __ORDER_LITTLE_ENDIAN__ ) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ ) || ( __little_endian__ == 1 ) || WIN32 || ( __BYTE_ORDER == __LITTLE_ENDIAN ) */ + uint32_t unsignedVersion32; + int32_t signedVersion32; + } u; /*!< @brief Version based on configuration in big endian or little endian. */ +} AppVersion32_t; + +/** + * @brief Stores information about the event message. + * + */ +typedef struct OtaEventMsg +{ + OtaDataEvent_t * dataEvent; /*!< Data Event message. */ + OtaJobEventData_t * jobEvent; /*!< Job Event message. */ + OtaEvent_t eventId; /*!< Identifier for the event. */ +} OtaEventMsg_t; + + +void otaDemo_start( void ); + +bool otaDemo_handleIncomingMQTTMessage( char * topic, + size_t topicLength, + uint8_t * message, + size_t messageLength ); + +OtaState_t getOtaAgentState(); +#endif /* ifndef OTA_DEMO_H */ diff --git a/examples/common/ota/ota_os/ota_os_freertos.c b/examples/common/ota/ota_os/ota_os_freertos.c new file mode 100644 index 0000000..75fe9c4 --- /dev/null +++ b/examples/common/ota/ota_os/ota_os_freertos.c @@ -0,0 +1,120 @@ +/* + * Copyright Amazon.com, Inc. and its affiliates. All Rights Reserved. + * SPDX-License-Identifier: MIT + * + * Licensed under the MIT License. See the LICENSE accompanying this file + * for the specific language governing permissions and limitations under + * the License. + */ + +/** + * @file ota_os_freertos.c + * @brief Example implementation of the OTA OS Functional Interface for + * FreeRTOS. + */ + +/* FreeRTOS includes. */ +#include "FreeRTOS.h" +#include "queue.h" +#include "timers.h" + +/* OTA OS POSIX Interface Includes.*/ + +#include "ota_demo.h" +#include "ota_os_freertos.h" + +/* OTA Event queue attributes.*/ +#define MAX_MESSAGES 20 +#define MAX_MSG_SIZE sizeof( OtaEventMsg_t ) + +/* Array containing pointer to the OTA event structures used to send events to + * the OTA task. */ +static OtaEventMsg_t queueData[ MAX_MESSAGES * MAX_MSG_SIZE ]; + +/* The queue control structure. .*/ +static StaticQueue_t staticQueue; + +/* The queue control handle. .*/ +static QueueHandle_t otaEventQueue; + +OtaOsStatus_t OtaInitEvent_FreeRTOS() +{ + OtaOsStatus_t otaOsStatus = OtaOsSuccess; + + otaEventQueue = xQueueCreateStatic( ( UBaseType_t ) MAX_MESSAGES, + ( UBaseType_t ) MAX_MSG_SIZE, + ( uint8_t * ) queueData, + &staticQueue ); + + if( otaEventQueue == NULL ) + { + otaOsStatus = OtaOsEventQueueCreateFailed; + +/* printf( "Failed to create OTA Event Queue: " */ +/* "xQueueCreateStatic returned error: " */ +/* "OtaOsStatus_t=%d \n", */ +/* ( int ) otaOsStatus ); */ + } + else + { +/* printf( "OTA Event Queue created.\n" ); */ + } + + return otaOsStatus; +} + +OtaOsStatus_t OtaSendEvent_FreeRTOS( const void * pEventMsg ) +{ + OtaOsStatus_t otaOsStatus = OtaOsSuccess; + BaseType_t retVal = pdFALSE; + + /* Send the event to OTA event queue.*/ + retVal = xQueueSendToBack( otaEventQueue, pEventMsg, ( TickType_t ) 0 ); + + if( retVal == pdTRUE ) + { +/* printf( "OTA Event Sent.\n" ); */ + } + else + { + otaOsStatus = OtaOsEventQueueSendFailed; + +/* printf( "Failed to send event to OTA Event Queue: " */ +/* "xQueueSendToBack returned error: " */ +/* "OtaOsStatus_t=%d \n", */ +/* ( int ) otaOsStatus ); */ + } + + return otaOsStatus; +} + +OtaOsStatus_t OtaReceiveEvent_FreeRTOS( void * pEventMsg ) +{ + OtaOsStatus_t otaOsStatus = OtaOsSuccess; + BaseType_t retVal = pdFALSE; + + retVal = xQueueReceive( otaEventQueue, ( OtaEventMsg_t * ) pEventMsg, pdMS_TO_TICKS( 3000U ) ); + + if( retVal == pdTRUE ) + { +/* printf( "OTA Event received \n" ); */ + } + else + { + otaOsStatus = OtaOsEventQueueReceiveFailed; + + /* printf( "Failed to receive event or timeout from OTA Event Queue: " */ +/* "xQueueReceive returned error: " */ +/* "OtaOsStatus_t=%d \n", */ +/* ( int ) otaOsStatus ); */ + } + + return otaOsStatus; +} + +void OtaDeinitEvent_FreeRTOS() +{ + vQueueDelete( otaEventQueue ); + +/* printf( "OTA Event Queue Deleted. \n" ); */ +} diff --git a/examples/common/ota/ota_os/ota_os_freertos.h b/examples/common/ota/ota_os/ota_os_freertos.h new file mode 100644 index 0000000..6ecfe23 --- /dev/null +++ b/examples/common/ota/ota_os/ota_os_freertos.h @@ -0,0 +1,102 @@ +/* + * Copyright Amazon.com, Inc. and its affiliates. All Rights Reserved. + * SPDX-License-Identifier: MIT + * + * Licensed under the MIT License. See the LICENSE accompanying this file + * for the specific language governing permissions and limitations under + * the License. + */ + +/** + * @file ota_os_freertos.h + * @brief Function declarations for the example OTA OS Functional interface for + * FreeRTOS. + */ + +#ifndef _OTA_OS_FREERTOS_H_ +#define _OTA_OS_FREERTOS_H_ + +/* Standard library include. */ +#include +#include +#include +#include + +/** + * @ingroup ota_enum_types + * @brief The OTA OS interface return status. + */ +typedef enum OtaOsStatus +{ + OtaOsSuccess = 0, /*!< @brief OTA OS interface success. */ + OtaOsEventQueueCreateFailed = 0x80U, /*!< @brief Failed to create the event + * queue. */ + OtaOsEventQueueSendFailed, /*!< @brief Posting event message to the event + * queue failed. */ + OtaOsEventQueueReceiveFailed, /*!< @brief Failed to receive from the event + * queue. */ + OtaOsEventQueueDeleteFailed, /*!< @brief Failed to delete the event queue. + */ +} OtaOsStatus_t; + +/** + * @brief Initialize the OTA events. + * + * This function initializes the OTA events mechanism for freeRTOS platforms. + * + * @param[pEventCtx] Pointer to the OTA event context. + * + * @return OtaOsStatus_t, OtaOsSuccess if success , other error + * code on failure. + */ +OtaOsStatus_t OtaInitEvent_FreeRTOS(); + +/** + * @brief Sends an OTA event. + * + * This function sends an event to OTA library event handler on FreeRTOS + * platforms. + * + * @param[pEventCtx] Pointer to the OTA event context. + * + * @param[pEventMsg] Event to be sent to the OTA handler. + * + * @param[timeout] The maximum amount of time (msec) the task should + * block. + * + * @return OtaOsStatus_t, OtaOsSuccess if success , other error + * code on failure. + */ +OtaOsStatus_t OtaSendEvent_FreeRTOS( const void * pEventMsg ); + +/** + * @brief Receive an OTA event. + * + * This function receives next event from the pending OTA events on FreeRTOS + * platforms. + * + * @param[pEventCtx] Pointer to the OTA event context. + * + * @param[pEventMsg] Pointer to store message. + * + * @param[timeout] The maximum amount of time the task should block. + * + * @return OtaOsStatus_t, OtaOsSuccess if success , other error + * code on failure. + */ +OtaOsStatus_t OtaReceiveEvent_FreeRTOS( void * pEventMsg ); + +/** + * @brief Deinitialize the OTA Events mechanism. + * + * This function deinitialize the OTA events mechanism and frees any resources + * used on FreeRTOS platforms. + * + * @param[pEventCtx] Pointer to the OTA event context. + * + * @return OtaOsStatus_t, OtaOsSuccess if success , other error + * code on failure. + */ +void OtaDeinitEvent_FreeRTOS(); + +#endif /* ifndef _OTA_OS_FREERTOS_H_ */ diff --git a/examples/common/ota/ota_pal.c b/examples/common/ota/ota_pal.c index 9400f51..1abb2e7 100644 --- a/examples/common/ota/ota_pal.c +++ b/examples/common/ota/ota_pal.c @@ -37,13 +37,10 @@ #include "mcuboot_app_support.h" -/* Specify the OTA signature algorithm we support on this platform. */ -const char OTA_JsonFileSignatureKey[ OTA_FILE_SIG_KEY_STR_MAX_LENGTH ] = "sig-sha256-ecdsa"; - /* PAL file context structure */ typedef struct { - const OtaFileContext_t * FileXRef; + const AfrOtaJobDocumentFields_t * FileXRef; uint32_t partition_log_addr; uint32_t partition_phys_addr; uint32_t partition_size; @@ -54,44 +51,57 @@ typedef struct static PAL_FileContext_t prvPAL_CurrentFileContext; -static PAL_FileContext_t * prvPAL_GetPALFileContext( OtaFileContext_t * const C ) -{ - PAL_FileContext_t * PalFileContext; +OtaPalStatus_t xFlashPalValidateSignature( uint8_t * pMappedAddress, + size_t mappedLength, + char * pCertificatePath, + size_t certlength, + uint8_t * pSignature, + size_t signatureLength ); - if( ( C == NULL ) || ( C->pFile == NULL ) ) + +static PAL_FileContext_t * prvPAL_GetPALFileContext( AfrOtaJobDocumentFields_t * const pFileContext ) +{ + if( pFileContext == NULL ) { return NULL; } - - PalFileContext = ( PAL_FileContext_t * ) C->pFile; - - if( ( PalFileContext == NULL ) || ( PalFileContext->FileXRef != C ) ) + else if( prvPAL_CurrentFileContext.FileXRef != pFileContext ) { return NULL; } - - return PalFileContext; + else + { + return &prvPAL_CurrentFileContext; + } } -OtaPalStatus_t xOtaPalAbort( OtaFileContext_t * const C ) +OtaPalStatus_t otaPal_Abort( AfrOtaJobDocumentFields_t * const pFileContext ) { OtaPalStatus_t result = OtaPalSuccess; LogInfo( ( "[OTA-NXP] Abort" ) ); - C->pFile = NULL; + pFileContext->fileId = 0; + pFileContext->filepath = NULL; return result; } -OtaPalStatus_t xOtaPalCreateFileForRx( OtaFileContext_t * const C ) +OtaPalJobDocProcessingResult_t otaPal_CreateFileForRx( AfrOtaJobDocumentFields_t * const pFileContext ) { partition_t update_partition; PAL_FileContext_t * PalFileContext = &prvPAL_CurrentFileContext; LogDebug( ( "[OTA-NXP] CreateFileForRx" ) ); + if( otaPal_SetPlatformImageState( pFileContext, OtaImageStateAccepted ) == OtaPalSuccess ) + { + /* TODO: Check here if anything is to be verified before sending the + * success message to IoT core. */ + return OtaPalNewImageBooted; + } + if( bl_get_update_partition_info( &update_partition ) != kStatus_Success ) { LogError( ( "[OTA-NXP] Could not get update partition information" ) ); @@ -108,21 +118,21 @@ OtaPalStatus_t xOtaPalCreateFileForRx( OtaFileContext_t * const C ) if( PalFileContext->partition_phys_addr == MFLASH_INVALID_ADDRESS ) { LogError( ( "[OTA-NXP] Could not get update partition FLASH address" ) ); - return OTA_PAL_COMBINE_ERR( OtaPalRxFileCreateFailed, 0U ); + return OtaPalRxFileCreateFailed; } /* Check partition alignment */ if( !mflash_drv_is_sector_aligned( PalFileContext->partition_phys_addr ) || !mflash_drv_is_sector_aligned( PalFileContext->partition_size ) ) { LogError( ( "[OTA-NXP] Invalid update partition" ) ); - return OTA_PAL_COMBINE_ERR( OtaPalRxFileCreateFailed, 0U ); + return OtaPalRxFileCreateFailed; } /* Check whether the file fits at all */ - if( C->fileSize > update_partition.size ) + if( pFileContext->fileSize > update_partition.size ) { LogError( ( "[OTA-NXP] File too large" ) ); - return OTA_PAL_COMBINE_ERR( OtaPalRxFileTooLarge, 0U ); + return OtaPalRxFileTooLarge; } /* Actual size of the file according to data received */ @@ -134,14 +144,15 @@ OtaPalStatus_t xOtaPalCreateFileForRx( OtaFileContext_t * const C ) /* Pre-set address of area not erased so far */ PalFileContext->next_erase_addr = PalFileContext->partition_phys_addr; - PalFileContext->FileXRef = C; /* pointer cross reference for integrity check */ - C->pFile = ( uint8_t * ) PalFileContext; + PalFileContext->FileXRef = pFileContext; /* pointer cross reference for integrity check */ + + /*C->pFile = ( uint8_t * ) PalFileContext; */ return OtaPalSuccess; } -OtaPalStatus_t xOtaPalCloseFile( OtaFileContext_t * const C ) +OtaPalStatus_t otaPal_CloseFile( AfrOtaJobDocumentFields_t * const pFileContext ) { OtaPalStatus_t result = OtaPalSuccess; PAL_FileContext_t * PalFileContext; @@ -149,14 +160,14 @@ OtaPalStatus_t xOtaPalCloseFile( OtaFileContext_t * const C ) LogDebug( ( "[OTA-NXP] CloseFile" ) ); - PalFileContext = prvPAL_GetPALFileContext( C ); + PalFileContext = prvPAL_GetPALFileContext( pFileContext ); if( PalFileContext == NULL ) { - return OTA_PAL_COMBINE_ERR( OtaPalFileClose, 0U ); + return OtaPalFileClose; } - if( PalFileContext->file_size != C->fileSize ) + if( PalFileContext->file_size != pFileContext->fileSize ) { LogWarn( ( "[OTA-NXP] Actual file size is not as expected" ) ); } @@ -165,14 +176,15 @@ OtaPalStatus_t xOtaPalCloseFile( OtaFileContext_t * const C ) if( file_data == NULL ) { - return OTA_PAL_COMBINE_ERR( OtaPalSignatureCheckFailed, 0U ); + return OtaPalSignatureCheckFailed; } result = xFlashPalValidateSignature( ( void * ) file_data, PalFileContext->file_size, - ( char * ) C->pCertFilepath, - C->pSignature->data, - C->pSignature->size ); + ( char * ) pFileContext->certfile, + pFileContext->certfileLen, + pFileContext->signature, + pFileContext->signatureLen ); if( result != OtaPalSuccess ) { @@ -198,12 +210,12 @@ OtaPalStatus_t xOtaPalCloseFile( OtaFileContext_t * const C ) } #endif /* ifndef DISABLE_OTA_CLOSE_FILE_HEADER_CHECK */ - C->pFile = NULL; - return OTA_PAL_COMBINE_ERR( result, 0U ); + pFileContext->fileId = 0; + return result; } -int16_t xOtaPalWriteBlock( OtaFileContext_t * const C, +int16_t otaPal_WriteBlock( AfrOtaJobDocumentFields_t * const pFileContext, uint32_t ulOffset, uint8_t * const pcData, uint32_t ulBlockSize ) @@ -219,7 +231,7 @@ int16_t xOtaPalWriteBlock( OtaFileContext_t * const C, LogDebug( ( "[OTA-NXP] WriteBlock 0x%x : 0x%x", ulOffset, ulBlockSize ) ); - PalFileContext = prvPAL_GetPALFileContext( C ); + PalFileContext = prvPAL_GetPALFileContext( pFileContext ); if( PalFileContext == NULL ) { @@ -315,31 +327,23 @@ int16_t xOtaPalWriteBlock( OtaFileContext_t * const C, } -OtaPalStatus_t xOtaPalActivateNewImage( OtaFileContext_t * const C ) +OtaPalStatus_t otaPal_ActivateNewImage( AfrOtaJobDocumentFields_t * const pFileContext ) { LogInfo( ( "[OTA-NXP] ActivateNewImage" ) ); - xOtaPalResetDevice( C ); /* go for reboot */ + otaPal_ResetDevice( pFileContext ); /* go for reboot */ return OtaPalSuccess; } -OtaPalStatus_t xOtaPalResetDevice( OtaFileContext_t * const C ) -{ - LogInfo( ( "[OTA-NXP] SystemReset" ) ); - vTaskDelay( 100 / portTICK_PERIOD_MS ); - NVIC_SystemReset(); /* this should never return */ -} - - -OtaPalStatus_t xOtaPalSetPlatformImageState( OtaFileContext_t * const C, +OtaPalStatus_t otaPal_SetPlatformImageState( AfrOtaJobDocumentFields_t * const pFileContext, OtaImageState_t eState ) { OtaPalStatus_t result = OtaPalSuccess; LogDebug( ( "[OTA-NXP] SetPlatformImageState %d", eState ) ); - if( xOtaPalGetPlatformImageState( C ) == OtaPalImageStatePendingCommit ) + if( otaPal_GetPlatformImageState( pFileContext ) == OtaPalImageStatePendingCommit ) { /* Device in test mode */ switch( eState ) @@ -414,11 +418,11 @@ OtaPalStatus_t xOtaPalSetPlatformImageState( OtaFileContext_t * const C, } } - return OTA_PAL_COMBINE_ERR( result, 0U ); + return result; } -OtaPalImageState_t xOtaPalGetPlatformImageState( OtaFileContext_t * const C ) +OtaPalImageState_t otaPal_GetPlatformImageState( AfrOtaJobDocumentFields_t * const pFileContext ) { uint32_t state; @@ -442,3 +446,11 @@ OtaPalImageState_t xOtaPalGetPlatformImageState( OtaFileContext_t * const C ) return OtaPalImageStateInvalid; } + + +OtaPalStatus_t otaPal_ResetDevice( AfrOtaJobDocumentFields_t * const pFileContext ) +{ + LogInfo( ( "[OTA-NXP] SystemReset" ) ); + vTaskDelay( 100 / portTICK_PERIOD_MS ); + NVIC_SystemReset(); /* this should never return */ +} diff --git a/examples/common/ota/ota_pal.h b/examples/common/ota/ota_pal.h index bcf5266..6c2f8ef 100644 --- a/examples/common/ota/ota_pal.h +++ b/examples/common/ota/ota_pal.h @@ -31,131 +31,276 @@ #ifndef OTA_PAL_H #define OTA_PAL_H -#include "ota.h" + +#include "jobs.h" +#include "job_parser.h" /** - * @brief Retrieve the current firmware image state from flash. + * @ingroup ota_enum_types + * @brief OTA Image states. + * + * After an OTA update image is received and authenticated, it is logically moved to + * the Self Test state by the OTA agent pending final acceptance. After the image is + * activated and tested by your user code, you should put it into either the Accepted + * or Rejected state by calling @ref OTA_SetImageState ( OtaImageStateAccepted ) or + * @ref OTA_SetImageState ( OtaImageStateRejected ). If the image is accepted, it becomes + * the main firmware image to be booted from then on. If it is rejected, the image is + * no longer valid and shall not be used, reverting to the last known good image. * - * @param[in] pFileContext Pointer to a context containing firmware image details. - * @return Appropriate state of the firmware image. + * If you want to abort an active OTA transfer, you may do so by calling the API + * @ref OTA_SetImageState ( OtaImageStateAborted ). */ -OtaPalImageState_t xOtaPalGetPlatformImageState( OtaFileContext_t * const pFileContext ); - -#define otaPal_GetPlatformImageState xOtaPalGetPlatformImageState +typedef enum OtaImageState +{ + OtaImageStateUnknown = 0, /*!< @brief The initial state of the OTA MCU Image. */ + OtaImageStateTesting = 1, /*!< @brief The state of the OTA MCU Image post successful download and reboot. */ + OtaImageStateAccepted = 2, /*!< @brief The state of the OTA MCU Image post successful download and successful self_test. */ + OtaImageStateRejected = 3, /*!< @brief The state of the OTA MCU Image when the job has been rejected. */ + OtaImageStateAborted = 4, /*!< @brief The state of the OTA MCU Image after a timeout publish to the stream request fails. + * Also if the OTA MCU image is aborted in the middle of a stream. */ + OtaLastImageState = OtaImageStateAborted +} OtaImageState_t; /** - * @brief Set the current firmware image state in flash. + * @ingroup ota_enum_types + * @brief OTA Platform Image State. * - * @param[in] pFileContext Pointer to a context containing firmware image details. - * @param[in] eState State to be set for the firmware image. - * @return OtaPalSuccess if successful, else OTA error code along with detailed PAL error code. + * The image state set by platform implementation. */ -OtaPalStatus_t xOtaPalSetPlatformImageState( OtaFileContext_t * const pFileContext, - OtaImageState_t eState ); - -#define otaPal_SetPlatformImageState xOtaPalSetPlatformImageState +typedef enum OtaPalImageState +{ + OtaPalImageStateUnknown = 0, /*!< @brief The initial state of the OTA PAL Image. */ + OtaPalImageStatePendingCommit, /*!< @brief OTA PAL Image awaiting update. */ + OtaPalImageStateValid, /*!< @brief OTA PAL Image is valid. */ + OtaPalImageStateInvalid /*!< @brief OTA PAL Image is invalid. */ +} OtaPalImageState_t; /** - * @brief Resets the device with the current firmware image. - * The API can be invoked when aborting the current OTA update to fall back to old image or while activating - * new image after a successful update. + * @ingroup ota_enum_types + * @brief OTA Platform Image State. * - * @param[in] pFileContext Pointer to a context containing firmware image details. - * @return OtaPalSuccess if successful, else OTA error code along with detailed PAL error code. + * The image state set by platform implementation. */ -OtaPalStatus_t xOtaPalResetDevice( OtaFileContext_t * const pFileContext ); +typedef enum OtaPalJobDocProcessingResult +{ + OtaPalJobDocFileCreated = 0, + OtaPalJobDocFileCreateFailed, + OtaPalNewImageBooted, + OtaPalNewImageBootFailed, + OtaPalJobDocProcessingStateInvalid +} OtaPalJobDocProcessingResult_t; -#define otaPal_ResetDevice xOtaPalResetDevice +typedef enum OtaPalStatus +{ + OtaPalSuccess = 0, + OtaPalUninitialized, + OtaPalOutOfMemory, + OtaPalNullFileContext, + OtaPalSignatureCheckFailed, + OtaPalRxFileCreateFailed, + OtaPalRxFileTooLarge, + OtaPalBootInfoCreateFailed, + OtaPalBadSignerCert, + OtaPalBadImageState, + OtaPalAbortFailed, + OtaPalRejectFailed, + OtaPalCommitFailed, + OtaPalActivateFailed, + OtaPalFileAbort, + OtaPalFileClose +} OtaPalStatus_t; /** - * @brief Activates the device with the new firmware image. - * The API should prepare the new image to be booted up and reset the device to boot up with the new image. + * @brief Abort an OTA transfer. + * + * Aborts access to an existing open file represented by the OTA file context pFileContext. This is + * only valid for jobs that started successfully. + * + * @note The input OtaFileContext_t pFileContext is checked for NULL by the OTA agent before this + * function is called. * - * @param[in] pFileContext Pointer to a context containing firmware image details. - * @return OtaPalSuccess if successful, else OTA error code along with detailed PAL error code. + * This function may be called before the file is opened, so the file pointer pFileContext->fileHandle + * may be NULL when this function is called. + * + * @param[in] pFileContext OTA file context information. + * + * @return The OtaPalStatus_t error code is a combination of the main OTA PAL interface error and + * the MCU specific sub error code. See ota_platform_interface.h for the OtaPalMainStatus_t + * error codes and your specific PAL implementation for the sub error code. + * + * Major error codes returned are: + * + * OtaPalSuccess: Aborting access to the open file was successful. + * OtaPalFileAbort: Aborting access to the open file context was unsuccessful. */ -OtaPalStatus_t xOtaPalActivateNewImage( OtaFileContext_t * const pFileContext ); - -#define otaPal_ActivateNewImage xOtaPalActivateNewImage +OtaPalStatus_t otaPal_Abort( AfrOtaJobDocumentFields_t * const pFileContext ); /** - * @brief Writes a block of the firmware image to flash. + * @brief Create a new receive file. + * + * @note Opens the file indicated in the OTA file context in the MCU file system. * - * @param[in] pFileContext Pointer to a context containing firmware image details. - * @param[in] offset Offset in bytes of the block with in the whole firmware image - * @param[in] pData Pointer to buffer containing the block. - * @param[in] blockSize Size of the block - * @return Number of bytes of block written or < 0 if there is an error. + * @note The previous image may be present in the designated image download partition or file, so the + * partition or file must be completely erased or overwritten in this routine. + * + * @note The input OtaFileContext_t pFileContext is checked for NULL by the OTA agent before this + * function is called. + * The device file path is a required field in the OTA job document, so pFileContext->pFilePath is + * checked for NULL by the OTA agent before this function is called. + * + * @param[in] pFileContext OTA file context information. + * + * @return The OtaPalStatus_t error code is a combination of the main OTA PAL interface error and + * the MCU specific sub error code. See ota_platform_interface.h for the OtaPalMainStatus_t + * error codes and your specific PAL implementation for the sub error code. + * + * Major error codes returned are: + * + * OtaPalSuccess: File creation was successful. + * OtaPalRxFileTooLarge: The OTA receive file is too big for the platform to support. + * OtaPalBootInfoCreateFailed: The bootloader information file creation failed. + * OtaPalRxFileCreateFailed: Returned for other errors creating the file in the device's + * non-volatile memory. If this error is returned, then the sub error + * should be set to the appropriate platform specific value. */ -int16_t xOtaPalWriteBlock( OtaFileContext_t * const pFileContext, - uint32_t offset, - uint8_t * const pData, - uint32_t blockSize ); - -#define otaPal_WriteBlock xOtaPalWriteBlock +OtaPalJobDocProcessingResult_t otaPal_CreateFileForRx( AfrOtaJobDocumentFields_t * const pFileContext ); /** - * @brief Closes the firmware image after reading or writing. + * @brief Authenticate and close the underlying receive file in the specified OTA context. + * + * @note The input OtaFileContext_t pFileContext is checked for NULL by the OTA agent before this + * function is called. This function is called only at the end of block ingestion. + * otaPAL_CreateFileForRx() must succeed before this function is reached, so + * pFileContext->fileHandle(or pFileContext->pFile) is never NULL. + * The file signature key is required job document field in the OTA Agent, so pFileContext->pSignature will + * never be NULL. * - * @param[in] pFileContext Pointer to a context containing firmware image details. - * @return OtaPalSuccess if successful, else OTA error code along with detailed PAL error code. + * If the signature verification fails, file close should still be attempted. + * + * @param[in] pFileContext OTA file context information. + * + * @return The OtaPalStatus_t error code is a combination of the main OTA PAL interface error and + * the MCU specific sub error code. See ota_platform_interface.h for the OtaPalMainStatus_t + * error codes and your specific PAL implementation for the sub error code. + * + * Major error codes returned are: + * + * OtaPalSuccess on success. + * OtaPalSignatureCheckFailed: The signature check failed for the specified file. + * OtaPalBadSignerCert: The signer certificate was not readable or zero length. + * OtaPalFileClose: Error in low level file close. */ -OtaPalStatus_t xOtaPalCloseFile( OtaFileContext_t * const pFileContext ); - -#define otaPal_CloseFile xOtaPalCloseFile +OtaPalStatus_t otaPal_CloseFile( AfrOtaJobDocumentFields_t * const pFileContext ); /** - * @brief Prepares a new firmware image to be written. + * @brief Write a block of data to the specified file at the given offset. + * + * @note The input OtaFileContext_t pFileContext is checked for NULL by the OTA agent before this + * function is called. + * The file pointer/handle pFileContext->pFile, is checked for NULL by the OTA agent before this + * function is called. + * pData is checked for NULL by the OTA agent before this function is called. + * blockSize is validated for range by the OTA agent before this function is called. + * offset is validated by the OTA agent before this function is called. * - * @param[in] pFileContext Pointer to a context containing firmware image details. - * @return OtaPalSuccess if successful, else OTA error code along with detailed PAL error code. + * @param[in] pFileContext OTA file context information. + * @param[in] ulOffset Byte offset to write to from the beginning of the file. + * @param[in] pData Pointer to the byte array of data to write. + * @param[in] ulBlockSize The number of bytes to write. + * + * @return The number of bytes written successfully, or a negative error code from the platform + * abstraction layer. */ -OtaPalStatus_t xOtaPalCreateFileForRx( OtaFileContext_t * const pFileContext ); - -#define otaPal_CreateFileForRx xOtaPalCreateFileForRx +int16_t otaPal_WriteBlock( AfrOtaJobDocumentFields_t * const pFileContext, + uint32_t ulOffset, + uint8_t * const pcData, + uint32_t ulBlockSize ); /** - * @brief Aborts the current firmware image being written. + * @brief Activate the newest MCU image received via OTA. + * + * This function shall take necessary actions to activate the newest MCU + * firmware received via OTA. It is typically just a reset of the device. + * + * @note This function SHOULD NOT return. If it does, the platform does not support + * an automatic reset or an error occurred. + * + * @param[in] pFileContext OTA file context information. + * + * @return The OtaPalStatus_t error code is a combination of the main OTA PAL interface error and + * the MCU specific sub error code. See ota_platform_interface.h for the OtaPalMainStatus_t + * error codes and your specific PAL implementation for the sub error code. + * + * Major error codes returned are: * - * @param[in] pFileContext Pointer to a context containing firmware image details. - * @return OtaPalSuccess if successful, else OTA error code along with detailed PAL error code. + * OtaPalSuccess on success. + * OtaPalActivateFailed: The activation of the new OTA image failed. */ -OtaPalStatus_t xOtaPalAbort( OtaFileContext_t * const pFileContext ); - -#define otaPal_Abort xOtaPalAbort - +OtaPalStatus_t otaPal_ActivateNewImage( AfrOtaJobDocumentFields_t * const pFileContext ); /** - * @brief Opens the firmware image for reading - * The API is used to verify the image signature after it has been written. + * @brief Attempt to set the state of the OTA update image. + * + * Take required actions on the platform to Accept/Reject the OTA update image (or bundle). + * Refer to the PAL implementation to determine what happens on your platform. + * + * @param[in] pFileContext File context of type OtaFileContext_t. + * @param[in] eState The desired state of the OTA update image. + * + * @return The OtaPalStatus_t error code is a combination of the main OTA PAL interface error and + * the MCU specific sub error code. See ota_platform_interface.h for the OtaPalMainStatus_t + * error codes and your specific PAL implementation for the sub error code. + * + * Major error codes returned are: * - * @param[in] pFileContext Pointer to a context containing firmware image details. - * @return OtaPalSuccess if successful, else OTA error code along with detailed PAL error code. + * OtaPalSuccess on success. + * OtaPalBadImageState: if you specify an invalid OtaImageState_t. No sub error code. + * OtaPalAbortFailed: failed to roll back the update image as requested by OtaImageStateAborted. + * OtaPalRejectFailed: failed to roll back the update image as requested by OtaImageStateRejected. + * OtaPalCommitFailed: failed to make the update image permanent as requested by OtaImageStateAccepted. */ -OtaPalStatus_t xOtaPalOpenFileForRead( OtaFileContext_t * const pContext ); - -#define otaPal_OpenFileForRead xOtaPalOpenFileForRead +OtaPalStatus_t otaPal_SetPlatformImageState( AfrOtaJobDocumentFields_t * const pFileContext, + OtaImageState_t eState ); /** - * @brief Reads a block of firmware image from flash + * @brief Get the state of the OTA update image. + * + * We read this at OTA_Init time and when the latest OTA job reports itself in self + * test. If the update image is in the "pending commit" state, we start a self test + * timer to assure that we can successfully connect to the OTA services and accept + * the OTA update image within a reasonable amount of time (user configurable). If + * we don't satisfy that requirement, we assume there is something wrong with the + * firmware and automatically reset the device, causing it to roll back to the + * previously known working code. + * + * If the update image state is not in "pending commit," the self test timer is + * not started. * - * @param[in] pFileContext Pointer to a context containing firmware image details. - * @param[in] offset Offset in bytes of the block with in the whole firmware image - * @param[in] pData Pointer to buffer where block is read to. - * @param[in] blockSize Size of the buffer - * @return Number of bytes of block read or < 0 if there is an error. + * @param[in] pFileContext File context of type OtaFileContext_t. + * + * @return An OtaPalImageState_t. One of the following: + * OtaPalImageStatePendingCommit (the new firmware image is in the self test phase) + * OtaPalImageStateValid (the new firmware image is already committed) + * OtaPalImageStateInvalid (the new firmware image is invalid or non-existent) + * + * NOTE: OtaPalImageStateUnknown should NEVER be returned and indicates an implementation error. */ -int32_t xOtaPalReadBlock( OtaFileContext_t * const pContext, - uint32_t offset, - uint8_t * pData, - uint16_t blockSize ); - -#define otaPal_ReadBlock xOtaPalReadBlock +OtaPalImageState_t otaPal_GetPlatformImageState( AfrOtaJobDocumentFields_t * const pFileContext ); -OtaPalStatus_t xFlashPalValidateSignature( uint8_t * pMappedAddress, - size_t mappedLength, - char * pCertificatePath, - uint8_t * pSignature, - size_t signatureLength ); +/** + * @brief Reset the device. + * + * This function shall reset the MCU and cause a reboot of the system. + * + * @note This function SHOULD NOT return. If it does, the platform does not support + * an automatic reset or an error occurred. + * + * @param[in] pFileContext OTA file context information. + * + * @return The OtaPalStatus_t error code is a combination of the main OTA PAL interface error and + * the MCU specific sub error code. See ota_platform_interface.h for the OtaPalMainStatus_t + * error codes and your specific PAL implementation for the sub error code. + */ +OtaPalStatus_t otaPal_ResetDevice( AfrOtaJobDocumentFields_t * const pFileContext ); -#endif /* OTA_PAL_H */ +#endif /* ifndef OTA_PAL_H_ */ diff --git a/examples/common/ota/ota_signature_validation.c b/examples/common/ota/ota_signature_validation.c index 88cac9c..016cdaa 100644 --- a/examples/common/ota/ota_signature_validation.c +++ b/examples/common/ota/ota_signature_validation.c @@ -246,6 +246,7 @@ CK_RV xVerifyImageSignatureUsingPKCS11( CK_SESSION_HANDLE session, OtaPalStatus_t xFlashPalValidateSignature( uint8_t * pMappedAddress, size_t mappedLength, char * pCertificatePath, + size_t certlength, uint8_t * pSignature, size_t signatureLength ) { @@ -254,6 +255,10 @@ OtaPalStatus_t xFlashPalValidateSignature( uint8_t * pMappedAddress, CK_RV xPKCS11Status = CKR_OK; CK_OBJECT_HANDLE certHandle; uint8_t pkcs11Signature[ pkcs11ECDSA_P256_SIGNATURE_LENGTH ] = { 0 }; + /* TODO: Fix the label length. */ + char certfile[ 30 + 1 ] = { '\0' }; + + memcpy( certfile, pCertificatePath, certlength ); if( PKI_mbedTLSSignatureToPkcs11Signature( pkcs11Signature, pSignature ) != 0 ) { diff --git a/examples/common/ota/ota_update.c b/examples/common/ota/ota_update.c index 434e95a..1a5b73d 100644 --- a/examples/common/ota/ota_update.c +++ b/examples/common/ota/ota_update.c @@ -52,15 +52,24 @@ /* MQTT library includes. */ #include "core_mqtt_agent.h" -/* OTA Library include. */ -#include "ota.h" +/* MQTT streams Library include. */ +#include "MQTTFileDownloader.h" +#include "MQTTFileDownloader_base64.h" -/* OTA Library Interface include. */ -#include "ota_os_freertos.h" -#include "ota_mqtt_interface.h" +/* jobs Library include. */ +#include "jobs.h" + +/* OTA job parser include. */ +#include "job_parser.h" +#include "ota_job_processor.h" /* Include firmware version struct definition. */ -#include "ota_appversion32.h" +/*#include "ota_appversion32.h" */ + +#include "ota_demo.h" +#include "ota_os_freertos.h" + +#include "mqtt_wrapper.h" /* Include platform abstraction header. */ #include "ota_pal.h" @@ -168,7 +177,19 @@ /** * @brief Maximum stack size of OTA agent task. */ -#define otaexampleAGENT_TASK_STACK_SIZE ( 4096 ) +#define otaexampleAGENT_TASK_STACK_SIZE ( 4096 * 2 ) + + +#define CONFIG_MAX_FILE_SIZE 200 /* TODO:!! */ +#define NUM_OF_BLOCKS_REQUESTED 1U +#define START_JOB_MSG_LENGTH 147U +#define MAX_THING_NAME_SIZE 128U +#define MAX_JOB_ID_LENGTH 64U +#define UPDATE_JOB_MSG_LENGTH 48U +#define MAX_NUM_OF_OTA_DATA_BUFFERS 2U + +/* Max bytes supported for a file signature (3072 bit RSA is 384 bytes). */ +#define OTA_MAX_SIGNATURE_SIZE ( 384U ) /** * @brief Defines the structure to use as the command callback context in this @@ -180,114 +201,22 @@ struct MQTTAgentCommandContext void * pArgs; }; -/** - * @brief Function used by OTA agent to publish control messages to the MQTT broker. - * - * The implementation uses MQTT agent to queue a publish request. It then waits - * for the request complete notification from the agent. The notification along with result of the - * operation is sent back to the caller task using xTaskNotify API. For publishes involving QOS 1 and - * QOS2 the operation is complete once an acknowledgment (PUBACK) is received. OTA agent uses this function - * to fetch new job, provide status update and send other control related messages to the MQTT broker. - * - * @param[in] pacTopic Topic to publish the control packet to. - * @param[in] topicLen Length of the topic string. - * @param[in] pMsg Message to publish. - * @param[in] msgSize Size of the message to publish. - * @param[in] qos Qos for the publish. - * @return OtaMqttSuccess if successful. Appropriate error code otherwise. - */ -static OtaMqttStatus_t prvMQTTPublish( const char * const pacTopic, - uint16_t topicLen, - const char * pMsg, - uint32_t msgSize, - uint8_t qos ); - - -/** - * @brief The callback invoked by the MQTT agent on a successful subscription of a topic filter - * with broker. - * The implementation adds a local subscription for the topic filter with the MQTT agent. - * - * @param pCommandContext Pointer to the command context passed from the caller. - * @param pxReturnInfo Pointer to the return status of the subscribe command. - */ -static void prvSubscribeCommandCallback( MQTTAgentCommandContext_t * pxCommandContext, - MQTTAgentReturnInfo_t * pxReturnInfo ); - -/** - * @brief The callback invoked by the MQTT agent on unsubscribing a topic filter - * with broker. - * The implementation removes the local subscription for the topic filter with the MQTT agent. - * - * @param pCommandContext Pointer to the command context passed from the caller. - * @param pxReturnInfo Pointer to the return status of the unsubscribe command. - */ -static void prvUnSubscribeCommandCallback( MQTTAgentCommandContext_t * pxCommandContext, - MQTTAgentReturnInfo_t * pxReturnInfo ); - -/** - * @brief Function used by OTA agent to subscribe for a control or data packet from the MQTT broker. - * - * The implementation queues a SUBSCRIBE request for the topic filter with the MQTT agent. It then waits for - * a notification of the request completion. Notification will be sent back to caller task, - * using xTaskNotify APIs. MQTT agent also stores a callback provided by this function with - * the associated topic filter. The callback will be used to - * route any data received on the matching topic to the OTA agent. OTA agent uses this function - * to subscribe to all topic filters necessary for receiving job related control messages as - * well as firmware image chunks from MQTT broker. - * - * @param[in] pTopicFilter The topic filter used to subscribe for packets. - * @param[in] topicFilterLength Length of the topic filter string. - * @param[in] ucQoS Intended qos value for the messages received on this topic. - * @return OtaMqttSuccess if successful. Appropriate error code otherwise. - */ -static OtaMqttStatus_t prvMQTTSubscribe( const char * pTopicFilter, - uint16_t topicFilterLength, - uint8_t ucQoS ); +static MqttFileDownloaderContext_t mqttFileDownloaderContext = { 0 }; +static uint32_t numOfBlocksRemaining = 0; +static uint32_t currentBlockOffset = 0; +static uint8_t currentFileId = 0; +static uint32_t totalBytesReceived = 0; +char globalJobId[ MAX_JOB_ID_LENGTH ] = { 0 }; -/** - * @brief Function is used by OTA agent to unsubscribe a topicfilter from MQTT broker. - * - * The implementation queues an UNSUBSCRIBE request for the topic filter with the MQTT agent. It then waits - * for a successful completion of the request from the agent. Notification along with results of - * operation is sent using xTaskNotify API to the caller task. MQTT agent also removes the topic filter - * subscription from its memory so any future - * packets on this topic will not be routed to the OTA agent. - * - * @param[in] pTopicFilter Topic filter to be unsubscribed. - * @param[in] topicFilterLength Length of the topic filter. - * @param[in] ucQos Qos value for the topic. - * @return OtaMqttSuccess if successful. Appropriate error code otherwise. - * - */ -static OtaMqttStatus_t prvMQTTUnsubscribe( const char * pTopicFilter, - uint16_t topicFilterLength, - uint8_t ucQoS ); +static SemaphoreHandle_t bufferSemaphore; -/** - * @brief Fetch an unused OTA event buffer from the pool. - * - * Demo uses a simple statically allocated array of fixed size event buffers. The - * number of event buffers is configured by the param otaconfigMAX_NUM_OTA_DATA_BUFFERS - * within ota_config.h. This function is used to fetch a free buffer from the pool for processing - * by the OTA agent task. It uses a mutex for thread safe access to the pool. - * - * @return A pointer to an unused buffer. NULL if there are no buffers available. - */ -static OtaEventData_t * prvOTAEventBufferGet( void ); +static OtaDataEvent_t dataBuffers[ MAX_NUM_OF_OTA_DATA_BUFFERS ] = { 0 }; +static OtaJobEventData_t jobDocBuffer = { 0 }; +static AfrOtaJobDocumentFields_t jobFields = { 0 }; +static uint8_t OtaImageSingatureDecoded[ OTA_MAX_SIGNATURE_SIZE ] = { 0 }; +static SemaphoreHandle_t bufferSemaphore; -/** - * @brief Free an event buffer back to pool - * - * OTA demo uses a statically allocated array of fixed size event buffers . The - * number of event buffers is configured by the param otaconfigMAX_NUM_OTA_DATA_BUFFERS - * within ota_config.h. The function is used by the OTA application callback to free a buffer, - * after OTA agent has completed processing with the event. The access to the pool is made thread safe - * using a mutex. - * - * @param[in] pxBuffer Pointer to the buffer to be freed. - */ -static void prvOTAEventBufferFree( OtaEventData_t * const pxBuffer ); +static OtaState_t otaAgentState = OtaAgentStateInit; /** * @brief The function which runs the OTA agent task. @@ -314,101 +243,79 @@ static void prvOTAAgentTask( void * pvParam ); void vOTAUpdateTask( void * pvParam ); /** - * @brief Callback to receive either data or control messages on OTA topics. - * - * Function can get invoked for a job notification message or a data message from MQTT broker. - * Function matches the topic of the message with list of topic filters and routes the message to - * either control message or data message processing functions. - * - * @param[in] pxSubscriptionContext Context which is passed unmodified from the MQTT agent. - * @param[in] pPublishInfo Pointer to the structure containing the details of the MQTT packet. + * @brief This is in essence the OTA agent implementation. */ -static void prvProcessIncomingMessage( void * pxSubscriptionContext, - MQTTPublishInfo_t * pxPublishInfo ); +static void processOTAEvents( void ); /** - * @brief Callback invoked for data messages received from MQTT broker. - * - * Function gets invoked for the firmware image blocks received on OTA data stream topic. - * The function is registered with MQTT agent's subscription manger along with the - * topic filter for data stream. For each packet received, the - * function fetches a free event buffer from the pool and queues the firmware image chunk for - * OTA agent task processing. - * - * @param[in] pxSubscriptionContext Context which is passed unmodified from the MQTT agent. - * @param[in] pPublishInfo Pointer to the structure containing the details of the MQTT packet. + * @brief */ -static void prvProcessIncomingData( void * pxSubscriptionContext, - MQTTPublishInfo_t * pPublishInfo ); +static bool imageActivationHandler( void ); /** - * @brief Callback invoked for job control messages from MQTT broker. - * - * Callback gets invoked for any OTA job related control messages from the MQTT broker. - * The function is registered with MQTT agent's subscription manger along with the topic filter for - * job stream. The function fetches a free event buffer from the pool and queues the appropriate event type - * based on the control message received. - * - * @param[in] pxSubscriptionContext Context which is passed unmodified from the MQTT agent. - * @param[in] pPublishInfo Pointer to the structure containing the details of MQTT packet. + * @brief */ -static void prvProcessIncomingJobMessage( void * pxSubscriptionContext, - MQTTPublishInfo_t * pPublishInfo ); +static bool closeFileHandler( void ); /** - * @brief Matches a client identifier within an OTA topic. - * This function is used to validate that topic is valid and intended for this device thing name. - * - * @param[in] pTopic Pointer to the topic - * @param[in] topicNameLength length of the topic - * @param[in] pClientIdentifier Client identifier, should be null terminated. - * @param[in] clientIdentifierLength Length of the client identifier. - * @return pdTRUE if client identifier is found within the topic at the right index. + * @brief + */ +static OtaPalJobDocProcessingResult_t receivedJobDocumentHandler( OtaJobEventData_t * jobDoc ); + +/** + * @brief + */ +static uint16_t getFreeOTABuffers( void ); + +/** + * @brief + */ +static void freeOtaDataEventBuffer( OtaDataEvent_t * const pxBuffer ); + +/** + * @brief */ -static BaseType_t prvMatchClientIdentifierInTopic( const char * pTopic, - size_t topicNameLength, - const char * pClientIdentifier, - size_t clientIdentifierLength ); +static OtaDataEvent_t * getOtaDataEventBuffer( void ); +/** + * @brief + */ +static void requestDataBlock( void ); /** - * @brief Buffer used to store the firmware image file path. - * Buffer is passed to the OTA agent during initialization. + * @brief */ -static uint8_t updateFilePath[ otaexampleMAX_FILE_PATH_SIZE ]; +static int16_t handleMqttStreamsBlockArrived( uint8_t * data, + size_t dataLength ); /** - * @brief Buffer used to store the code signing certificate file path. - * Buffer is passed to the OTA agent during initialization. + * @brief */ -static uint8_t certFilePath[ otaexampleMAX_FILE_PATH_SIZE ]; +static bool convertSignatureToDER( AfrOtaJobDocumentFields_t * jobFields ); /** - * @brief Buffer used to store the name of the data stream. - * Buffer is passed to the OTA agent during initialization. + * @brief */ -static uint8_t streamName[ otaexampleMAX_STREAM_NAME_SIZE ]; +static void initMqttDownloader( AfrOtaJobDocumentFields_t * jobFields ); /** - * @brief Buffer used decode the CBOR message from the MQTT payload. - * Buffer is passed to the OTA agent during initialization. + * @brief */ -static uint8_t decodeMem[ ( 1U << otaconfigLOG2_FILE_BLOCK_SIZE ) ]; +static void requestJobDocumentHandler( void ); /** - * @brief Application buffer used to store the bitmap for requesting firmware image - * chunks from MQTT broker. Buffer is passed to the OTA agent during initialization. + * @brief */ -static uint8_t bitmap[ OTA_MAX_BLOCK_BITMAP_SIZE ]; +static bool jobDocumentParser( char * message, + size_t messageLength, + AfrOtaJobDocumentFields_t * jobFields ); + /** - * @brief A statically allocated array of event buffers used by the OTA agent. - * Maximum number of buffers are determined by how many chunks are requested - * by OTA agent at a time along with an extra buffer to handle control message. - * The size of each buffer is determined by the maximum size of firmware image - * chunk, and other metadata send along with the chunk. + * @brief */ -static OtaEventData_t eventBuffer[ otaconfigMAX_NUM_OTA_DATA_BUFFERS ] = { 0 }; +static bool sendSuccessMessage( void ); + /* * @brief Mutex used to manage thread safe access of OTA event buffers. @@ -420,23 +327,6 @@ static SemaphoreHandle_t xBufferSemaphore; */ extern MQTTAgentContext_t xGlobalMqttAgentContext; -/** - * @brief Structure containing all application allocated buffers used by the OTA agent. - * Structure is passed to the OTA agent during initialization. - */ -static OtaAppBuffer_t otaBuffer = -{ - .pUpdateFilePath = updateFilePath, - .updateFilePathsize = otaexampleMAX_FILE_PATH_SIZE, - .pCertFilePath = certFilePath, - .certFilePathSize = otaexampleMAX_FILE_PATH_SIZE, - .pStreamName = streamName, - .streamNameSize = otaexampleMAX_STREAM_NAME_SIZE, - .pDecodeMemory = decodeMem, - .decodeMemorySize = ( 1U << otaconfigLOG2_FILE_BLOCK_SIZE ), - .pFileBitmap = bitmap, - .fileBitmapSize = OTA_MAX_BLOCK_BITMAP_SIZE -}; /** * @brief Structure used for encoding firmware version. @@ -455,717 +345,759 @@ const AppVersion32_t appFirmwareVersion = static char * pcThingName = NULL; static size_t xThingNameLength = 0U; - -/*---------------------------------------------------------*/ - -static void prvOTAEventBufferFree( OtaEventData_t * const pxBuffer ) -{ - if( xSemaphoreTake( xBufferSemaphore, portMAX_DELAY ) == pdTRUE ) - { - pxBuffer->bufferUsed = false; - ( void ) xSemaphoreGive( xBufferSemaphore ); - } - else - { - LogError( ( "Failed to get buffer semaphore." ) ); - } -} - /*-----------------------------------------------------------*/ -static OtaEventData_t * prvOTAEventBufferGet( void ) +static void prvOTAAgentTask( void * pvParam ) { - uint32_t ulIndex = 0; - OtaEventData_t * pFreeBuffer = NULL; + BaseType_t xResult; + size_t xValueLength = 0U; + char * pcValue = NULL; + + LogError( "Running OTA Agent task. Waiting..." ); - if( xSemaphoreTake( xBufferSemaphore, portMAX_DELAY ) == pdTRUE ) + while( 1 ) { - for( ulIndex = 0; ulIndex < otaconfigMAX_NUM_OTA_DATA_BUFFERS; ulIndex++ ) + xResult = xWaitForMQTTAgentState( MQTT_AGENT_STATE_CONNECTED, + portMAX_DELAY ); + + if( xResult == pdTRUE ) { - if( eventBuffer[ ulIndex ].bufferUsed == false ) - { - eventBuffer[ ulIndex ].bufferUsed = true; - pFreeBuffer = &eventBuffer[ ulIndex ]; - break; - } + break; } - - ( void ) xSemaphoreGive( xBufferSemaphore ); } - else + + /* Load broker thing name from the key store. */ + xValueLength = KVStore_getValueLength( KVS_CORE_THING_NAME ); + + if( xValueLength > 0 ) { - LogError( ( "Failed to get buffer semaphore." ) ); + pcValue = pvPortMalloc( xValueLength + 1 ); + + if( pcValue != NULL ) + { + ( void ) KVStore_getString( KVS_CORE_THING_NAME, pcValue, ( xValueLength + 1 ) ); + } } - return pFreeBuffer; -} + mqttWrapper_setThingName( pcValue, xValueLength ); + + vPortFree( pcValue ); + + otaDemo_start(); -/*-----------------------------------------------------------*/ -static void prvOTAAgentTask( void * pvParam ) -{ - OTA_EventProcessingTask( pvParam ); vTaskDelete( NULL ); } /*-----------------------------------------------------------*/ -/** - * @brief The OTA agent has completed the update job or it is in - * self test mode. If it was accepted, we want to activate the new image. - * This typically means we should reset the device to run the new firmware. - * If now is not a good time to reset the device, it may be activated later - * by your user code. If the update was rejected, just return without doing - * anything and we will wait for another job. If it reported that we should - * start test mode, normally we would perform some kind of system checks to - * make sure our new firmware does the basic things we think it should do - * but we will just go ahead and set the image as accepted for demo purposes. - * The accept function varies depending on your platform. Refer to the OTA - * PAL implementation for your platform in aws_ota_pal.c to see what it - * does for you. - * - * @param[in] event Specify if this demo is running with the AWS IoT - * MQTT server. Set this to `false` if using another MQTT server. - * @param[in] pData Data associated with the event. - * @return None. - */ -static void otaAppCallback( OtaJobEvent_t event, - void * pData ) +void otaDemo_start( void ) { - OtaErr_t err = OtaErrUninitialized; + OtaEventMsg_t initEvent = { 0 }; - switch( event ) + if( !mqttWrapper_isConnected() ) { - case OtaJobEventActivate: - LogInfo( ( "Received OtaJobEventActivate callback from OTA Agent." ) ); - - /** - * Activate the new firmware image immediately. Applications can choose to postpone - * the activation to a later stage if needed. - */ - err = OTA_ActivateNewImage(); - - /** - * Activation of the new image failed. This indicates an error that requires a follow - * up through manual activation by resetting the device. The demo reports the error - * and shuts down the OTA agent. - */ - LogError( ( "New image activation failed." ) ); + LogInfo( "MQTT not connected, exiting!" ); + return; + } - /* Shutdown OTA Agent, if it is required that the unsubscribe operations are not - * performed while shutting down please set the second parameter to 0 instead of 1. */ - OTA_Shutdown( 0, 1 ); + bufferSemaphore = xSemaphoreCreateMutex(); + if( bufferSemaphore != NULL ) + { + memset( dataBuffers, 0x00, sizeof( dataBuffers ) ); + } - break; + LogError( "Starting OTA thread." ); - case OtaJobEventFail: + OtaInitEvent_FreeRTOS(); - /** - * No user action is needed here. OTA agent handles the job failure event. - */ - LogInfo( ( "Received an OtaJobEventFail notification from OTA Agent." ) ); + initEvent.eventId = OtaAgentEventRequestJobDocument; + OtaSendEvent_FreeRTOS( &initEvent ); - break; + while( otaAgentState != OtaAgentStateStopped ) + { + processOTAEvents(); + } +} - case OtaJobEventStartTest: +/*-----------------------------------------------------------*/ - /* This demo just accepts the image since it was a good OTA update and networking - * and services are all working (or we would not have made it this far). If this - * were some custom device that wants to test other things before validating new - * image, this would be the place to kick off those tests before calling - * OTA_SetImageState() with the final result of either accepted or rejected. */ +static void requestJobDocumentHandler( void ) +{ + char thingName[ MAX_THING_NAME_SIZE + 1 ] = { 0 }; + size_t thingNameLength = 0U; + char topicBuffer[ TOPIC_BUFFER_SIZE + 1 ] = { 0 }; + char messageBuffer[ START_JOB_MSG_LENGTH ] = { 0 }; + size_t topicLength = 0U; - LogInfo( ( "Received OtaJobEventStartTest callback from OTA Agent." ) ); + mqttWrapper_getThingName( thingName, &thingNameLength ); - err = OTA_SetImageState( OtaImageStateAccepted ); + /* + * AWS IoT Jobs library: + * Creates the topic string for a StartNextPendingJobExecution request. + * It used to check if any pending jobs are available. + */ + Jobs_StartNext( topicBuffer, + TOPIC_BUFFER_SIZE, + thingName, + ( uint16_t ) thingNameLength, + &topicLength ); - if( err == OtaErrNone ) - { - LogInfo( ( "New image validation succeeded in self test mode." ) ); - } - else - { - LogError( ( "Failed to set image state as accepted with error %d.", err ) ); - } + /* + * AWS IoT Jobs library: + * Creates the message string for a StartNextPendingJobExecution request. + * It will be sent on the topic created in the previous step. + */ + size_t messageLength = Jobs_StartNextMsg( "test", + 4U, + messageBuffer, + START_JOB_MSG_LENGTH ); + + mqttWrapper_publish( topicBuffer, + topicLength, + ( uint8_t * ) messageBuffer, + messageLength ); +} - break; +/*-----------------------------------------------------------*/ - case OtaJobEventProcessed: +static void initMqttDownloader( AfrOtaJobDocumentFields_t * jobFields ) +{ + char thingName[ MAX_THING_NAME_SIZE + 1 ] = { 0 }; + size_t thingNameLength = 0U; - LogDebug( ( "OTA Event processing completed. Freeing the event buffer to pool." ) ); - configASSERT( pData != NULL ); - prvOTAEventBufferFree( ( OtaEventData_t * ) pData ); + numOfBlocksRemaining = jobFields->fileSize / + mqttFileDownloader_CONFIG_BLOCK_SIZE; + numOfBlocksRemaining += ( jobFields->fileSize % + mqttFileDownloader_CONFIG_BLOCK_SIZE > 0 ) ? 1 : 0; + currentFileId = ( uint8_t ) jobFields->fileId; + currentBlockOffset = 0; + totalBytesReceived = 0; - break; + mqttWrapper_getThingName( thingName, &thingNameLength ); - case OtaJobEventSelfTestFailed: - LogDebug( ( "Received OtaJobEventSelfTestFailed callback from OTA Agent." ) ); + /* + * MQTT streams Library: + * Initializing the MQTT streams downloader. Passing the + * parameters extracted from the AWS IoT OTA jobs document + * using OTA jobs parser. + */ + mqttDownloader_init( &mqttFileDownloaderContext, + jobFields->imageRef, + jobFields->imageRefLen, + thingName, + thingNameLength, + DATA_TYPE_JSON ); + + mqttWrapper_subscribe( mqttFileDownloaderContext.topicStreamData, + mqttFileDownloaderContext.topicStreamDataLength ); +} - /* Requires manual activation of previous image as self-test for - * new image downloaded failed.*/ - LogError( ( "OTA Self-test failed for new image. shutting down OTA Agent." ) ); +/*-----------------------------------------------------------*/ - /* Shutdown OTA Agent, if it is required that the unsubscribe operations are not - * performed while shutting down please set the second parameter to 0 instead of 1. */ - OTA_Shutdown( 0, 1 ); +static bool convertSignatureToDER( AfrOtaJobDocumentFields_t * jobFields ) +{ + bool returnVal = true; + size_t decodedSignatureLength = 0; - break; - default: - LogWarn( ( "Received an unhandled callback event from OTA Agent, event = %d", event ) ); + Base64Status_t xResult = base64_Decode( OtaImageSingatureDecoded, + sizeof( OtaImageSingatureDecoded ), + &decodedSignatureLength, + jobFields->signature, + jobFields->signatureLen ); - break; + if( xResult == Base64Success ) + { + jobFields->signature = OtaImageSingatureDecoded; + jobFields->signatureLen = decodedSignatureLength; + } + else + { + returnVal = false; } + + return returnVal; } /*-----------------------------------------------------------*/ -static void prvProcessIncomingMessage( void * pxSubscriptionContext, - MQTTPublishInfo_t * pxPublishInfo ) +static int16_t handleMqttStreamsBlockArrived( uint8_t * data, + size_t dataLength ) { - bool isMatched = false; + int16_t writeblockRes = -1; - { - ( void ) MQTT_MatchTopic( pxPublishInfo->pTopicName, - pxPublishInfo->topicNameLength, - OTA_JOB_NOTIFY_TOPIC_FILTER, - OTA_JOB_NOTIFY_TOPIC_FILTER_LENGTH, - &isMatched ); + LogInfo( "Downloaded block %u of %u. \n", currentBlockOffset, ( currentBlockOffset + numOfBlocksRemaining ) ); - if( isMatched == true ) - { - prvProcessIncomingJobMessage( pxSubscriptionContext, pxPublishInfo ); - } - } + writeblockRes = otaPal_WriteBlock( &jobFields, + totalBytesReceived, + data, + dataLength ); - if( isMatched == false ) + if( writeblockRes > 0 ) { - ( void ) MQTT_MatchTopic( pxPublishInfo->pTopicName, - pxPublishInfo->topicNameLength, - OTA_DATA_STREAM_TOPIC_FILTER, - OTA_DATA_STREAM_TOPIC_FILTER_LENGTH, - &isMatched ); - - if( isMatched == true ) - { - prvProcessIncomingData( pxSubscriptionContext, pxPublishInfo ); - } + totalBytesReceived += writeblockRes; } + + return writeblockRes; } /*-----------------------------------------------------------*/ -static void prvProcessIncomingData( void * pxSubscriptionContext, - MQTTPublishInfo_t * pPublishInfo ) +static void requestDataBlock( void ) { - BaseType_t isMatch = pdFALSE; - OtaEventData_t * pData; - OtaEventMsg_t eventMsg = { 0 }; - + char getStreamRequest[ GET_STREAM_REQUEST_BUFFER_SIZE ]; + size_t getStreamRequestLength = 0U; - configASSERT( pPublishInfo != NULL ); - ( void ) pxSubscriptionContext; + /* + * MQTT streams Library: + * Creating the Get data block request. MQTT streams library only + * creates the get block request. To publish the request, MQTT libraries + * like coreMQTT are required. + */ + getStreamRequestLength = mqttDownloader_createGetDataBlockRequest( mqttFileDownloaderContext.dataType, + currentFileId, + mqttFileDownloader_CONFIG_BLOCK_SIZE, + ( uint16_t ) currentBlockOffset, + NUM_OF_BLOCKS_REQUESTED, + getStreamRequest, + GET_STREAM_REQUEST_BUFFER_SIZE ); + + mqttWrapper_publish( mqttFileDownloaderContext.topicGetStream, + mqttFileDownloaderContext.topicGetStreamLength, + ( uint8_t * ) getStreamRequest, + getStreamRequestLength ); +} - isMatch = prvMatchClientIdentifierInTopic( pPublishInfo->pTopicName, - pPublishInfo->topicNameLength, - pcThingName, - xThingNameLength ); +/*-----------------------------------------------------------*/ - if( isMatch == pdTRUE ) - { - if( pPublishInfo->payloadLength <= OTA_DATA_BLOCK_SIZE ) - { - pData = prvOTAEventBufferGet(); +static bool closeFileHandler( void ) +{ + return( OtaPalSuccess == otaPal_CloseFile( &jobFields ) ); +} - if( pData != NULL ) - { - memcpy( pData->data, pPublishInfo->pPayload, pPublishInfo->payloadLength ); - pData->dataLength = pPublishInfo->payloadLength; - eventMsg.eventId = OtaAgentEventReceivedFileBlock; - eventMsg.pEventData = pData; +/*-----------------------------------------------------------*/ - /* Send job document received event. */ - OTA_SignalEvent( &eventMsg ); - } - else - { - LogError( ( "Error: No OTA data buffers available.\r\n" ) ); - } - } - else - { - LogError( ( "Received OTA data block of size (%d) larger than maximum size(%d) defined. ", - pPublishInfo->payloadLength, - OTA_DATA_BLOCK_SIZE ) ); - } - } - else - { - LogWarn( ( "Received data block on an unsolicited topic, thing name does not match. topic: %.*s ", - pPublishInfo->topicNameLength, - pPublishInfo->pTopicName ) ); - } +static bool imageActivationHandler( void ) +{ + return( OtaPalSuccess == otaPal_ActivateNewImage( &jobFields ) ); } /*-----------------------------------------------------------*/ -static void prvProcessIncomingJobMessage( void * pxSubscriptionContext, - MQTTPublishInfo_t * pPublishInfo ) +static OtaPalJobDocProcessingResult_t receivedJobDocumentHandler( OtaJobEventData_t * jobDoc ) { - OtaEventData_t * pData; - OtaEventMsg_t eventMsg = { 0 }; - BaseType_t isMatch = pdFALSE; + bool parseJobDocument = false; + bool handled = false; + char * jobId; + const char ** jobIdptr = &jobId; + size_t jobIdLength = 0U; + OtaPalJobDocProcessingResult_t xResult = OtaPalJobDocFileCreateFailed; + + memset( &jobFields, 0, sizeof( jobFields ) ); - ( void ) pxSubscriptionContext; - configASSERT( pPublishInfo != NULL ); + /* + * AWS IoT Jobs library: + * Extracting the job ID from the received OTA job document. + */ + jobIdLength = Jobs_GetJobId( ( char * ) jobDoc->jobData, jobDoc->jobDataLength, jobIdptr ); - isMatch = prvMatchClientIdentifierInTopic( pPublishInfo->pTopicName, - pPublishInfo->topicNameLength, - pcThingName, - xThingNameLength ); + if( jobIdLength ) + { + if( strncmp( globalJobId, jobId, jobIdLength ) ) + { + parseJobDocument = true; + strncpy( globalJobId, jobId, jobIdLength ); + } + else + { + xResult = OtaPalJobDocFileCreated; + } + } - if( isMatch == pdTRUE ) + if( parseJobDocument ) { - if( pPublishInfo->payloadLength <= OTA_DATA_BLOCK_SIZE ) + handled = jobDocumentParser( ( char * ) jobDoc->jobData, jobDoc->jobDataLength, &jobFields ); + + if( handled ) { - LogInfo( ( "Received OTA job message, size: %d.\n\n", pPublishInfo->payloadLength ) ); - pData = prvOTAEventBufferGet(); + initMqttDownloader( &jobFields ); - if( pData != NULL ) - { - memcpy( pData->data, pPublishInfo->pPayload, pPublishInfo->payloadLength ); - pData->dataLength = pPublishInfo->payloadLength; - eventMsg.eventId = OtaAgentEventReceivedJobDocument; - eventMsg.pEventData = pData; + /* AWS IoT core returns the signature in a PEM format. We need to + * convert it to DER format for image signature verification. */ + + handled = convertSignatureToDER( &jobFields ); - /* Send job document received event. */ - OTA_SignalEvent( &eventMsg ); + if( handled ) + { + xResult = otaPal_CreateFileForRx( &jobFields ); } else { - LogError( ( "Error: No OTA data buffers available.\r\n" ) ); + LogError( "Failed to decode the image signature to DER format." ); } } - else - { - LogError( ( "Received OTA job message size (%d) is larger than the OTA maximum size (%d) defined.\n\n", pPublishInfo->payloadLength, OTA_DATA_BLOCK_SIZE ) ); - } - } - else - { - LogWarn( ( "Received a job message on an unsolicited topic, thing name does not match. topic: %.*s ", - pPublishInfo->topicNameLength, - pPublishInfo->pTopicName ) ); } -} + return xResult; +} /*-----------------------------------------------------------*/ -static BaseType_t prvMatchClientIdentifierInTopic( const char * pTopic, - size_t topicNameLength, - const char * pClientIdentifier, - size_t clientIdentifierLength ) +static uint16_t getFreeOTABuffers( void ) { - BaseType_t isMatch = pdFALSE; - size_t idx; - size_t matchIdx = 0; + uint32_t ulIndex = 0; + uint16_t freeBuffers = 0; - for( idx = OTA_TOPIC_CLIENT_IDENTIFIER_START_IDX; idx < topicNameLength; idx++ ) + if( xSemaphoreTake( bufferSemaphore, portMAX_DELAY ) == pdTRUE ) { - if( matchIdx == clientIdentifierLength ) - { - if( pTopic[ idx ] == '/' ) - { - isMatch = pdTRUE; - } - - break; - } - else + for( ulIndex = 0; ulIndex < MAX_NUM_OF_OTA_DATA_BUFFERS; ulIndex++ ) { - if( pClientIdentifier[ matchIdx ] != pTopic[ idx ] ) + if( dataBuffers[ ulIndex ].bufferUsed == false ) { - break; + freeBuffers++; } } - matchIdx++; + ( void ) xSemaphoreGive( bufferSemaphore ); + } + else + { + LogInfo( "Failed to get buffer semaphore. \n" ); } - return isMatch; + return freeBuffers; } /*-----------------------------------------------------------*/ -static void prvCommandCallback( MQTTAgentCommandContext_t * pCommandContext, - MQTTAgentReturnInfo_t * pxReturnInfo ) +static void freeOtaDataEventBuffer( OtaDataEvent_t * const pxBuffer ) { - if( pCommandContext->xTaskToNotify != NULL ) + if( xSemaphoreTake( bufferSemaphore, portMAX_DELAY ) == pdTRUE ) + { + pxBuffer->bufferUsed = false; + ( void ) xSemaphoreGive( bufferSemaphore ); + } + else { - xTaskNotify( pCommandContext->xTaskToNotify, ( uint32_t ) ( pxReturnInfo->returnCode ), eSetValueWithOverwrite ); + LogInfo( "Failed to get buffer semaphore.\n" ); } } - /*-----------------------------------------------------------*/ -static void prvSubscribeCommandCallback( MQTTAgentCommandContext_t * pxCommandContext, - MQTTAgentReturnInfo_t * pxReturnInfo ) +/* Implemented for use by the MQTT library */ +bool otaDemo_handleIncomingMQTTMessage( char * topic, + size_t topicLength, + uint8_t * message, + size_t messageLength ) { - MQTTAgentSubscribeArgs_t * pxSubscribeArgs = ( MQTTAgentSubscribeArgs_t * ) pxCommandContext->pArgs; - BaseType_t xResult; + OtaEventMsg_t nextEvent = { 0 }; + char thingName[ MAX_THING_NAME_SIZE + 1 ] = { 0 }; + size_t thingNameLength = 0U; + + /* + * MQTT streams Library: + * Checks if the incoming message contains the requested data block. It is performed by + * comparing the incoming MQTT message topic with MQTT streams topics. + */ + bool handled = mqttDownloader_isDataBlockReceived( &mqttFileDownloaderContext, topic, topicLength ); - if( pxReturnInfo->returnCode == MQTTSuccess ) + if( handled ) { - xResult = xAddMQTTTopicFilterCallback( pxSubscribeArgs->pSubscribeInfo[ 0 ].pTopicFilter, - pxSubscribeArgs->pSubscribeInfo[ 0 ].topicFilterLength, - prvProcessIncomingMessage, - NULL, - pdFALSE ); - configASSERT( xResult == pdTRUE ); + nextEvent.eventId = OtaAgentEventReceivedFileBlock; + OtaDataEvent_t * dataBuf = getOtaDataEventBuffer(); + memcpy( dataBuf->data, message, messageLength ); + nextEvent.dataEvent = dataBuf; + dataBuf->dataLength = messageLength; + OtaSendEvent_FreeRTOS( &nextEvent ); } - - if( pxCommandContext->xTaskToNotify != NULL ) + else { - xTaskNotify( pxCommandContext->xTaskToNotify, ( uint32_t ) ( pxReturnInfo->returnCode ), eSetValueWithOverwrite ); + mqttWrapper_getThingName( thingName, &thingNameLength ); + + /* + * AWS IoT Jobs library: + * Checks if a message comes from the start-next/accepted reserved topic. + */ + handled = Jobs_IsStartNextAccepted( topic, + topicLength, + thingName, + thingNameLength ); + + if( handled ) + { + memcpy( jobDocBuffer.jobData, message, messageLength ); + nextEvent.jobEvent = &jobDocBuffer; + jobDocBuffer.jobDataLength = messageLength; + nextEvent.eventId = OtaAgentEventReceivedJobDocument; + OtaSendEvent_FreeRTOS( &nextEvent ); + } } + + return handled; } /*-----------------------------------------------------------*/ -static void prvUnSubscribeCommandCallback( MQTTAgentCommandContext_t * pxCommandContext, - MQTTAgentReturnInfo_t * pxReturnInfo ) +static bool sendSuccessMessage( void ) { - MQTTAgentSubscribeArgs_t * pxSubscribeArgs = ( MQTTAgentSubscribeArgs_t * ) pxCommandContext->pArgs; + char thingName[ MAX_THING_NAME_SIZE + 1 ] = { 0 }; + size_t thingNameLength = 0U; + char topicBuffer[ TOPIC_BUFFER_SIZE + 1 ] = { 0 }; + size_t topicBufferLength = 0U; + char messageBuffer[ UPDATE_JOB_MSG_LENGTH ] = { 0 }; + bool result = true; + JobsStatus_t jobStatusResult; - if( pxReturnInfo->returnCode == MQTTSuccess ) + mqttWrapper_getThingName( thingName, &thingNameLength ); + + /* + * AWS IoT Jobs library: + * Creating the MQTT topic to update the status of OTA job. + */ + jobStatusResult = Jobs_Update( topicBuffer, + TOPIC_BUFFER_SIZE, + thingName, + ( uint16_t ) thingNameLength, + globalJobId, + ( uint16_t ) strnlen( globalJobId, 1000U ), + &topicBufferLength ); + + if( jobStatusResult == JobsSuccess ) { - vRemoveMQTTTopicFilterCallback( pxSubscribeArgs->pSubscribeInfo[ 0 ].pTopicFilter, - pxSubscribeArgs->pSubscribeInfo[ 0 ].topicFilterLength ); + /* + * AWS IoT Jobs library: + * Creating the message which contains the status of OTA job. + * It will be published on the topic created in the previous step. + */ + size_t messageBufferLength = Jobs_UpdateMsg( Succeeded, + "2", + 1U, + messageBuffer, + UPDATE_JOB_MSG_LENGTH ); + + result = mqttWrapper_publish( topicBuffer, + topicBufferLength, + ( uint8_t * ) messageBuffer, + messageBufferLength ); + + LogInfo( "\033[1;32mOTA Completed successfully!\033[0m\n" ); + globalJobId[ 0 ] = 0U; + + /* Clean up the job doc buffer so that it is ready for when we + * receive new job doc. */ + memset( &jobDocBuffer, 0, sizeof( jobDocBuffer ) ); } - - if( pxCommandContext->xTaskToNotify != NULL ) + else { - xTaskNotify( pxCommandContext->xTaskToNotify, ( uint32_t ) ( pxReturnInfo->returnCode ), eSetValueWithOverwrite ); + result = false; } + + return result; } /*-----------------------------------------------------------*/ - -static OtaMqttStatus_t prvMQTTSubscribe( const char * pTopicFilter, - uint16_t topicFilterLength, - uint8_t ucQoS ) +static bool jobDocumentParser( char * message, + size_t messageLength, + AfrOtaJobDocumentFields_t * jobFields ) { - MQTTStatus_t mqttStatus; - uint32_t ulNotifiedValue; - MQTTAgentSubscribeArgs_t xSubscribeArgs = { 0 }; - MQTTSubscribeInfo_t xSubscribeInfo = { 0 }; - BaseType_t result; - MQTTAgentCommandInfo_t xCommandParams = { 0 }; - MQTTAgentCommandContext_t xCommandContext = { 0 }; - OtaMqttStatus_t otaRet = OtaMqttSuccess; - - configASSERT( pTopicFilter != NULL ); - configASSERT( topicFilterLength > 0 ); - - xSubscribeInfo.pTopicFilter = pTopicFilter; - xSubscribeInfo.topicFilterLength = topicFilterLength; - xSubscribeInfo.qos = ucQoS; - xSubscribeArgs.pSubscribeInfo = &xSubscribeInfo; - xSubscribeArgs.numSubscriptions = 1; - - xCommandContext.pArgs = ( void * ) ( &xSubscribeArgs ); - xCommandContext.xTaskToNotify = xTaskGetCurrentTaskHandle(); - - xCommandParams.blockTimeMs = otaexampleMQTT_TIMEOUT_MS; - xCommandParams.cmdCompleteCallback = prvSubscribeCommandCallback; - xCommandParams.pCmdCompleteCallbackContext = ( void * ) &xCommandContext; + const char * jobDoc; + size_t jobDocLength = 0U; + int8_t fileIndex = 0; /* - * Wait for Agent to be connected before sending a subscribe message. + * AWS IoT Jobs library: + * Extracting the OTA job document from the jobs message recevied from AWS IoT core. */ - if( xGetMQTTAgentState() != MQTT_AGENT_STATE_CONNECTED ) + jobDocLength = Jobs_GetJobDocument( message, messageLength, &jobDoc ); + + if( jobDocLength != 0U ) { - ( void ) xWaitForMQTTAgentState( MQTT_AGENT_STATE_CONNECTED, portMAX_DELAY ); + do + { + /* + * AWS IoT Jobs library: + * Parsing the OTA job document to extract all of the parameters needed to download + * the new firmware. + */ + fileIndex = otaParser_parseJobDocFile( jobDoc, + jobDocLength, + fileIndex, + jobFields ); + } while( fileIndex > 0 ); } - xTaskNotifyStateClear( NULL ); + /* File index will be -1 if an error occured, and 0 if all files were + * processed. */ + return fileIndex == 0; +} - mqttStatus = MQTTAgent_Subscribe( &xGlobalMqttAgentContext, - &xSubscribeArgs, - &xCommandParams ); +/*-----------------------------------------------------------*/ - /* Block for command to complete so MQTTSubscribeInfo_t remains in scope for the - * duration of the command. */ - if( mqttStatus == MQTTSuccess ) - { - result = xTaskNotifyWait( 0, otaexampleMAX_UINT32, &ulNotifiedValue, portMAX_DELAY ); +static OtaDataEvent_t * getOtaDataEventBuffer( void ) +{ + uint32_t ulIndex = 0; + OtaDataEvent_t * freeBuffer = NULL; - if( result == pdTRUE ) - { - mqttStatus = ( MQTTStatus_t ) ( ulNotifiedValue ); - } - else + if( xSemaphoreTake( bufferSemaphore, portMAX_DELAY ) == pdTRUE ) + { + for( ulIndex = 0; ulIndex < MAX_NUM_OF_OTA_DATA_BUFFERS; ulIndex++ ) { - mqttStatus = MQTTRecvFailed; + if( dataBuffers[ ulIndex ].bufferUsed == false ) + { + dataBuffers[ ulIndex ].bufferUsed = true; + freeBuffer = &dataBuffers[ ulIndex ]; + break; + } } - } - - if( mqttStatus != MQTTSuccess ) - { - LogError( ( "Failed to SUBSCRIBE to topic with error = %u.", - mqttStatus ) ); - otaRet = OtaMqttSubscribeFailed; + ( void ) xSemaphoreGive( bufferSemaphore ); } else { - LogInfo( ( "Subscribed to topic %.*s.\n\n", - topicFilterLength, - pTopicFilter ) ); - - otaRet = OtaMqttSuccess; + LogInfo( "Failed to get buffer semaphore. \n" ); } - return otaRet; + return freeBuffer; } -static OtaMqttStatus_t prvMQTTPublish( const char * const pacTopic, - uint16_t topicLen, - const char * pMsg, - uint32_t msgSize, - uint8_t qos ) -{ - OtaMqttStatus_t otaRet = OtaMqttSuccess; - BaseType_t result; - MQTTStatus_t mqttStatus = MQTTBadParameter; - MQTTPublishInfo_t publishInfo = { MQTTQoS0 }; - MQTTAgentCommandInfo_t xCommandParams = { 0 }; - MQTTAgentCommandContext_t xCommandContext = { 0 }; - uint32_t ulNotifiedValue; - - configASSERT( qos <= MQTTQoS2 ); - - publishInfo.pTopicName = pacTopic; - publishInfo.topicNameLength = topicLen; - publishInfo.qos = ( MQTTQoS_t ) qos; - publishInfo.pPayload = pMsg; - publishInfo.payloadLength = msgSize; +/*-----------------------------------------------------------*/ - xCommandContext.xTaskToNotify = xTaskGetCurrentTaskHandle(); +static void processOTAEvents( void ) +{ + OtaEventMsg_t recvEvent = { 0 }; + OtaEvent_t recvEventId = 0; + static OtaEvent_t lastRecvEventId = OtaAgentEventStart; + OtaEventMsg_t nextEvent = { 0 }; - xCommandParams.blockTimeMs = otaexampleMQTT_TIMEOUT_MS; - xCommandParams.cmdCompleteCallback = prvCommandCallback; - xCommandParams.pCmdCompleteCallbackContext = ( void * ) &xCommandContext; + OtaReceiveEvent_FreeRTOS( &recvEvent ); + recvEventId = recvEvent.eventId; - /* - * Wait for Agent to be connected before sending a publish message. - */ - if( xGetMQTTAgentState() != MQTT_AGENT_STATE_CONNECTED ) + if( recvEventId != OtaAgentEventStart ) { - ( void ) xWaitForMQTTAgentState( MQTT_AGENT_STATE_CONNECTED, portMAX_DELAY ); + lastRecvEventId = recvEventId; } - - xTaskNotifyStateClear( NULL ); - - mqttStatus = MQTTAgent_Publish( &xGlobalMqttAgentContext, - &publishInfo, - &xCommandParams ); - - /* Block for command to complete so MQTTPublishInfo_t remains in scope for the - * duration of the command. */ - if( mqttStatus == MQTTSuccess ) + else { - result = xTaskNotifyWait( 0, otaexampleMAX_UINT32, &ulNotifiedValue, portMAX_DELAY ); - - if( result != pdTRUE ) - { - mqttStatus = MQTTSendFailed; - } - else + if( lastRecvEventId == OtaAgentEventRequestFileBlock ) { - mqttStatus = ( MQTTStatus_t ) ( ulNotifiedValue ); + /* No current event and we have not received the new block + * since last timeout, try sending the request for block again. */ + recvEventId = lastRecvEventId; + + /* It is likely that the network was disconnected and reconnected, + * we should wait for the MQTT connection to go up. */ + while( !mqttWrapper_isConnected() ) + { + vTaskDelay( pdMS_TO_TICKS( 100 ) ); + } } } - if( mqttStatus != MQTTSuccess ) - { - LogError( ( "Failed to send PUBLISH packet to broker with error = %u.", mqttStatus ) ); - otaRet = OtaMqttPublishFailed; - } - else + switch( recvEventId ) { - LogInfo( ( "Sent PUBLISH packet to broker %.*s to broker.\n\n", - topicLen, - pacTopic ) ); + case OtaAgentEventRequestJobDocument: + LogInfo( "Request Job Document event Received \n" ); + LogInfo( "-------------------------------------\n" ); + requestJobDocumentHandler(); + otaAgentState = OtaAgentStateRequestingJob; + break; - otaRet = OtaMqttSuccess; - } + case OtaAgentEventReceivedJobDocument: + LogInfo( "Received Job Document event Received \n" ); + LogInfo( "-------------------------------------\n" ); - return otaRet; -} + if( otaAgentState == OtaAgentStateSuspended ) + { + LogInfo( "OTA-Agent is in Suspend State. Hence dropping Job Document. \n" ); + break; + } -static OtaMqttStatus_t prvMQTTUnsubscribe( const char * pTopicFilter, - uint16_t topicFilterLength, - uint8_t ucQoS ) -{ - MQTTStatus_t mqttStatus; - uint32_t ulNotifiedValue; - MQTTAgentSubscribeArgs_t xSubscribeArgs = { 0 }; - MQTTSubscribeInfo_t xSubscribeInfo = { MQTTQoS0 }; - BaseType_t result; - MQTTAgentCommandInfo_t xCommandParams = { 0 }; - MQTTAgentCommandContext_t xCommandContext = { 0 }; - OtaMqttStatus_t otaRet = OtaMqttSuccess; + switch( receivedJobDocumentHandler( recvEvent.jobEvent ) ) + { + case OtaPalJobDocFileCreated: + LogInfo( "Received OTA Job. \n" ); + nextEvent.eventId = OtaAgentEventRequestFileBlock; + OtaSendEvent_FreeRTOS( &nextEvent ); + otaAgentState = OtaAgentStateCreatingFile; + break; + + case OtaPalJobDocFileCreateFailed: + case OtaPalNewImageBootFailed: + case OtaPalJobDocProcessingStateInvalid: + LogInfo( "This is not an OTA job \n" ); + break; + + case OtaPalNewImageBooted: + ( void ) sendSuccessMessage(); + + /* Short delay before restarting the loop. This allows IoT core + * to update the status of the job. */ + vTaskDelay( pdMS_TO_TICKS( 5000 ) ); + + /* Get ready for new OTA job. */ + nextEvent.eventId = OtaAgentEventRequestJobDocument; + OtaSendEvent_FreeRTOS( &nextEvent ); + break; + } + + break; - configASSERT( pTopicFilter != NULL ); - configASSERT( topicFilterLength > 0 ); - configASSERT( ucQoS <= MQTTQoS2 ); + case OtaAgentEventRequestFileBlock: + otaAgentState = OtaAgentStateRequestingFileBlock; + LogInfo( "Request File Block event Received \n" ); + LogInfo( "-----------------------------------\n" ); + + if( currentBlockOffset == 0 ) + { + LogInfo( "Starting The Download. \n" ); + } - xSubscribeInfo.pTopicFilter = pTopicFilter; - xSubscribeInfo.topicFilterLength = topicFilterLength; - xSubscribeInfo.qos = ( MQTTQoS_t ) ucQoS; - xSubscribeArgs.pSubscribeInfo = &xSubscribeInfo; - xSubscribeArgs.numSubscriptions = 1; + requestDataBlock(); + LogInfo( "ReqSent----------------------------\n" ); + break; + case OtaAgentEventReceivedFileBlock: + LogInfo( "Received File Block event Received \n" ); + LogInfo( "---------------------------------------\n" ); - xCommandContext.xTaskToNotify = xTaskGetCurrentTaskHandle(); - xCommandContext.pArgs = ( void * ) ( &xSubscribeArgs ); + if( otaAgentState == OtaAgentStateSuspended ) + { + LogInfo( "OTA-Agent is in Suspend State. Hence dropping File Block. \n" ); + freeOtaDataEventBuffer( recvEvent.dataEvent ); + break; + } - xCommandParams.blockTimeMs = otaexampleMQTT_TIMEOUT_MS; - xCommandParams.cmdCompleteCallback = prvUnSubscribeCommandCallback; - xCommandParams.pCmdCompleteCallbackContext = ( void * ) &xCommandContext; + uint8_t decodedData[ mqttFileDownloader_CONFIG_BLOCK_SIZE ]; + size_t decodedDataLength = 0; + MQTTFileDownloaderStatus_t xReturnStatus; + int16_t result = -1; + int32_t fileId; + int32_t blockId; + int32_t blockSize; + static int32_t lastReceivedblockId = -1; + + /* + * MQTT streams Library: + * Extracting and decoding the received data block from the incoming MQTT message. + */ + xReturnStatus = mqttDownloader_processReceivedDataBlock( + &mqttFileDownloaderContext, + recvEvent.dataEvent->data, + recvEvent.dataEvent->dataLength, + &fileId, + &blockId, + &blockSize, + decodedData, + &decodedDataLength ); + + if( xReturnStatus != MQTTFileDownloaderSuccess ) + { + /* There was some failure in trying to decode the block. */ + } + else if( fileId != jobFields.fileId ) + { + /* Error - the file ID doesn't match with the one we received in the job document. */ + } + else if( blockSize > mqttFileDownloader_CONFIG_BLOCK_SIZE ) + { + /* Error - the block size doesn't match with what we requested. It can be smaller as + * the last block may or may not be of exact size. */ + } + else if( blockId <= lastReceivedblockId ) + { + /* Ignore this block. */ + } + else + { + result = handleMqttStreamsBlockArrived( decodedData, decodedDataLength ); + lastReceivedblockId = blockId; + } - LogInfo( ( " Unsubscribing to topic filter: %s", pTopicFilter ) ); - xTaskNotifyStateClear( NULL ); + freeOtaDataEventBuffer( recvEvent.dataEvent ); + if( result > 0 ) + { + numOfBlocksRemaining--; + currentBlockOffset++; + } - mqttStatus = MQTTAgent_Unsubscribe( &xGlobalMqttAgentContext, - &xSubscribeArgs, - &xCommandParams ); + if( ( numOfBlocksRemaining % 10 ) == 0 ) + { + LogInfo( "Free OTA buffers %u", getFreeOTABuffers() ); + } - /* Block for command to complete so MQTTSubscribeInfo_t remains in scope for the - * duration of the command. */ - if( mqttStatus == MQTTSuccess ) - { - result = xTaskNotifyWait( 0, otaexampleMAX_UINT32, &ulNotifiedValue, portMAX_DELAY ); + if( numOfBlocksRemaining == 0 ) + { + nextEvent.eventId = OtaAgentEventCloseFile; + OtaSendEvent_FreeRTOS( &nextEvent ); + } + else + { + if( currentBlockOffset % NUM_OF_BLOCKS_REQUESTED == 0 ) + { + nextEvent.eventId = OtaAgentEventRequestFileBlock; + OtaSendEvent_FreeRTOS( &nextEvent ); + } + } - if( result == pdTRUE ) - { - mqttStatus = ( MQTTStatus_t ) ( ulNotifiedValue ); - } - else - { - mqttStatus = MQTTRecvFailed; - } - } + break; - if( mqttStatus != MQTTSuccess ) - { - LogError( ( "Failed to UNSUBSCRIBE from topic %.*s with error = %u.", - topicFilterLength, - pTopicFilter, - mqttStatus ) ); + case OtaAgentEventCloseFile: + LogInfo( "Close file event Received \n" ); + LogInfo( "-----------------------\n" ); - otaRet = OtaMqttUnsubscribeFailed; - } - else - { - LogInfo( ( "UNSUBSCRIBED from topic %.*s.\n\n", - topicFilterLength, - pTopicFilter ) ); + if( closeFileHandler() == true ) + { + nextEvent.eventId = OtaAgentEventActivateImage; + OtaSendEvent_FreeRTOS( &nextEvent ); + } - otaRet = OtaMqttSuccess; - } + break; - return otaRet; -} + case OtaAgentEventActivateImage: + LogInfo( "Activate Image event Received \n" ); + LogInfo( "-----------------------\n" ); -/*-----------------------------------------------------------*/ + if( imageActivationHandler() == true ) + { + nextEvent.eventId = OtaAgentEventActivateImage; + OtaSendEvent_FreeRTOS( &nextEvent ); + } -static void setOtaInterfaces( OtaInterfaces_t * pOtaInterfaces ) -{ - configASSERT( pOtaInterfaces != NULL ); - - /* Initialize OTA library OS Interface. */ - pOtaInterfaces->os.event.init = OtaInitEvent_FreeRTOS; - pOtaInterfaces->os.event.send = OtaSendEvent_FreeRTOS; - pOtaInterfaces->os.event.recv = OtaReceiveEvent_FreeRTOS; - pOtaInterfaces->os.event.deinit = OtaDeinitEvent_FreeRTOS; - pOtaInterfaces->os.timer.start = OtaStartTimer_FreeRTOS; - pOtaInterfaces->os.timer.stop = OtaStopTimer_FreeRTOS; - pOtaInterfaces->os.timer.delete = OtaDeleteTimer_FreeRTOS; - pOtaInterfaces->os.mem.malloc = Malloc_FreeRTOS; - pOtaInterfaces->os.mem.free = Free_FreeRTOS; - - /* Initialize the OTA library MQTT Interface.*/ - pOtaInterfaces->mqtt.subscribe = prvMQTTSubscribe; - pOtaInterfaces->mqtt.publish = prvMQTTPublish; - pOtaInterfaces->mqtt.unsubscribe = prvMQTTUnsubscribe; - - /* Initialize the OTA library PAL Interface.*/ - pOtaInterfaces->pal.getPlatformImageState = xOtaPalGetPlatformImageState; - pOtaInterfaces->pal.setPlatformImageState = xOtaPalSetPlatformImageState; - pOtaInterfaces->pal.writeBlock = xOtaPalWriteBlock; - pOtaInterfaces->pal.activate = xOtaPalActivateNewImage; - pOtaInterfaces->pal.closeFile = xOtaPalCloseFile; - pOtaInterfaces->pal.reset = xOtaPalResetDevice; - pOtaInterfaces->pal.abort = xOtaPalAbort; - pOtaInterfaces->pal.createFile = xOtaPalCreateFileForRx; -} + otaAgentState = OtaAgentStateStopped; + break; -static void prvSuspendOTAUpdate( void ) -{ - if( ( OTA_GetState() != OtaAgentStateSuspended ) && ( OTA_GetState() != OtaAgentStateStopped ) ) - { - OTA_Suspend(); - while( ( OTA_GetState() != OtaAgentStateSuspended ) && - ( OTA_GetState() != OtaAgentStateStopped ) ) - { - vTaskDelay( pdMS_TO_TICKS( otaexampleTASK_DELAY_MS ) ); - } - } -} + case OtaAgentEventSuspend: + LogInfo( "Suspend Event Received \n" ); + LogInfo( "-----------------------\n" ); + otaAgentState = OtaAgentStateSuspended; + break; -static void prvResumeOTAUpdate( void ) -{ - if( OTA_GetState() == OtaAgentStateSuspended ) - { - OTA_Resume(); + case OtaAgentEventResume: + LogInfo( "Resume Event Received \n" ); + LogInfo( "---------------------\n" ); + otaAgentState = OtaAgentStateRequestingJob; + nextEvent.eventId = OtaAgentEventRequestJobDocument; + OtaSendEvent_FreeRTOS( &nextEvent ); - while( OTA_GetState() == OtaAgentStateSuspended ) - { - vTaskDelay( pdMS_TO_TICKS( otaexampleTASK_DELAY_MS ) ); - } + default: + break; } } +/*-----------------------------------------------------------*/ + void vOTAUpdateTask( void * pvParam ) { /* FreeRTOS APIs return status. */ BaseType_t xResult = pdPASS; - /* OTA library return status. */ - OtaErr_t otaRet = OtaErrNone; - - /* OTA event message used for sending event to OTA Agent.*/ - OtaEventMsg_t eventMsg = { 0 }; - - /* OTA interface context required for library interface functions.*/ - OtaInterfaces_t otaInterfaces; - - /* OTA library packet statistics per job.*/ - OtaAgentStatistics_t otaStatistics = { 0 }; - - ( void ) pvParam; - /* Set OTA Library interfaces.*/ - setOtaInterfaces( &otaInterfaces ); - LogInfo( ( "OTA over MQTT demo, Application version %u.%u.%u", appFirmwareVersion.u.x.major, appFirmwareVersion.u.x.minor, @@ -1204,36 +1136,6 @@ void vOTAUpdateTask( void * pvParam ) } } - if( xResult == pdPASS ) - { - /* - * Topic is an unsolicited topic, ie a subscription is not required with the MQTT broker. - * Messages on this topic is directly sent to client. Hence this topic filter is added as - * a static entry in the MQTT agent topic filter store. Last parameter indicates MQTT agent - * should not subscribe to topic on a reconnection. - */ - xResult = xAddMQTTTopicFilterCallback( OTA_JOB_ACCEPTED_RESPONSE_TOPIC_FILTER, - OTA_JOB_ACCEPTED_RESPONSE_TOPIC_FILTER_LENGTH, - prvProcessIncomingJobMessage, - NULL, - pdFALSE ); - } - - if( xResult == pdPASS ) - { - memset( eventBuffer, 0x00, sizeof( eventBuffer ) ); - - if( ( otaRet = OTA_Init( &otaBuffer, - &otaInterfaces, - ( const uint8_t * ) ( pcThingName ), - otaAppCallback ) ) != OtaErrNone ) - { - LogError( ( "Failed to initialize OTA Agent, exiting = %u.", - otaRet ) ); - xResult = pdFAIL; - } - } - if( xResult == pdPASS ) { if( ( xResult = xTaskCreate( prvOTAAgentTask, @@ -1249,45 +1151,10 @@ void vOTAUpdateTask( void * pvParam ) } } - /***************************Start OTA demo loop. ******************************/ - - if( xResult == pdPASS ) - { - /* Start the OTA Agent.*/ - eventMsg.eventId = OtaAgentEventStart; - OTA_SignalEvent( &eventMsg ); - - while( OTA_GetState() != OtaAgentStateStopped ) - { - /* Get OTA statistics for currently executing job. */ - OTA_GetStatistics( &otaStatistics ); - LogInfo( ( " Received: %u Queued: %u Processed: %u Dropped: %u", - otaStatistics.otaPacketsReceived, - otaStatistics.otaPacketsQueued, - otaStatistics.otaPacketsProcessed, - otaStatistics.otaPacketsDropped ) ); - - if( xWaitForMQTTAgentState( MQTT_AGENT_STATE_DISCONNECTED, - pdMS_TO_TICKS( otaexampleTASK_DELAY_MS ) ) == pdTRUE ) - { - /* Suspend ongoing OTA job if any until MQTT agent is reconnected. */ - prvSuspendOTAUpdate(); - - ( void ) xWaitForMQTTAgentState( MQTT_AGENT_STATE_CONNECTED, portMAX_DELAY ); - - /* Resume OTA Update so that agent checks for any new jobs during a lost connection. */ - prvResumeOTAUpdate(); - } - } - } + vTaskDelay( portMAX_DELAY ); LogInfo( ( "OTA agent task stopped. Exiting OTA demo." ) ); - - /* Unconditionally remove the static subscription. */ - vRemoveMQTTTopicFilterCallback( OTA_JOB_ACCEPTED_RESPONSE_TOPIC_FILTER, - OTA_JOB_ACCEPTED_RESPONSE_TOPIC_FILTER_LENGTH ); - if( pcThingName != NULL ) { vPortFree( pcThingName ); diff --git a/examples/evkbmimxrt1060/bootloader/signing_pub_key.c b/examples/evkbmimxrt1060/bootloader/signing_pub_key.c deleted file mode 100644 index dc0943f..0000000 --- a/examples/evkbmimxrt1060/bootloader/signing_pub_key.c +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy of - * this software and associated documentation files (the "Software"), to deal in - * the Software without restriction, including without limitation the rights to - * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of - * the Software, and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS - * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR - * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - * http://www.FreeRTOS.org - * http://aws.amazon.com/freertos - * - * 1 tab == 4 spaces! - */ - -#include "mcuboot_config.h" - -#if defined( MCUBOOT_SIGN_RSA ) - -#error Please use MCUBoot imgtool.py to generate an RSA signing key \ - and replace this file with the output of the tool. - -const unsigned char rsa_pub_key[] = { 0x00 }; -const unsigned int rsa_pub_key_len = 0; - -#elif defined( MCUBOOT_SIGN_EC256 ) - -#error Please use MCUBoot imgtool.py to generate an EC signing key \ - and replace this file with the output of the tool. - -const unsigned char ecdsa_pub_key[] = { 0x00 }; -const unsigned int ecdsa_pub_key_len = 0; - -#endif /* if defined( MCUBOOT_SIGN_RSA ) */ diff --git a/examples/evkbmimxrt1060/defender/include/FreeRTOSConfig.h b/examples/evkbmimxrt1060/defender/include/FreeRTOSConfig.h index 2629dd3..1fee882 100644 --- a/examples/evkbmimxrt1060/defender/include/FreeRTOSConfig.h +++ b/examples/evkbmimxrt1060/defender/include/FreeRTOSConfig.h @@ -76,6 +76,9 @@ extern void vLoggingPrintf( const char * pcFormat, #define configOVERRIDE_DEFAULT_TICK_CONFIGURATION 0 #define configRECORD_STACK_HIGH_ADDRESS 1 +/* Task notification settings. */ +#define configTASK_NOTIFICATION_ARRAY_ENTRIES ( 4 ) + /* Co-routine definitions. */ #define configUSE_CO_ROUTINES 0 #define configMAX_CO_ROUTINE_PRIORITIES ( 2 ) diff --git a/examples/evkbmimxrt1060/defender/include/MQTTFileDownloader_config.h b/examples/evkbmimxrt1060/defender/include/MQTTFileDownloader_config.h new file mode 100644 index 0000000..6d7a256 --- /dev/null +++ b/examples/evkbmimxrt1060/defender/include/MQTTFileDownloader_config.h @@ -0,0 +1,27 @@ +/* + * AWS IoT Core MQTT File Streams Embedded C v1.1.0 + * Copyright (C) 2023 Amazon.com, Inc. and its affiliates. All Rights Reserved. + * SPDX-License-Identifier: MIT + * + * Licensed under the MIT License. See the LICENSE accompanying this file + * for the specific language governing permissions and limitations under + * the License. + */ + +/** + * @file MQTTFileDownloader_config.h + * @brief Configs for MQTT stream. + */ + +#ifndef MQTT_FILE_DOWNLOADER_CONFIG_H +#define MQTT_FILE_DOWNLOADER_CONFIG_H + +/** + * Configure the Maximum size of the data payload. The smallest value is 256 bytes, + * maximum is 128KB. + */ +#ifndef mqttFileDownloader_CONFIG_BLOCK_SIZE +#define mqttFileDownloader_CONFIG_BLOCK_SIZE 512U +#endif + +#endif /* #ifndef MQTT_FILE_DOWNLOADER_DEFAULT_H */ diff --git a/examples/evkbmimxrt1060/pubsub/app_main.c b/examples/evkbmimxrt1060/pubsub/app_main.c index 107558d..a6a2467 100644 --- a/examples/evkbmimxrt1060/pubsub/app_main.c +++ b/examples/evkbmimxrt1060/pubsub/app_main.c @@ -47,7 +47,7 @@ * information for the device to connect to broker and perform OTA updates. Disabling the flag results * in disabling the CLI task and execution of the demo tasks in normal device operation mode. */ -#define appmainPROVISIONING_MODE ( 1 ) +#define appmainPROVISIONING_MODE ( 0 ) /** * @brief Subscribe Publish demo tasks configuration. @@ -55,7 +55,7 @@ * to a topic, publishing messages to a topic and reporting the incoming messages on subscribed topic. * Number of subscribe publish demo tasks to be spawned is configurable. */ -#define appmainMQTT_NUM_PUBSUB_TASKS ( 2 ) +#define appmainMQTT_NUM_PUBSUB_TASKS ( 0 ) #define appmainMQTT_PUBSUB_TASK_STACK_SIZE ( 2048 ) #define appmainMQTT_PUBSUB_TASK_PRIORITY ( tskIDLE_PRIORITY + 1 ) @@ -97,6 +97,8 @@ int app_main( void ) xResult = KVStore_init(); + configPRINTF( ( "Version 0.1.0" ) ); + if( xResult == pdFAIL ) { configPRINTF( ( "Failed to initialize key value configuration store.\r\n" ) ); diff --git a/examples/evkbmimxrt1060/pubsub/include/FreeRTOSConfig.h b/examples/evkbmimxrt1060/pubsub/include/FreeRTOSConfig.h index 2629dd3..1fee882 100644 --- a/examples/evkbmimxrt1060/pubsub/include/FreeRTOSConfig.h +++ b/examples/evkbmimxrt1060/pubsub/include/FreeRTOSConfig.h @@ -76,6 +76,9 @@ extern void vLoggingPrintf( const char * pcFormat, #define configOVERRIDE_DEFAULT_TICK_CONFIGURATION 0 #define configRECORD_STACK_HIGH_ADDRESS 1 +/* Task notification settings. */ +#define configTASK_NOTIFICATION_ARRAY_ENTRIES ( 4 ) + /* Co-routine definitions. */ #define configUSE_CO_ROUTINES 0 #define configMAX_CO_ROUTINE_PRIORITIES ( 2 ) diff --git a/examples/evkbmimxrt1060/pubsub/include/MQTTFileDownloader_config.h b/examples/evkbmimxrt1060/pubsub/include/MQTTFileDownloader_config.h new file mode 100644 index 0000000..6d7a256 --- /dev/null +++ b/examples/evkbmimxrt1060/pubsub/include/MQTTFileDownloader_config.h @@ -0,0 +1,27 @@ +/* + * AWS IoT Core MQTT File Streams Embedded C v1.1.0 + * Copyright (C) 2023 Amazon.com, Inc. and its affiliates. All Rights Reserved. + * SPDX-License-Identifier: MIT + * + * Licensed under the MIT License. See the LICENSE accompanying this file + * for the specific language governing permissions and limitations under + * the License. + */ + +/** + * @file MQTTFileDownloader_config.h + * @brief Configs for MQTT stream. + */ + +#ifndef MQTT_FILE_DOWNLOADER_CONFIG_H +#define MQTT_FILE_DOWNLOADER_CONFIG_H + +/** + * Configure the Maximum size of the data payload. The smallest value is 256 bytes, + * maximum is 128KB. + */ +#ifndef mqttFileDownloader_CONFIG_BLOCK_SIZE +#define mqttFileDownloader_CONFIG_BLOCK_SIZE 512U +#endif + +#endif /* #ifndef MQTT_FILE_DOWNLOADER_DEFAULT_H */ diff --git a/examples/evkbmimxrt1060/pubsub/main.c b/examples/evkbmimxrt1060/pubsub/main.c index eabd49f..5ef34b1 100644 --- a/examples/evkbmimxrt1060/pubsub/main.c +++ b/examples/evkbmimxrt1060/pubsub/main.c @@ -325,6 +325,7 @@ int main( void ) } } + void vApplicationDaemonTaskStartupHook( void ) { /* Initialize file system. */ diff --git a/examples/evkbmimxrt1060/shadow/include/FreeRTOSConfig.h b/examples/evkbmimxrt1060/shadow/include/FreeRTOSConfig.h index 2629dd3..1fee882 100644 --- a/examples/evkbmimxrt1060/shadow/include/FreeRTOSConfig.h +++ b/examples/evkbmimxrt1060/shadow/include/FreeRTOSConfig.h @@ -76,6 +76,9 @@ extern void vLoggingPrintf( const char * pcFormat, #define configOVERRIDE_DEFAULT_TICK_CONFIGURATION 0 #define configRECORD_STACK_HIGH_ADDRESS 1 +/* Task notification settings. */ +#define configTASK_NOTIFICATION_ARRAY_ENTRIES ( 4 ) + /* Co-routine definitions. */ #define configUSE_CO_ROUTINES 0 #define configMAX_CO_ROUTINE_PRIORITIES ( 2 ) diff --git a/examples/evkbmimxrt1060/shadow/include/MQTTFileDownloader_config.h b/examples/evkbmimxrt1060/shadow/include/MQTTFileDownloader_config.h new file mode 100644 index 0000000..6d7a256 --- /dev/null +++ b/examples/evkbmimxrt1060/shadow/include/MQTTFileDownloader_config.h @@ -0,0 +1,27 @@ +/* + * AWS IoT Core MQTT File Streams Embedded C v1.1.0 + * Copyright (C) 2023 Amazon.com, Inc. and its affiliates. All Rights Reserved. + * SPDX-License-Identifier: MIT + * + * Licensed under the MIT License. See the LICENSE accompanying this file + * for the specific language governing permissions and limitations under + * the License. + */ + +/** + * @file MQTTFileDownloader_config.h + * @brief Configs for MQTT stream. + */ + +#ifndef MQTT_FILE_DOWNLOADER_CONFIG_H +#define MQTT_FILE_DOWNLOADER_CONFIG_H + +/** + * Configure the Maximum size of the data payload. The smallest value is 256 bytes, + * maximum is 128KB. + */ +#ifndef mqttFileDownloader_CONFIG_BLOCK_SIZE +#define mqttFileDownloader_CONFIG_BLOCK_SIZE 512U +#endif + +#endif /* #ifndef MQTT_FILE_DOWNLOADER_DEFAULT_H */ diff --git a/examples/evkbmimxrt1060/test/include/FreeRTOSConfig.h b/examples/evkbmimxrt1060/test/include/FreeRTOSConfig.h index 2629dd3..1fee882 100644 --- a/examples/evkbmimxrt1060/test/include/FreeRTOSConfig.h +++ b/examples/evkbmimxrt1060/test/include/FreeRTOSConfig.h @@ -76,6 +76,9 @@ extern void vLoggingPrintf( const char * pcFormat, #define configOVERRIDE_DEFAULT_TICK_CONFIGURATION 0 #define configRECORD_STACK_HIGH_ADDRESS 1 +/* Task notification settings. */ +#define configTASK_NOTIFICATION_ARRAY_ENTRIES ( 4 ) + /* Co-routine definitions. */ #define configUSE_CO_ROUTINES 0 #define configMAX_CO_ROUTINE_PRIORITIES ( 2 ) diff --git a/examples/evkbmimxrt1060/test/include/MQTTFileDownloader_config.h b/examples/evkbmimxrt1060/test/include/MQTTFileDownloader_config.h new file mode 100644 index 0000000..6d7a256 --- /dev/null +++ b/examples/evkbmimxrt1060/test/include/MQTTFileDownloader_config.h @@ -0,0 +1,27 @@ +/* + * AWS IoT Core MQTT File Streams Embedded C v1.1.0 + * Copyright (C) 2023 Amazon.com, Inc. and its affiliates. All Rights Reserved. + * SPDX-License-Identifier: MIT + * + * Licensed under the MIT License. See the LICENSE accompanying this file + * for the specific language governing permissions and limitations under + * the License. + */ + +/** + * @file MQTTFileDownloader_config.h + * @brief Configs for MQTT stream. + */ + +#ifndef MQTT_FILE_DOWNLOADER_CONFIG_H +#define MQTT_FILE_DOWNLOADER_CONFIG_H + +/** + * Configure the Maximum size of the data payload. The smallest value is 256 bytes, + * maximum is 128KB. + */ +#ifndef mqttFileDownloader_CONFIG_BLOCK_SIZE +#define mqttFileDownloader_CONFIG_BLOCK_SIZE 512U +#endif + +#endif /* #ifndef MQTT_FILE_DOWNLOADER_DEFAULT_H */ diff --git a/manifest.yml b/manifest.yml index 4566d28..958f3eb 100644 --- a/manifest.yml +++ b/manifest.yml @@ -4,100 +4,112 @@ description: |- "Reference IoT integration project using NXP i.MX RT1060 with EdgeLock® SE050 secure element and FreeRTOS LTS libraries" dependencies: - name: "FreeRTOS-Kernel" - version: "V10.5.1" + version: "V11.1.0" repository: type: "git" url: "https://github.com/FreeRTOS/FreeRTOS-Kernel.git" - path: "/Middleware/FreeRTOS/kernel" + path: "Middleware/FreeRTOS/kernel" - name: "coreJSON" - version: "v3.2.0" + version: "v3.3.0" repository: type: "git" url: "https://github.com/FreeRTOS/coreJSON.git" - path: "/Middleware/FreeRTOS/coreJSON" + path: "Middleware/FreeRTOS/coreJSON" - name: "coreMQTT" - version: "v2.1.1" + version: "v2.3.0" repository: type: "git" url: "https://github.com/FreeRTOS/coreMQTT.git" - path: "/Middleware/FreeRTOS/coreMQTT" + path: "Middleware/FreeRTOS/coreMQTT" - name: "corePKCS11" - version: "v3.5.0" + version: "v3.6.1" repository: type: "git" url: "https://github.com/FreeRTOS/corePKCS11.git" - path: "/Middleware/FreeRTOS/corePKCS11" + path: "Middleware/FreeRTOS/corePKCS11" - name: "backoffAlgorithm" - version: "v1.3.0" + version: "v1.4.1" repository: type: "git" url: "https://github.com/FreeRTOS/backoffAlgorithm" - path: "/Middleware/FreeRTOS/backoffAlgorithm" + path: "Middleware/FreeRTOS/backoffAlgorithm" - name: "coreMQTT-Agent" version: "v1.2.0" repository: type: "git" url: "https://github.com/FreeRTOS/coreMQTT-Agent.git" - path: "/Middleware/FreeRTOS/coreMQTT-Agent" + path: "Middleware/FreeRTOS/coreMQTT-Agent" - name: "device-defender" - version: "v1.3.0" + version: "v1.4.0" repository: type: "git" url: "https://github.com/aws/Device-Defender-for-AWS-IoT-embedded-sdk.git" - path: "/Middleware/AWS/device-defender" - - name: "ota" - version: "v3.4.0" - repository: - type: "git" - url: "https://github.com/aws/ota-for-AWS-IoT-embedded-sdk.git" - path: "/Middleware/AWS/ota" + path: "Middleware/AWS/device-defender" - name: "device-shadow" - version: "v1.3.0" + version: "v1.4.1" repository: type: "git" url: "https://github.com/aws/Device-Shadow-for-AWS-IoT-embedded-sdk.git" - path: "/Middleware/AWS/device-shadow" + path: "Middleware/AWS/device-shadow" - name: "mcux-sdk" version: "MCUX_2.10.0" repository: type: "git" url: "https://github.com/NXPmicro/mcux-sdk.git" - path: "/core" + path: "core" - name: "lwip" version: "STABLE-2_1_2_RELEASE" repository: type: "git" url: "https://github.com/lwip-tcpip/lwip.git" - path: "/Middleware/lwip" + path: "Middleware/lwip" - name: "mbedtls" version: "v2.26.0" repository: type: "git" url: "https://github.com/Mbed-TLS/mbedtls.git" - path: "/Middleware/mbedtls" + path: "Middleware/mbedtls" - name: "mcuboot" version: "v1.7.2" repository: type: "git" url: "https://github.com/mcu-tools/mcuboot.git" - path: "/Middleware/mcuboot" + path: "Middleware/mcuboot" - name: "tinycbor" version: "v0.6.0" repository: type: "git" url: "https://github.com/intel/tinycbor.git" - path: "/Middleware/tinycbor" + path: "Middleware/tinycbor" - name: "unity" version: "db878ccaedaea3d07b3c5443a00d131ecacd30b3" repository: type: "git" url: "https://github.com/ThrowTheSwitch/Unity.git" - path: "/Middleware/unity" + path: "Middleware/unity" - name: "FreeRTOS-Libraries-Integration-Tests" - version: "202210.01" + version: "692d509" repository: type: "git" url: "https://github.com/FreeRTOS/FreeRTOS-Libraries-Integration-Tests" - path: "/Middleware/FreeRTOS/tests" + path: "Middleware/FreeRTOS/tests" + - name: "aws-iot-core-mqtt-file-streams-embedded-c" + version: "v1.1.0" + repository: + type: "git" + url: "https://github.com/aws/aws-iot-core-mqtt-file-streams-embedded-c" + path: "Middleware/AWS/mqtt-stream" + - name: "pkcs11" + version: "v2.40_errata01" + repository: + type: "git" + url: "https://github.com/amazon-freertos/pkcs11.git" + path: "Middleware/FreeRTOS/pkcs11" + - name: "Jobs-for-AWS-IoT-embedded-sdk" + version: "v1.5.1" + repository: + type: "git" + url: "https://github.com/aws/Jobs-for-AWS-IoT-embedded-sdk.git" + path: "Middleware/AWS/jobs" license: "MIT" diff --git a/projects/evkmimxrt1060/bootloader/.cproject b/projects/evkmimxrt1060/bootloader/.cproject index 549607e..f2609e3 100644 --- a/projects/evkmimxrt1060/bootloader/.cproject +++ b/projects/evkmimxrt1060/bootloader/.cproject @@ -35,7 +35,7 @@ @@ -149,7 +150,7 @@