From c98f3168d91bd4cca79c5e1a6e3ab73f93151c37 Mon Sep 17 00:00:00 2001 From: Markus Sattler Date: Tue, 2 Jun 2015 23:47:42 +0200 Subject: [PATCH 01/18] add images --- doc/ESP_improved_stability.png | Bin 0 -> 18458 bytes doc/ESP_min.png | Bin 0 -> 6617 bytes doc/ESP_to_serial.png | Bin 0 -> 30183 bytes 3 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 doc/ESP_improved_stability.png create mode 100644 doc/ESP_min.png create mode 100644 doc/ESP_to_serial.png diff --git a/doc/ESP_improved_stability.png b/doc/ESP_improved_stability.png new file mode 100644 index 0000000000000000000000000000000000000000..74a7e01eeb22c808ca1e171367e09857fbeb8af4 GIT binary patch literal 18458 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 literal 0 HcmV?d00001 diff --git a/doc/ESP_min.png b/doc/ESP_min.png new file mode 100644 index 0000000000000000000000000000000000000000..59dc10c15aa4516fb5fc9f61c81ef51a68bd0881 GIT binary patch literal 6617 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

lwoHhj((xZhdXqF2z54lGm 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 Date: Tue, 2 Jun 2015 23:55:29 +0200 Subject: [PATCH 02/18] add new schematics to README.md --- README.md | 41 +++++++++++++++++++++++++++++------------ 1 file changed, 29 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index 008ddcd3e..b2404b0b2 100644 --- a/README.md +++ b/README.md @@ -221,26 +221,43 @@ ESPxx Hardware - Reset is also named RSBT or REST (adding PullUp improves the stability of the Module) - GPIO2 is alternative TX for the boot loader mode -ESP01 example: - -![ESP01 connect](https://raw.githubusercontent.com/Links2004/Arduino/esp8266/docs/ESP01_connect.jpg) +###### esp to Serial +![ESP to Serial](https://raw.githubusercontent.com/Links2004/Arduino/esp8266/docs/ESP_to_serial.png) #### Minimal hardware Setup for Bootloading only #### ESPxx Hardware -| PIN | Resistor | Serial Adapter | -| ------------- | -------- | -------------- | -| VCC | | VCC (3.3V) | -| GND | | GND | -| TX or GPIO2 | | RX | -| RX | | TX | -| GPIO0 | | GND | +| PIN | Resistor | Serial Adapter | +| ------------- | -------- | --------------- | +| VCC | | VCC (3.3V) | +| GND | | GND | +| TX or GPIO2 | | RX | +| RX | | TX | +| GPIO0 | | GND | | Reset | | RTS* | -| GPIO15 | PullDown | | -| CH_PD | PullUp | | +| GPIO15 | PullDown | | +| CH_PD | PullUp | | * Note - if no RTS is used a manual power toggle is needed + +#### Minimal hardware Setup for running only #### + +ESPxx Hardware + +| PIN | Resistor | Power supply | +| ------------- | -------- | --------------- | +| VCC | | VCC (3.3V) | +| GND | | GND | +| GPIO0 | PullUp | | +| GPIO15 | PullDown | | +| CH_PD | PullUp | | + +###### minimal +![ESP min](https://raw.githubusercontent.com/Links2004/Arduino/esp8266/docs/ESP_min.png) + +###### improved stability +![ESP improved stability](https://raw.githubusercontent.com/Links2004/Arduino/esp8266/docs/ESP_improved_stability.png) ### Issues and support ### From bda23fa4d3b49b79c5bb2cea9838d2622a14dcd4 Mon Sep 17 00:00:00 2001 From: Markus Sattler Date: Wed, 3 Jun 2015 00:16:12 +0200 Subject: [PATCH 03/18] add current note fix image --- README.md | 7 +++++++ doc/ESP_to_serial.png | Bin 30183 -> 21830 bytes 2 files changed, 7 insertions(+) diff --git a/README.md b/README.md index b2404b0b2..a916b8f3a 100644 --- a/README.md +++ b/README.md @@ -201,6 +201,13 @@ Libraries that don't rely on low-level access to AVR registers should work well. Pick the correct serial port. You need to put ESP8266 into bootloader mode before uploading code. +#### Power Supply #### + +For stable use of the ESP8266 a power supply with 3V3 and >= 250mA is required. + +* Note + - using Power from USB to Serial is may unstable, they not deliver enough current. + #### Minimal hardware Setup for Bootloading and usage #### ESPxx Hardware diff --git a/doc/ESP_to_serial.png b/doc/ESP_to_serial.png index 2d09ce076063dfb39e01679a5c29f8008bc3547e..9dd116be74c84a9cb42269a8f74468498e254e29 100644 GIT binary patch literal 21830 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

kVi_ic1}aBBqC zmylUOTTWq2k6zb}+@35k4{Hav{>h?>ih%tTM}B$Rr3_RRS|d~M&dd-p=*h!twv)>X zJZAl;X)?lkFWo7^wwW?7V^R^@pf)-ZyaNSzFM+b}rwjPG3&in!JTC$frmrTt-kYXv`MxAlzBSsEM_ z+QS5gLw(ktd+oX1$pnlMTYs@i8b9L;8(|wQ2j^8OsO((>qY%{v&)1&L+5O7Q?8JzA zFF0zux>dV=BkwIFq5@A%rkwr_-tq6%9dO{iIIGQTgwFQvI4V=Z8^MDV0&|lNxP+SU zyJ@ouFgM=! z6@760(sO-ZG9w1 zPBOaGYL6{JEFwBOAbTh705V?cZ0uy{>kUSKQ1wgu0}yT)ii$Ti^dG!KM&0n{23q@f%8-FPBSDBI5WnucuQ7& zmNLywmKX`u6hi^T+wON=XWU>_BJwo<^PxYjnck~x%VEr^+86kOhE>YhoDcpG)~o*- z{Y>p_+>3tbEaQ^+wODAgC%v<3x|<-Op)(fEu^X#zK|3_qsZ#4O{lF+m%SDaTRqr$8HeAq@ ztF(q@cStwK-t%LGRf6-kyZMFS)gmjTp3m?iFV|Q*9Y`}?V?V3<-yZvtMjA@noyIYB zTpusjpZ?*QwPNVE8pe33*8C-zFu`{{UnGGy4viusDtd>H8yXZmdzU4TkKO9-c6pW# z*m7)b+iX7^|LvW%C8*T)dfDia!P_l7WAkPc|DGS(zq9lnmk>^@K$jf@iCAVrq>eG+ zt2R&$0A;P#vr_9Y4?bdh>+b18dCDgRMS<1Kqps(pG= z3ZYDEPA7}a>8Qnl$J~o->$4c8}mRYe0+TN=0^`ZxJ zJkO}d5f^p69o6s{5>$!Pi|dwNKJ1JvRpdMXkM#}BtC5_)Y;v32DZNGr&TMa)-(#hI z-9&;qv7FnNTjc*Vq&x8I-mKhf_>1drJOtMXe{!mQQP%Bo#c})f$J2hMog_k9T!>&cDY*>Jnq=kk{OuS1J{v?Ay&oto*+(tF>Q$^N$V6w17BK)ZPP zZ*41O`!Y~7oLMk147NAkV-@uC($UuS(9cg1#oM8uFJyvEpr2=TR>wd;UtQUtvIzXV z+PBkoG4!DERPIvfXZC;b08d_%W+#gbZ<**GNgbhUUpQIWsyOZ!{b(*;}E`^00F zlVEq!Cv$_;|L+|(UDbAGoI?t{9fhztQJD)d>3-85-dn-nUX_YrtMZE&v4=Df2dy6DReb7qGaP6y#Rs0YYa^pa90aGDykEu&4QpdL7rHA#s zN|!F_s<4`SO90!VAB@X<{-F6lDt`M-ZQKSG6O1<8|N28UB<9zVcf}V%SvMLp#YQ{q ztA~K}wTyNI937b|?5!wx)MXNz6uO62e9r7ZhQg@pGu5Il1(BF@nJ3(G6SJ*Q_V126 zKr1rq!u>&pGatqL{xRl?nS_gB&2Dq8UDQ(KAmZZ0Kwdza$LGI4XJ0CVYb!o&HWGYN z$$Lv^ekgo0p=+MtqPRJG!$unn!m#LW;Z!zB(Y8$5%`LM)SwUg|KMBOHKh`(kXj8Pf z$aul@CLHeW4wX&JkQ+F5iD3ZRU}eBx9zI_#9gK>?AScQVXEeaNe%(GSJ#gzD!qjBe z>TS_-#>-42EPV5gor>(Np~&DV)c#1)PTOa-d%qy?6m+Og*_g%bpuy}Q1AO|#t`BUf zfSFS&<9Kr9^4(_^y1S_L6WO_rzXVh=BveEbPiSV@HDc2vb5TSzU;1}H8`AlG?%9?P z78_iQOW(Y|;>IY@Z%gwWTeCVQc#USAeb2{sdPd=GNM>I>XyCnt4mVP#ye(bdE>}09 z0p;(@(w5*Qd02n)NbhUqCF<*OxAesFML&!@9g&}XvnXa_C>OhH#+|9aZq zGPn10l+8dJkudef&gWZa|FhtNzdXj7G@I9~Mg1m3{3{jigpAKEEOI~;$5FeOW%Lmn zLG38jhL7LO8*J(C25hPBR-s)2J-B1}j=~NKCWfF#FSq`#;Uu@yq}qBV%saN$M{@C5 zY6H6Dpb1@$?owe8l#g&XS&QZFv?b6p2*iWLkM{ys`XsUlTW%Hn?IAUzp7ZcVwk>`a z-K`J1lg%s(k;JGJe!d@ES!-)|Jq!G?1lF|8i*C2%Y+?hi1UdKONJQy_hhTdQmXt&T zrY}P)hst;w)u;k>EV^3vNm^NZ%rm%bE*dCR-f6snQ~-eOIrZ>>eh5++nH~X2BsoyW0M+fBZS-( z-q%g&(Am-1>7u|R$tPCI1+6n&DHovD)*Mpbe8tUf(A1Vz81MM%+~pHP-l-lw(?wGWd+W6jB1cn2gG~gZl%yZ&&T&;lINloe+yKWZ z+CI~FP-$tTrrx%eog{?>#@8OXABtuNDixAyx3Cw(3hlc6Dwn-dYM!wn;KL+bh}QYh z#q5h|F>FNdZyV%EArk-G@dg!bzCmE$NR#Y5)4Rj`QocGev9o(~0`v#0UxJL~ZiXo< z+G6;+zVd{fD&5mBuj%|B>9xe*C%eE&!&=-B9J`fQ>*mKQOOyPXbLo(oq>3o|ao)x% z8CX#XZAGtP>%Hs1q7b( z%MdUj415Ne9?j9R(5zzijBv15DtzPh-{xhN5A9W7w6H5)sd{o3y%6EsP!=(CNDHe; z|7jzfZF+Q8xH=9twVtyTmM5TVHO(ke9oPQz?*3a0%YBezFf)@AI2*pTbL~}!HrA4} zl6-%GrX5`ASuVQHz_9Fr4lLj{R`jZ!fSWousFZ*1FMl}qRO^1rrP4Z|A$sjGr3SFMg|zclupki=si+2>E}v^71MyT$2^>^!%%9>12k z5oOqlxmL{9lAif~bWZDu6f5!7G2;KT18F~J=7N??oT=?J#u5V{v*`lioUwrJpXiLBnw4CNe1KLrhLsMSa_zs-jpj|uc z)qSpRI(Lf*3_(<%XXE1{4y@0rJiB(k`+0HWX`Zl_W4Jg=T*NY%B3)`;YMuqFa(iP& z(>x0+>==IaTCn~E9Y%^y`Qob^IKRwu_{U;N+(;$9UaPqy&8ZNz1?K(XF{kdapw=}m{&i^YH3*W z+zgx9y-Qjuu*(Z;gt{J*W#O0C+E*Ozi43`u*BE(6uryBp4WA_~I$$R!IM(e}E1YCu z@<@i%*v2`_0t7j{DE}LZx)PBdoi+2~)}Sjb#g3#sgEv`9uE!ub+vq9m#rs2ReKr;` z*B|Jn5}AX$phx`y6wWVGAwoL=DGX*|K18?@V}o67vRi3HGn9WPw4ZAqh$UD;<)W)% z!kt^3+*jX*RgGElir1y>)FPQGv?)O1az@y0fTEo4iG%Vp_^F8qAq_rx1+*2Fr!RSB zhh(G>22;IKKMjY4&TcJQ3%l8bUEbs_w4jih5FVr=S$6Bu-n8L|&{5Hht3Qju`h%E* z$!uMeOplTm7pO!_dCo8S3w5H9j)=nH6-GVkIaxVj*kQ`x@>e)ly>ui!lbMl5^oM0_ z28*tqv#3A;*h~&&gI7-vxEbshu6K(83ug6H$Q189M;4t_$I@R(&sk5QZfVq#os#=7 z*_5L z5i(5N6bl%{kLspVztBKXJ`}fzJk_vCk7IsVYl#b6^lCJ(r|MdcmC)}LSkRn3bj_)itJ+8N z1#C!bf5_Xk3v-b1TiWX&)Nqm&EeX*rrLy6up|q`d2QWy1HpvOs#QNG0};8 zSK4WW<}|rv|1Q3CXyC6@kF03XTX5*BV+5w05{{jgs~Nbyjr;Ll5wh>0O>`MeKd@4_ z#2-1Z=*i)({BHBjJ-#=n#0#Dzf*-7j_kF4TeZiGI!TG}o`^q(QyyL_Rmx^z%!`Q^p z4!eOPA6*VBavIWo&Suh6wo-wZHA%xfa=+8o58L{?m!jyY5BDVb%pd1j%(-pgpv1ki zS@X~_6MKewOjd-rzRA>Q#G+R`fGn6D25)!3^=h!ZWZ}b#_h?`K5g8&}t(R zLo@N=4j*I@TqEb)9&S|Zbym;KTzK8qJihmKwV9w(gh`hLup7SjpW?X7mKk7_(9ot| zpB>d-TA+UAWbE}bHY`p9;U3?C6r&C**GY`hvJ(@2@+6BjB~?t?i2WQS$qMo)b(|mG z)KZwDF%<}cFX2vBMDZEh9&wYOe9WL6NtO1mVvrlV7TLKiE|V~oQk%(G4hwVEE^ix5 z+dix0<^Bbz^riDITR@`6co3S^Z__CsmxJU!M-z2mg=Ur35+olg>l745&j&WesvA^D z1L4wz!WgNgYA)D<<|XZ!WUnQCi*T;H*R0cd>mf~q#EXEnd_j&(ZgeWvY?6X`Cw*35 z)pT(#Y~x0#;>L)XHObqHa8+WNSV{f%OR#=-_~dkmdaE?=7g+vB8K?F66?4%U%g%w@ zZ%vxXzeyOi{$|a6kk_wGnn{KEr4z8{ORWdOam!&%U1?y7IT_IA(p5)87`~+VdxZ6pzRy~4Wgfz#!l(P)@07Nlm`dxIsI;`Im zM>^KuH?QpSoYN}&|S{rSUb zUvW!T&hclo1cd(ozXf6b&w`BpXSM&eDBmlUnW;fW+Vf+>F1H_@A<4TU{E^!TuISrn zHJgN0PDs>{ak%H9V@gHaTb_8(v_-BEY0^Td>#QXCnho3-F%G|b|J{khrb;>6&yz<8 zV-hJMF-NnEhD{C|E2aP2XL^UT34hr#yfyTAF_q+D(zlLJ%3sWLFNtAL<8U9iwq?Qi z)Q;fFYU{TPq%Q9(yfApmmelkOX{7+A1!ZtJ;`yVMYS=C+@;Z@H$<^#sQ z0=FHB_}oVJ^pX6J_h8&Mx>*MM3|)QSF+J<0htzI*0yr((O+&=h4K8K*DbK8XJZ{eIohgbYDbXq5KotU}9OG0i%rkzkoFSw`aY45m7~ zBN}6aN%I9K-T6=UIj}RIx}h0~wJA?=@h>{4nBx^DW)@NK!8Ew?Agbx9!sz?^mArp& z(DjqvD0m^YV>Hb2<6r=dh@6#zK1wcT%XKgZYzB~EzQOSmt7Bp_@035xn}esXtXqxN zE6qWYatjnN2pakAF?RN$&^Xp($}X_Q0E!vWGGwc~|CrwVhiGD6|8bBQ0@cXpd#fN@q%Y%nAZ`1>uup4q*N}4q7#TAOcqO=r18h~H1;7&j63uJ6Gn>J_%ds3pkXg*uS&!+&Y z3F!d4@|0i95R1JF>7oKRuAd}qr>80G#|#eF4a>=c?Z1s(JfGjNO@R0T9jnv43}#Fe zpU+bLOs)T`wt${e397bP>1o#A*yL>r>wnBTA;h*@_&G1YUj^Ut*6l^hmFT@jwgJB3uedRBd71UmrD$CR z*qAAIhY)D@m}7~iF}szqIVNkuG9y<0=i7?eyva#MEdLu3)}lj;6(%BH&+#I@%?C2# zr&A^NqQRS^x4nkC3a)46JjTDmy^Is1h*cKEeT-!cUgYg)J&p>$$IO4CDT_?a1vzKa z7heVJmZw8fC}i0=Ccf}7DERYDEXDpP*}r|IKF^J_wf`}~>5z$Sbi;XyPpSr96SxIt zQLM)+3M^Rl8-cGm?!J^^Uol z`4>|mYc!$~T8f?%@-2l8K+^I*#gw@{K$q;A5eOqUjpI@POIx>>m!#?8of+M;Gshs6 zrTG@$NL!I#`PEu%0-$dZ70@6BV371-MK*Ql<|)A-mtexx*fCD$wNUb5H|AIKu1{2X zbj?81749P5@4gm60riEn`p<8Azx>g09MvU`N%NuAx2pVahcWIGZKaw|F84v}j9$e( z)K*UOf75)lyxk`gcmJ+Bh04%SohnFF4MTc5SmqMXii1QnqyV_SaUZs$hqv#()MSQk z>Ay&_I{M8%!?oxM7b3ArrqdBt;FVo*ns`kq?T@|_B{aS1v$Y|UFF^`Z`ZdV*0tUu$ z1`|~9t<*D(r;9tMhnBBJXZy<7jfSlAYigwHwb)%`gpO4`lnLcjH=XchWZh|QP@wa= zR>TX=>C?(GzGi`r+UuLnHg_92;Zl_APq_zL(a?8B`NyO~57~V~-6;_42eOXT&hjIZ zuWxM}^#V!Iz1M|j#O2&p4fw|9O^hncop;^7P3&Zucv3l zebx9V=}QstoKzUdNCP2Jj&mBmFh`FR<|#L{6>W}JK4Z5HMPBy@J1Kt1TrbbvyaFlw zT1@zLN}Ln>u;A;PWA|)A?wtux1P;&9js%R!Yn~M~!nGORT)+@;O_jFT#Elts$BeSx zFA0~Q1!vc&^BMv#?sBHK6{dM;zdo`X_PhF3~lN*Ir}M})bvWU^)qstLbOdt z)R`s?1i~lLJH8f6*haulCr3%mc?b=w0mhoQ6#gkUoihUGhyjC@jJ;9D0T5;I@3=kaw!fLkha1VIk<11Og9HY{(vA;&i zmG*OUSo7zg&VKPh@BMuRSs&h>)v*OR$o(55v#eFh(m?qFj<^PviQyRX9*Pa1{E>rJ zs3E{2d{3+n!=qof7peo0wRdMpcdF4lmh&uSI(8 zGI0JfPv(iieKF0h7uOm#GiS`$bYn^qI`TzM;)o$|^6-ajcV4<(yXm}t>df@XdlP=N ztLXZ_cU)8i_Te*NrXuC3#+;HI*MeG>oTX8>;_l&&h}FEB0exkC2KQp;uS0Hqvu74i z=1uZoWI=e-38G_uoj`*@eij!O95_iBvp6>x;Jd^iYV|S7;b+YJsJKE3P0z8g?(3G4 zX=J%`wa!on9Z8G$)R;qB^-3po-|VNxuU|^E%WMSV&$pfdHe;izrJ5qKqaUTmo}MvU z?M4l~Vq$7)*34wZsWrR)u@;1}WiAz~d@)WG+oQdGYdDMhr!5`__PPzZw*k*oa6Wu% z9mLzORA?t)FRCHJ8C@Y&*D%ZFOUIqSzWaDR3zVpUe=~A&h-+TqYI66GMB!rYqG`Q-w8-+458 zpX^m0b>Npj9O7}}oK0wUM2gi}^5S~5)31}83u3j(y;B5A8uDgj32 z0;4gDe&B5in=sIpjZDpQl}U_K-{=>ivjmoBhx5rTSeDdPy9D}8L{wJivVw74$4(&7nN7FY_KdFTn?iYp zEVGPWTPU*YZvqJW^KAGuZ>_#!eH1bp&=5g77a-4~eDET7N2_j6cnZQMRYUZmP_L~5 zte6#|>Pi){Nh@IT1RJ}l*?3Nd(xhXAb%I@~!KwtYkOA-{uPsdPHuv8#^ty?lktWZl z_1_KY(a@gll*=y4R2kPk+-it}wDLbE)z`e!yZ$?F`B}*Vr-MS5!s)RBcSk(O_G?VH z&b}Q(LVKj1uSBuWKM4PCf|TCfDm_hpY4eJXt`Rr67S-q%&W&y02AB7>GY+iUe6CA355h&0DT zU5hRASal7&4MIQ5j1nJ>U*-m#!%&=n-zI z7S5d-A3eFWkIw_xzZ86{huA(~-CQkB@g};7g^j?Kas;H`bn0bEor*VgL`Ud$^osX5 zv-J^n`+Re_#8=txj?V^p4q(V7hKM%DzhRyGR>#!+9aG1~dhk51CN>G*i z18L(8Q4lnMsfh}HJQ!!3|tfWl?4w$p=9R>(Dm$|OGoD;l3?}Y{uZ(}2 zluJ8czbC`Gm#RY{mwd}gxcrz6Gd@)cTXbFf}`>ncvZ^XQIt5}5q zUh;SfbG)ZIH2#?e@BMw99`T-Adf?o2Ryv*KJ+yv@mPx;`i@Axv)Fy12hC#=0*cxHv z@@eV9rC!KpUu(Q4o`Atm3|hhmB|-Uy&z_>gz~q~y%8zvL_x`6I=PcO_Xmm}I6Yz|T zfm5L^i6OoFLC0mh_*|f7vD5B6N|FW2h@%@nl8ROj)~~1dPU=SMC{yE_)&)*Yqi403 z1g|snGn)c+zcb?G5!-}`s))Kqo@JYs<7p?JcnvW1+O322koo`QY~ZZ+a)&P{H+(S$ zsvob7E$%O~dV1z~^2SH5eHmxm%>rkXsvO|HLnC;;BjJzVV(@%}O7Ob#yj!8y;deJ5 zOpWv?dq!_o`0Kafam=FTv-QajKrS2;@~eP!%KW=M_RbWzu|E#sGULnH8{Pc-5ff8zFeu3AaesNW_TSBLzR<&i z2PZ&P@^54uxAj=VvNJ^legN1w)+;;--r+D=l3xGU zjyld}BDKoIWyaVo1E?B{&}fU)_!Kh(brbP+Je>pLkkojqZrZ_qYyK$gFG~vr*-So0;CKk7 z_EdwXC;&E~U@v{Fc5CrN$k=<7-xTKAAo3keKe_*we4+;L*!;UL;9dRVKp;^sL~wo! zVUD3(iM5#EAZC72a5aQ

@GS4GNHwc%{Pn)+#8=<-0~T?Z`84H*Q7_#t9IL99J2C zSJIQm|6D+M7}M}g((3hs=|M=CZx&=w{+jbI(^omeclssw1JDOx9$>`M$wOm<8e_Xa z_V-F_gs8CC5^_8vq$s69W*cP$pbZGwUYI3}gqZco5&wPI9e&AQ=Z6jU-}(`w!aY+M+wg02uiN?^s<{T zeDZ2v<(l_A&o=wt4mzr!qS5-W{W(o1{qUxg4cp06C|&q)+|k;E3ETLD?FzTbd%JKN zA91zGUT5&xX1Y2~(CN3G#`%4!@QpkJ zLT2n;gsVuK8m7iIfgxj&7S9^=Z=;PXL)6Teh!D*a6ixFzW56;_XyVLzIfppAsM!`b@dHVrUAplAI1qiOJF^MvOtvfupw2dT^*)<1j!W_ zY81eOn!5?TI^JzQvy=oZh39*FzfRVKrL z&vx#M7qXo&KCvrJV0vMKDt5uJ5u9qEN#vhfRVj)o>f{7i&>GZ`S70j1;MM!yTQqWh?v0 zxyI~{ZQJWDy6@lb{y5R_5z*5HKS1)ZhrLSDuACR

lwoHhj((xZhdXqF2z54lGm zK2gw2+Iz&=tkhhIvw1s>NGP;EMSL+l09#~ej>3UX`F^-Azk*OGMMWcV+Zj+9 zWDo@bqwtI6$-|<3)O>rYTKkBtJ$KlGI`dR7<}}KztGeh-w^vCaD+ef$1#t48Q7?Re zOqP^Bx9zBHxX#R%$aD;zfqUlE;ybn_)-wMBK#k(z$h-QPd>3g_0;ucnp!S~BI;8F@ zAIdlmgu&e=)x)%dwXDa`X5JTVFf%FOh-pxKwDqPBx^I!c2ueWcA0fxbHzPS|EhE~p&|61*1;{O+0k z27KCl*S9X-_O_RIZIm>2yNR593_MGbm`A(QDT^pT%$gYm&|!u;(Ap2C2udzO_vrQ@ zk3UdUsT%6rxR>XUTN~u#w#J!?kr@x*@{exnos2AUZmq4>^@hdAJC5iKBz# z8Q0W>mf+OAccK~ZAls5w$EbGTpIjZVEnkGTWixYvuo!H^($2LQn^Sc{C5btEa&tVh zsCM)uDzcQ8IAx2cI2`+G)9nDleS@g7=fkSQdRf_l4PeYik#?PJ_53lTaeiaV1tq$Y zE>=+$TzjKLh+9 zplZ(70slu(!uR^{W~S0cv9@go6)gm&g@3ct}SrvoO|$&ogJ3Z zkyqdWkjl?ComageHYn}RTh%M5kZ##Fr~l|}#ywWF{HA&nW5-fs$C!pAENy$?6NG;; zio7yz#$A@L)A=X+U8m2DfIR+4U@(Cl`OuIA;N)O~@)}f@gR#I&O!`((&BpL5*OH1F zZ~mJae4|%!9s6xb{(8$DitLv?LQzQ60e8+YgVd8aE5f5lvx=O=6)HE=ZXP zhibC9ybmfE*qDc6-D&=i1S+88nE`dNfp3SUq?E7J=gI{>XS`|ddz0){GV`zcHn%oR zA}-ChoTfC)lbTFpHE2;sqMGz+Q%#;}#?$yRZp9iy()Q-QU;y(91pIq$PiT3@&E&`# zu;?Ewg)xol>Ds6G)C^T*>(1Dum^ky4vNu2_ojGbSZQ++A2}Ldc!U_1g#7=|KgyXLj z-5G4QJ=z=u7g%kuB4hx7xYBVbGSGoTd&2q5#+ zCshlcbO$)}JQr;RBxWsK`+!Ro!P9v9I#4{kiz5K{d^SAdvu}3yhnqMdYMD`t)QcgR*%SB@DNG!On)S&} zMNdk+2(8I{TAPHcvJG${B5aPOIrMnT^JsaW^D5pxl$gjG>G6+jntEd-+vFll|Exw) z?eDFX%SmF`%?*f=NgTOt)+>_$2&m)TZTnS5Gp2dcH}w5zLy=b%Gavms$ZYC;^qm0r zF3>aQ5=41f0{rZJF!hM4!PDmC(9=Rh7`XPeGcPcVCslxOuTOIf8M$(r(O|HYGqX%J zn?Z<0{unym(^WsYHGW*r-#cA^djp4013PZ*<2eWGCVNFSN?UNHqJ(R5meK40SOUk;4j^aW<@D?3)Ok$ND%Cfnbuxo0Ns4$z3q#RF=J~j#&udWQO$MQ#9x#;VnuAc7r3eGK2}Cq5=wa`L^WLV4&!IO zQvU{-Yf6Cq0AOaBDxydtNSl^n+N;83C+sJ4B0fJFJpqJG-U<2jV*{8QSc(Ft;{oM@ zxkDwH$zX20iVzlk${9EI$#jgGxC!p}zrQERsl_St6 z?@7#_#PAmDD-uNjzRxc(g!5_!^{F67TGvoi1I_Fp?_`Z8B@G<3XMD)z_$Hcwf~88(i<&ZbcW@?# zB4SQUCvp4@xm5r=M{9tDsFNj6doPBoH@p?fkv5?PqJ3CI7~;`I&dqru$513fKFZXD z6jc+TNO5Ej_&TW4M#$l(P(>esp^a;kJxYUFDSFv=(o0eJTfp{25ThM!;jWLI}pl;h2OdlDpM z1D6ouk!Tby$2eOGsDU<5XfPnjqg-j(E8`Tp!N^`;O;7i476N-~ON63lP^z@z z>4T`eljVK1d{z&|b^0J4gduSsVu9Kb4=SWgV?k~?0a6SNV~K!=NI>m?F&W0oUb!kW z_KyHL@VqiVW}I-$a>G-6C|uwz4O!JGNKA0bZY^}gP?P3l22?ch$t)LDx~PBE+-L#w zqdhrCxm#S(eZEpqW~12ZlYZ*sqnM8$4LZuy&L{AyCYPNHBLEDB>f9xZF&2bd-Cjc# zPRn40Z<4rUFN862@%Gd@o8x0=7V%?VoFetdv^9pkv{3bt`;oZ12cK!dPr9QR}Lzs1L@%4X~*HMi($PLGP3hm&0koMuigP6 zjSs+{gn_p>ekJUM!aS%A8cZM)7aKaKl&+o+^P}-AU@tWPpS~gwV1Nw(Zl1mkpv)%J z4|r`|gJuAUFlABidGLqloBD7u02UtcBl!lv&Ki(jw!cXe+%Z}m^MYx#s8#$h0FNOE zmy`NK>^|?`D}jn(2+~{jZ4(Uuv1R<&-8Z|A0YG85VHsIrVga-Tp&kiYN!qC!R1Lz9 z9lDNP+9+-6%*_v*s56O$H=)Ki)$EuC6E_XG|H6MjOgc9Lurz)QT%Ln@Sowe|ffvFC z7z;)$1tU6CsuKn-mhT)Eb)$_u*{(`gWD^?Jf~e+wQlf(*`brpL_B{b5it(Wqf;=vO zg%5ZaMuTEYzsNeAxDa0e%qaxw(0^`^Y2HUSnng64Gqe&}kM0&0_|Jp5!;tbg0>*&B z;PU`3VE;KQwhi&!Vjd}5>pMx$ub(rbzLR13<Gb{&*O3%RD@cf+4_*HlyXM` zWbIt~)PEn58|vxOnXp%cI|dWa*z-ihH^YCFvY6J|1oUh9SE9Z*s&C@Kq&)v0+ zI%iO_Mx>-BcYi<+6##=Kv~s>6k~NSACT2Yh)TQ-KqDTtmg~`Jr3(?w-4NiabT9b!|2ry8rnz?13;e{Y8sx*Ngx6dhl7y;qx^IP_|n8@IWMB-VOa$XzHC>Qi~^{^r<;=l8K0=ExD3cETLjDcj%^li zha%aHF^^8#y25v}!8b;VfS0J>YzD8zsqxm8xyq=1w;&FcD5-WA<$5vL{_ij`=u!p2 z#9m|tEi6prXXkE$5pzx&1Tg>d{8zIQvxl4%S<7E=?>4T< zNZgPit2}F3H>UvXTs-DcEmros9r&wOb8FrPbws<&{4-z(%t}{-G+nn8(CJ!!-5~pd z6kZ)J-b^_hgq&2G&yTsF6{(A0Mdb@LU4MSA$4TX1Ya1+A@f9M-OBG&lSOn8&EPN>y z_42D5Fy)kQmF7jJtL^Zg`Exj;hl>iE0smo3ARSE2XFiW%AM!aXh1BO zj}(7P-DMcWH$eUv8461kc9r)%*#}Gp>e+)Af3Fh&x}#*TEKE8Oi_jld`|w)vyYq(x zRzQJS^Ui-UxQ6+|LW~awBVRvd1|+@k32Z}%#|>`QAnVryjAB)r8h*l#IuzauU2O*oP8s7$EKw)Vtgww2xyc@ce zs{bvw{#IhcX@FEzA2ue#Z~})*fW5@ zBI7cC&bT20lBXL$eQp%elrsBt&k;%>nfH{rwFI<80~`dxOo_TKsU8)E!XeC*2&7yMiU=^^nV}kd-d4K+@$~jENDY~ zv^i5T7o*gvn=0n~Hq_Hcszl2;B?OZDlw$DydNGoKU#)47{+Z9!2u%Qpv>q>e#>~L@ z6r{&Qm4#G?>3z^l0!cGS1(Ws3MKNVSmsx?RXEDr~J)flsHkpenB<|0L5J3Bd$zTo! zm^D8lWPrMw^wHsa1pP$fdjd$rQ{-V+E#@&tAh`ITYHs+q1f9@h^H3_q-?wZntv(kd z^MqM96B4Lbut}SC2Rir$|9%Z)`T*!&=!eu|{26G?7u;N;o;@HmZ~_f$77EU9XDf@O+_>st+;x0Yjw%Go$nT zUz9sE+J6G9>LU)lo7d-wX1q@scMIno{CW^RO2>9JqW+^~9+YVnIX3UV2Plmy4fS=A z=G8t_m6?8VVg#z|jQuy%64LcXuJ9c{>UxB`8}Yq;W#|u2*CysSY!bK)|DM}RHaW3# z2Ya>gLj6vrCWS>v7TLekDfuB%2+-JPL2eeeNS7bsC&uQ@mjLR=vlDlyXw@x9#vw`G ztTRi=+27T^vw3A?`SDUEP|x36@pG<`=?W*7940XJp-MxL$ss!#{Pj#jH7P0ZZ8#{) z0BIa!aIbIOe5S4dIa$i9xfhrN%n05CAVCtOXwR(fYJ;eWplrgEW^qtyOt*_SN6$R1 zRmh?)6(USlz@s*?@RQ0b1C{|qS%PZB0;iJzbMD<)=*avlK||HzU1T|GO~V%-Pz!Bi z0xC62jmN)vQ(p6g5aC^5Tw+oHoYf4pH2-$N$Zf9;BO!J8yD&{KwT9rE7us) zDD6Q2E1O}bsf{5a+ zVk`LD`+zsC#k7BOr5#XA_X>NWIa~k56D$we^Vy;@yc`-apQ(1O$*<{x0G(L2n(@*; z!B{c{(da7NDJX+Yn=Ch-Tm{ysUp)REd!%-v#4R!33L5c~5y?StV}(Jp=z+5J=b;fn zhY;_ZLRd#Zx5xKSCA;J+FFodcjz3_k1Bz_XB&hkTc~p-MglbG#Y~%^G6T!Do%5( z-B}+d!?UBqM%wd)i1hArln=p5S#=GTbBMXHT$PW9f|^-y-501X)zOKkwHCiO@an5r zCyAB~USFB;_LAbz1$0vF?JN zFB(4+DcLStP)2)SdhG3B*3c?#&!Lx&VGj2nWy-s9--@^;jsc# zV&_gl;i#$Z5m4RS5ynkK5kW0o zJ5fI|n|N2h2qYE&5*i#Wi@%#(g7jV1+hX(nsjG5G3Ze zwtNH$VMB)`jepHT>!UA&y6_)lo6ZT-1{Ko5JTE1E$}nQ%KpT_}0qy}m}XXlWaR1Y z)2=36)w5pU4#wD)9=&?QfHbon?{8WVA)*#2j(3egyvvHug;xgHe?J77NE>LcopkNI zh-hgYh;gsf@#_?Quh$0nhogu4NV48H$EHL$=eV|@+bvWsQ|ic`0QDZJJx80j_;$mSi+1jvP3(c5p|~*k!2r^zZbf zZPBqIO;hs5{)RRt2@`?X)TtBv^3!_G%9>=&*^}Mk4amhu>JN#6D`4bc<)E*j?bkrB z%%n5NH@l&{AdcDV#P>t$Z5%{E4XGY26BH0N%J<^P1t&Y+}zDF{OYVXR8QrcM;a-2FM0kMNCR-)mwXWfLa3hyLH z*jGFr2A3Nth{?+;g?D+2UR*cl$l|5-?iUXKa^um)(LKQ?Eu=I9casBxVp2!)H3a4D z85G(RtnlI=bZ|J1rEU}-4X``_-4&Yii9G;%+q~$Wazw{FeaMM>eKNBx4s6+c99$UIGT&PVvEwm+YIkNS>b9-24u-41N7h z{f>Wl+_7fAwFfIg@Q;eOdtj!YO0RI^o7I4gk_2Svak+GY%{yhNF?GNJo^1yP@>X=s!wt@ZooF@gPSV}6phBrJk zbXNlVrmjdNg2qHMDX!S{IUEr7uJCNOwI}zj8&ze0={w!?wXwi+b_Cil|K5qy2Wh&a zk+r88Xv==DY2f;(xL}1|@ZH0%$J*MsRrrqSzf$Ip)M)(y2n~?)1yXrL8 zw{__~&<$09C|VzF2aVucq~>~q{`nhd-71I%nKfFV8@%@oVJ}vbUyrq7Z21u!(QA(> z=rkWU*PLj*5h8bsBp-Tok_rERHC67H5#Hxn#!%r3P_-uPY_$DOf`_&WABLpw+dSGa zMi?)aR13dI8gG zGn=ooI40|f7MJvg|vH6@40^(f$`Vpsz~8x=!V#xBG8gsR z{W}S`4MhiEb0Z$84eC9Z{sre30Bd?9L}Y$G^npu5>a5}MMc$(SzKNW^W}Kg>Z|I$Z z@&9O}TEUfBcR~B}lJAR&kS*ZX=Fdp$6?ejeauvP~o&X)fi$)jrfL-;Q48N4}+@ORZ zOMJ)&>MkC8EAi{yiP1uNSj(!pCYFExc5?tKyu5|KrjL_UIbB-8e12>i-@LH#*8Y13 zrCM~pSm*Y_4{i0G2+Hh?80=iw0d@PGp`qoMr_V{BuRZQ?Rg;$Dp`E9hGbHL%EyFqC zmO3_At8baAAbAz{y~o_22}ygOjID4~^bH$Ye6(Ti+ksSvh3Y#{i(Fsi{ zpBr)da-$G3LjF_}!hpp8OTnVy8Q7(Y@bXml;;Gfam9r5Wn+!&!5N@6%lr*fUFHJqg z+%J3h(5||s_27D|ldjsuino(g;IL5vVof-&psar%fPa@c%lAwy*OYJ#@$GA!xDjL<60;kpzBCh0#mwlFid%4|=dN z=*xarHDBg=XumAV7ShZ$mB5eP(mOvNKm&t+y%hT zW_43D?rLTINQheX%d^_bpU4tnvtGE?-&amv`h>;S$P+bkh?=)Ekoq6ra+d!{x8>(j z&y*ngJcl-SSpv)MTb}PK)1Ee(_c4S4et*DkU#N>HV+Y1MWgqLv7{9`KCxgy#9!wUd z>9;ahZP_Nj8!(UbJbJ1%&M%@#jqA-w`S9Q=yw2WL+2=1a=X7>-*3e`B$fVS<<3ien z$Oh%je7*GWjjgG-Uc^1ZmKM#Owlla?!r-}j^`%#*0V94t(&)0(0tbp7o2)OVAPJa@ z_Nh9AkvPAq+@44}LHjs6s2*__fm#s|TFeeC2dlcGcM$f8vG6#}-K&_RuAqi@P?X|t zXs-yeBZ;3XLKq2xv8tzjz0{Y(A1%K#sOV-r!Y!j8nY?BUG-atN{OqCM>w5$Cg7m{a zSq~_@I*_mIlm%`34U15~U5gCDhK{XjPblm5iTt2NdeN2%(CcG3 z_xB;r8?35t-m)&&-&}L#9*Lh=67C;md+e5Kn`AOnmU-q zP$=)N4*U?p_-jrq`+F*QGWci#?V$YO63~3H_`)X}-YsIBe;QxqT!_JT&T;O4HX3#6 zmRrTKu4)IcFca;k@CYJOr(cIVg|;oj4;=5v>P1udy``^cJ1yL7lQJlM`lwxGw$QZbb>VKQmf3)j_~|iVJAF}IM&rR+1F5aq|sw=tQ82Ipc=ia&7Qc{ zf&N;3>5;UCnYzD=sGz-d{KADMsvT^k0-M?Z)n9{~OZO~6^{S|AyI-+DI{LEZ0^$kU z`JD+fTWuT9C+=;@(LDuPo}SA81#js#>-xEw-^e(RsLq!U!vK@4m@4b_I&%5W|bI&>V|F7HKHpZ52?cx`>1ys@K4+81Fl6ytPN*1#HD1@^A{F`yA zr6sJlVC)ZeA_IV_m;bqyi%n$c!ItP>HeX;tE&u7-9JXR*R}Q!53(|P8W8KUW$Yd2G zyDK8?UhDHI&!dnyLZl(WTfjG0neuoMNIH4E-sbm#Hq}%K)j~7NTQL>~sJ-$NJRoFwv3;Dvz?Z@$>mq0Si_H~= zNced!E9A3S->6|`0^rG%JE$+Z~M%Q7XCun7K8e8}G% zME(G|$=q8j8mhtNN!QE8#m|dtF=-aGnWV;q3HAVd*QG5~hWikf5iD#cR|@!s*@1q^ zi1-{a!&pFR#Tu$7nn?v+dSTNvIhpt_?+j_VY+KZ z5+F%gO}C%ckVDB4sA%89pEWsn%oFK|%jLSB8(l)Ltn_I;*xSL0ykku1m@SDsBCP1- z@tKa$Du{w)-S2+nMz`-GkBzUTuK?II)^Swz_P%Zz=I?2CDtL)8kqaYWDzWLm6s*bB z$n9>MM0%iT0M?@i%~E02HFRQCKL9|siL)rEh|}n38r=Yvu?3O-8RqlMJW@;ZnIUb< zPGjyFiMqu6ZG<5Ft^1+u)~=F28TPlv%8Cw9s0{;K{;*kHoqz>^TC6AaLNgpA!P|oN z%|ZM8knHi&`~~KoB+)%#hc`OdQA4W~CiMN7{89#m&yBX&06u^JNJRZ;gKP535eGvX zn9yaJ#>#(Rp4y@cgPs0tlu5Oq2kj)xbiTz4d>>bqgWu6DzHakXJlg@ag4^V1(ZF}q z$`%g5lc8^s?Qp}t%VDg7^9z^t4cN11y0xU#GlI8-mq$QdEGd(iPsz=@lHsn01&S(a zM++Z_b<`Qb)9wMRsWq&ij0mED*xC31EYzHLUF^V`P=oRUs4;Bq+x2v4T@rx7qJ!Va zF19z$?#|rsZyzw0ga@I%4t(TRpnFx%9Id{x%?~c%<(5+{|FgZbQEyJBl);tt{@U!4 z;n;4aJ#Y9Mo)~^@Re#VTm=rifOdTL0NytzOWFaYGTb zeUYj!ptJl571289f-(Rq`b{REi!iPl*jQ0kVE-T(J~7Q&vc^*t{1FigRi)3eg$c26 zm>HBVQAe|UgbjW@nQGrj1cINg19$M3nT)7Y=;@hNE)fxmlOw#Xv(q>4 zVMTftPBO{9&PXrS4McQHTsZtg@c4qH{wM0U*cWwm)}aZ;WX0DF@~yTx&&b!H!v{s; zU6zvG8cR|=%i@@{A_5Tpp@0N+Q%n7p#CSH7EIYC_wiq5+yp0F%=lepj9@MTo`ZJ$L zBQ)?lU{#rCRRO26RN;VX9GiPE&%UJh+&GR5cm@=T@{2Usf8ig#-)4jB|FgwZbK;4- z$6Tu5NTp+Vo)*#pbM)dZenhZht~O@BY8-0r@nTY*x=$Do$BESzC|0&LUS7K^@ADTV zBTjGfIId~3rBwk%WLw-I`%;Bhd;a3)mP!wGbW~>Fu8jLIP*tWbKRToo}n7fbZ z!zm!gPyanpb91-6SotjT<;Oxa4x{6FiBj#ZC{(}>Zt)wPU+kCktni&YR4D@>@+6zp zmTAs_E1>0fdSzdD3c8`0av62hd@bYT1@`0N7)Z{^=yz zFbwzM$^&LY*DFAn1T5ysiXE|{(W2=#`Z7dZ2DLm!TeTD_{%9Mg^=Tqi0MxiFWoj1~ z+y5b?$V|@0_XGeiV@$_X0xT40-SHc%!XnychVW23aKONdoW1-6oMC84x;oq?At?$T zEop@VspP2HB)eN*$RQou^)z6e31DhHEEX?rd;SG&%g7`KyFFZf55P3NX^4OIF7tD7 znxH5KcLAvF_|D5yGizFZ~k{(VT>AdHa!#iGoZNe17>XpkG z5whRTFX=Ot-Z`AZ6&!EBHi7cb5!VbUmr0g1h7a^)?1@cKdk3a^>Xmd!GXUN-em*<& z;iaOux(^dRgVjrP;Y}&QcegrCHhnDDYnu3&usAK_V-szPiMk1aoM(`k?_dR9@AvSp zQ~5-P{5rqV8g)vFWJOyX@(zJo+5kH&!^dmM<73achiR7znr_hG)!pp1|BP;wZ!M>dfUtr28% z?;!vHH68CsjOLH81Pi(yeuoTckT2KYG&TrbJzLwLgveZn_X*NF`HU1~E)aUXXr3j!RGWuQs!gVfnpf zRnCkY;!{|Gaw6hAOE@#dnjT7(w(dH+=P){CSN)f(ZWM2Qv&xM+ium= Date: Tue, 2 Jun 2015 15:59:22 -0700 Subject: [PATCH 04/18] Include Servo Library in Readme --- README.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/README.md b/README.md index 008ddcd3e..d3af79de9 100644 --- a/README.md +++ b/README.md @@ -184,6 +184,11 @@ Allows the sketch to respond to multicast DNS queries for domain names like "foo Currently the library only works on STA interface, AP interface is not supported. See attached example and library README file for details. +#### Servor #### + +This library exposes the ability to control RC(hobby) servo motors. It will support upto 24 servos on any available output pin. By defualt the first 12 servos will use Timer0 and currently this will not interfere with any other support. Servos counts above 12 will use Timer1 and features that use it will be effected. +While many RC servo motors will accept the 3.3v IO data pin from a esp8266, most will not be able to run off 3.3v and will require another power source that matches their specifications. Make sure to connect the grounds between the esp8266 and the servo motor power supply. + #### Other libraries (not included with the IDE) Libraries that don't rely on low-level access to AVR registers should work well. Here are a few libraries that were verified to work: From c86c79e90109198a6a8ea8451047caa8ac11a533 Mon Sep 17 00:00:00 2001 From: Makuna Date: Tue, 2 Jun 2015 16:00:51 -0700 Subject: [PATCH 05/18] edits --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index d3af79de9..8928e14c8 100644 --- a/README.md +++ b/README.md @@ -184,9 +184,9 @@ Allows the sketch to respond to multicast DNS queries for domain names like "foo Currently the library only works on STA interface, AP interface is not supported. See attached example and library README file for details. -#### Servor #### +#### Servo #### -This library exposes the ability to control RC(hobby) servo motors. It will support upto 24 servos on any available output pin. By defualt the first 12 servos will use Timer0 and currently this will not interfere with any other support. Servos counts above 12 will use Timer1 and features that use it will be effected. +This library exposes the ability to control RC (hobby) servo motors. It will support upto 24 servos on any available output pin. By defualt the first 12 servos will use Timer0 and currently this will not interfere with any other support. Servo counts above 12 will use Timer1 and features that use it will be effected. While many RC servo motors will accept the 3.3v IO data pin from a esp8266, most will not be able to run off 3.3v and will require another power source that matches their specifications. Make sure to connect the grounds between the esp8266 and the servo motor power supply. #### Other libraries (not included with the IDE) From 1de33fe51bc28004248637cf2748407905a13c62 Mon Sep 17 00:00:00 2001 From: Markus Sattler Date: Wed, 3 Jun 2015 15:10:35 +0200 Subject: [PATCH 06/18] improve mode handling for ESP8266WiFiClass::scanNetworks and ESP8266WiFiClass::beginSmartConfig --- libraries/ESP8266WiFi/src/ESP8266WiFi.cpp | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/libraries/ESP8266WiFi/src/ESP8266WiFi.cpp b/libraries/ESP8266WiFi/src/ESP8266WiFi.cpp index 0f97e48a1..84bb134ea 100644 --- a/libraries/ESP8266WiFi/src/ESP8266WiFi.cpp +++ b/libraries/ESP8266WiFi/src/ESP8266WiFi.cpp @@ -333,10 +333,14 @@ void ESP8266WiFiClass::_scanDone(void* result, int status) int8_t ESP8266WiFiClass::scanNetworks() { - if ((wifi_get_opmode() & 1) == 0)//1 and 3 have STA enabled - { + if(_useApMode) { + // turn on AP+STA mode mode(WIFI_AP_STA); + } else { + // turn on STA mode + mode(WIFI_STA); } + int status = wifi_station_get_connect_status(); if (status != STATION_GOT_IP && status != STATION_IDLE) { @@ -508,9 +512,12 @@ void ESP8266WiFiClass::beginSmartConfig() if (_smartConfigStarted) return; - if ((wifi_get_opmode() & 1) == 0)//1 and 3 have STA enabled - { + if(_useApMode) { + // turn on AP+STA mode mode(WIFI_AP_STA); + } else { + // turn on STA mode + mode(WIFI_STA); } _smartConfigStarted = true; From fa4fd9ed9dfa818a69b1869e5666c4b640d060ec Mon Sep 17 00:00:00 2001 From: Markus Sattler Date: Wed, 3 Jun 2015 15:40:43 +0200 Subject: [PATCH 07/18] only call wifi_set_opmode when really needed --- libraries/ESP8266WiFi/src/ESP8266WiFi.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libraries/ESP8266WiFi/src/ESP8266WiFi.cpp b/libraries/ESP8266WiFi/src/ESP8266WiFi.cpp index 84bb134ea..11a1c11ee 100644 --- a/libraries/ESP8266WiFi/src/ESP8266WiFi.cpp +++ b/libraries/ESP8266WiFi/src/ESP8266WiFi.cpp @@ -45,6 +45,9 @@ ESP8266WiFiClass::ESP8266WiFiClass() void ESP8266WiFiClass::mode(WiFiMode m) { + if(wifi_get_opmode() == (uint8)m) { + return; + } ETS_UART_INTR_DISABLE(); wifi_set_opmode(m); ETS_UART_INTR_ENABLE(); From ab03a267a19c0714c3258e1ee5e0d4a7756db244 Mon Sep 17 00:00:00 2001 From: Markus Sattler Date: Wed, 3 Jun 2015 19:32:44 +0200 Subject: [PATCH 08/18] add some infos to Serial Adapter --- README.md | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/README.md b/README.md index a916b8f3a..84d2f7ccb 100644 --- a/README.md +++ b/README.md @@ -208,6 +208,21 @@ For stable use of the ESP8266 a power supply with 3V3 and >= 250mA is required. * Note - using Power from USB to Serial is may unstable, they not deliver enough current. +#### Serial Adapter #### + +There are many different USB to Serial adapters / boards. + +* Note + - for full upload management you need RTS and DTR + - the chip need to have 3V3 TTL (5V may damage the chip) + - not all board have all pins of the ICs as breakout (check before order) + - CTS and DSR are not useful for upload (they are Inputs) + +* Working ICs + - FT232RL + - CP2102 + - may others (drop a comment) + #### Minimal hardware Setup for Bootloading and usage #### ESPxx Hardware From cfb9cf7374a37338fc9a8f767867e40979de4b8f Mon Sep 17 00:00:00 2001 From: John Doe Date: Wed, 3 Jun 2015 22:23:19 +0300 Subject: [PATCH 09/18] double --- cores/esp8266/esp8266_peri.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cores/esp8266/esp8266_peri.h b/cores/esp8266/esp8266_peri.h index d7723c3ad..996185ddc 100644 --- a/cores/esp8266/esp8266_peri.h +++ b/cores/esp8266/esp8266_peri.h @@ -284,7 +284,7 @@ extern uint8_t esp8266_gpioToFn[16]; //SPI_READY #define SPIRDY ESP8266_DREG(0x0C) -#define SPIBUSY 9 //wait SPI idle +#define SPI_BUSY 9 //wait SPI idle //SPI0 Registers (SPI0 is used for the flash) #define SPI0CMD ESP8266_REG(0x200) From 7daa6c6b690f6a96f5e2ccd5af7c5965fa385333 Mon Sep 17 00:00:00 2001 From: chad cormier roussel Date: Wed, 3 Jun 2015 15:29:25 -0400 Subject: [PATCH 10/18] Add function overload to config to include DNS Disable DHCP if using static IP With dhcp disabled, I noticed about 50% less conncection time --- libraries/ESP8266WiFi/src/ESP8266WiFi.cpp | 26 ++++++++++++++++++++++- libraries/ESP8266WiFi/src/ESP8266WiFi.h | 13 ++++++++++-- 2 files changed, 36 insertions(+), 3 deletions(-) diff --git a/libraries/ESP8266WiFi/src/ESP8266WiFi.cpp b/libraries/ESP8266WiFi/src/ESP8266WiFi.cpp index 0f97e48a1..2ba6eda66 100644 --- a/libraries/ESP8266WiFi/src/ESP8266WiFi.cpp +++ b/libraries/ESP8266WiFi/src/ESP8266WiFi.cpp @@ -40,6 +40,7 @@ extern "C" void esp_yield(); ESP8266WiFiClass::ESP8266WiFiClass() : _useApMode(false) , _useClientMode(false) +, _useStaticIp(false) { } @@ -100,7 +101,8 @@ int ESP8266WiFiClass::begin(const char* ssid, const char *passphrase, int32_t ch wifi_set_channel(channel); } - wifi_station_dhcpc_start(); + if(!_useStaticIp) + wifi_station_dhcpc_start(); return status(); } @@ -112,6 +114,8 @@ uint8_t ESP8266WiFiClass::waitForConnectResult(){ return status(); } + +// You will have to set the DNS-Server manually later since this will not enable DHCP void ESP8266WiFiClass::config(IPAddress local_ip, IPAddress gateway, IPAddress subnet) { struct ip_info info; @@ -121,6 +125,26 @@ void ESP8266WiFiClass::config(IPAddress local_ip, IPAddress gateway, IPAddress s wifi_station_dhcpc_stop(); wifi_set_ip_info(STATION_IF, &info); + + _useStaticIp = true; +} + +void ESP8266WiFiClass::config(IPAddress local_ip, IPAddress gateway, IPAddress subnet, IPAddress dns) +{ + struct ip_info info; + info.ip.addr = static_cast(local_ip); + info.gw.addr = static_cast(gateway); + info.netmask.addr = static_cast(subnet); + + wifi_station_dhcpc_stop(); + wifi_set_ip_info(STATION_IF, &info); + + // Set DNS-Server + ip_addr_t d; + d.addr = static_cast(dns); + dns_setserver(0,&d); + + _useStaticIp = true; } int ESP8266WiFiClass::disconnect() diff --git a/libraries/ESP8266WiFi/src/ESP8266WiFi.h b/libraries/ESP8266WiFi/src/ESP8266WiFi.h index 64563ad7e..5591343ab 100644 --- a/libraries/ESP8266WiFi/src/ESP8266WiFi.h +++ b/libraries/ESP8266WiFi/src/ESP8266WiFi.h @@ -75,7 +75,6 @@ public: */ void softAP(const char* ssid, const char* passphrase, int channel = 1); - /* Change Ip configuration settings disabling the dhcp client * * param local_ip: Static ip configuration @@ -84,6 +83,15 @@ public: */ void config(IPAddress local_ip, IPAddress gateway, IPAddress subnet); + /* Change Ip configuration settings disabling the dhcp client + * + * param local_ip: Static ip configuration + * param gateway: Static gateway configuration + * param subnet: Static Subnet mask + * param dns: Defined DNS + */ + void config(IPAddress local_ip, IPAddress gateway, IPAddress subnet, IPAddress dns); + /* Configure access point * * param local_ip: access point IP @@ -310,7 +318,8 @@ protected: bool _useApMode; bool _useClientMode; - + bool _useStaticIp; + static size_t _scanCount; static void* _scanResult; From c0df9b0430b6ff0df2273cad41e1f79896a051aa Mon Sep 17 00:00:00 2001 From: Markus Sattler Date: Fri, 5 Jun 2015 11:48:02 +0200 Subject: [PATCH 11/18] fix #386 --- .../ESP8266WiFi/src/ESP8266WiFiMulti.cpp | 27 ++++++++++++------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/libraries/ESP8266WiFi/src/ESP8266WiFiMulti.cpp b/libraries/ESP8266WiFi/src/ESP8266WiFiMulti.cpp index 7161c399c..91f03bbc0 100644 --- a/libraries/ESP8266WiFi/src/ESP8266WiFiMulti.cpp +++ b/libraries/ESP8266WiFi/src/ESP8266WiFiMulti.cpp @@ -72,7 +72,6 @@ wl_status_t ESP8266WiFiMulti::run(void) { WiFi.getNetworkInfo(i, ssid_scan, sec_scan, rssi_scan, BSSID_scan, chan_scan, hidden_scan); - bool known = false; for(uint32_t x = 0; x < APlist.size(); x++) { WifiAPlist_t entry = APlist[x]; @@ -152,7 +151,17 @@ bool ESP8266WiFiMulti::APlistAdd(const char* ssid, const char *passphrase) { WifiAPlist_t newAP; - newAP.ssid = (char*) malloc(strlen(ssid)); + if(!ssid || strlen(ssid) > 31) { + // fail SSID to long or missing! + return false; + } + + if(passphrase && strlen(passphrase) > 63) { + // fail passphrase to long! + return false; + } + + newAP.ssid = (char*) malloc((strlen(ssid) + 1)); if(!newAP.ssid) { return false; @@ -161,16 +170,14 @@ bool ESP8266WiFiMulti::APlistAdd(const char* ssid, const char *passphrase) { strcpy(newAP.ssid, ssid); if(passphrase && *passphrase != 0x00) { - newAP.passphrase = (char*) malloc(strlen(passphrase)); + newAP.passphrase = (char*) malloc((strlen(passphrase) + 1)); + if(!newAP.passphrase) { + free(newAP.ssid); + return false; + } + strcpy(newAP.passphrase, passphrase); } - if(!newAP.passphrase) { - free(newAP.ssid); - return false; - } - - strcpy(newAP.passphrase, passphrase); - APlist.push_back(newAP); return true; } From 14eb2b30d1e58909e89ef4126c3157e5e56fd349 Mon Sep 17 00:00:00 2001 From: Dario Di Maio Date: Thu, 4 Jun 2015 16:51:52 +0200 Subject: [PATCH 12/18] Update README.md --- README.md | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 174b078ed..1004502e1 100644 --- a/README.md +++ b/README.md @@ -193,14 +193,15 @@ While many RC servo motors will accept the 3.3v IO data pin from a esp8266, most Libraries that don't rely on low-level access to AVR registers should work well. Here are a few libraries that were verified to work: -- [aREST](https://github.com/marcoschwartz/aREST) REST API handler library. -- [PubSubClient](https://github.com/Imroy/pubsubclient) MQTT library by @Imroy. -- [DHT11](https://github.com/adafruit/DHT-sensor-library) - initialize DHT as follows: ```DHT dht(DHTPIN, DHTTYPE, 15);``` -- [DallasTemperature](https://github.com/milesburton/Arduino-Temperature-Control-Library.git) -- [NeoPixelBus](https://github.com/Makuna/NeoPixelBus) - Arduino NeoPixel library compatible with esp8266. -- [RTC](https://github.com/Makuna/Rtc) - Arduino Library for Ds1307 & Ds3231 compatible with esp8266. -- [Blynk](https://github.com/blynkkk/blynk-library) - easy IoT framework for Makers (check out the [Kickstarter page](http://tiny.cc/blynk-kick)). - [arduinoWebSockets](https://github.com/Links2004/arduinoWebSockets) - WebSocket Server and Client compatible with esp8266 (RFC6455) +- [aREST](https://github.com/marcoschwartz/aREST) REST API handler library. +- [Blynk](https://github.com/blynkkk/blynk-library) - easy IoT framework for Makers (check out the [Kickstarter page](http://tiny.cc/blynk-kick)). +- [DallasTemperature](https://github.com/milesburton/Arduino-Temperature-Control-Library.git) +- [DHT11](https://github.com/adafruit/DHT-sensor-library) - initialize DHT as follows: ```DHT dht(DHTPIN, DHTTYPE, 15);``` +- [NeoPixelBus](https://github.com/Makuna/NeoPixelBus) - Arduino NeoPixel library compatible with esp8266. +- [PubSubClient](https://github.com/Imroy/pubsubclient) MQTT library by @Imroy. +- [RTC](https://github.com/Makuna/Rtc) - Arduino Library for Ds1307 & Ds3231 compatible with esp8266. +- [Souliss, Smart Home](https://github.com/souliss/souliss) - Framework for Smart Home based on Arduino, Android and openHAB. #### Upload via serial port #### Pick the correct serial port. From a4126b123568f2dc1ba886e5c7e6e6dbb4eafe30 Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Fri, 5 Jun 2015 08:04:10 +0300 Subject: [PATCH 13/18] Fix typo --- bootloaders/eboot/Makefile | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/bootloaders/eboot/Makefile b/bootloaders/eboot/Makefile index cd9e14143..1364ac0d0 100644 --- a/bootloaders/eboot/Makefile +++ b/bootloaders/eboot/Makefile @@ -1,4 +1,4 @@ -XTENSA_TOOCHAIN ?= +XTENSA_TOOLCHAIN ?= BIN_DIR := ./ TARGET_DIR := ./ @@ -9,11 +9,11 @@ TARGET_OBJ_FILES := \ TARGET_OBJ_PATHS := $(addprefix $(TARGET_DIR)/,$(TARGET_OBJ_FILES)) -CC := $(XTENSA_TOOCHAIN)xtensa-lx106-elf-gcc -CXX := $(XTENSA_TOOCHAIN)xtensa-lx106-elf-g++ -AR := $(XTENSA_TOOCHAIN)xtensa-lx106-elf-ar -LD := $(XTENSA_TOOCHAIN)xtensa-lx106-elf-gcc -OBJDUMP := $(XTENSA_TOOCHAIN)xtensa-lx106-elf-objdump +CC := $(XTENSA_TOOLCHAIN)xtensa-lx106-elf-gcc +CXX := $(XTENSA_TOOLCHAIN)xtensa-lx106-elf-g++ +AR := $(XTENSA_TOOLCHAIN)xtensa-lx106-elf-ar +LD := $(XTENSA_TOOLCHAIN)xtensa-lx106-elf-gcc +OBJDUMP := $(XTENSA_TOOLCHAIN)xtensa-lx106-elf-objdump CFLAGS += -std=gnu99 From 73740d6e6d5c0a684438d73a78d319c4c3cd5686 Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Fri, 5 Jun 2015 08:08:53 +0300 Subject: [PATCH 14/18] Clean up eboot --- bootloaders/eboot/Makefile | 1 + bootloaders/eboot/eboot.c | 57 +++++++------------------ bootloaders/eboot/eboot.elf | Bin 9816 -> 11233 bytes bootloaders/eboot/eboot_command.c | 26 +++++++++-- bootloaders/eboot/eboot_command.h | 5 ++- bootloaders/eboot/flash.c | 42 ++++++++++++++++++ bootloaders/eboot/{eboot.h => flash.h} | 9 ++-- 7 files changed, 88 insertions(+), 52 deletions(-) create mode 100644 bootloaders/eboot/flash.c rename bootloaders/eboot/{eboot.h => flash.h} (90%) diff --git a/bootloaders/eboot/Makefile b/bootloaders/eboot/Makefile index 1364ac0d0..0872ee35f 100644 --- a/bootloaders/eboot/Makefile +++ b/bootloaders/eboot/Makefile @@ -6,6 +6,7 @@ TARGET_DIR := ./ TARGET_OBJ_FILES := \ eboot.o \ eboot_command.o \ + flash.o \ TARGET_OBJ_PATHS := $(addprefix $(TARGET_DIR)/,$(TARGET_OBJ_FILES)) diff --git a/bootloaders/eboot/eboot.c b/bootloaders/eboot/eboot.c index b3193e299..0b74fcdf0 100644 --- a/bootloaders/eboot/eboot.c +++ b/bootloaders/eboot/eboot.c @@ -9,9 +9,8 @@ #include #include #include -#include "eboot.h" +#include "flash.h" #include "eboot_command.h" -extern void* flashchip; #define SWRST do { (*((volatile uint32_t*) 0x60000700)) |= 0x80000000; } while(0); @@ -73,53 +72,21 @@ int load_app_from_flash_raw(const uint32_t flash_addr) -int erase(const uint32_t start, const uint32_t size) -{ - if (start & (FLASH_SECTOR_SIZE - 1) != 0) { - return 1; - } - - const uint32_t sectors_per_block = FLASH_BLOCK_SIZE / FLASH_SECTOR_SIZE; - uint32_t current_sector = start / FLASH_SECTOR_SIZE; - uint32_t sector_count = (size + FLASH_SECTOR_SIZE - 1) / FLASH_SECTOR_SIZE; - const uint32_t end = current_sector + sector_count; - - for (; current_sector < end && (current_sector & (sectors_per_block-1)); - ++current_sector, --sector_count) { - if (SPIEraseSector(current_sector)) { - return 2; - } - } - - for (;current_sector + sectors_per_block <= end; - current_sector += sectors_per_block, - sector_count -= sectors_per_block) { - if (SPIEraseBlock(current_sector / sectors_per_block)) { - return 3; - } - } - - for (; current_sector < end; - ++current_sector, --sector_count) { - if (SPIEraseSector(current_sector)) { - return 4; - } - } - - return 0; -} - int copy_raw(const uint32_t src_addr, const uint32_t dst_addr, const uint32_t size) { + ets_putc('\n'); + ets_putc('c'); + ets_putc('p'); + ets_putc('\n'); // require regions to be aligned if (src_addr & 0xfff != 0 || dst_addr & 0xfff != 0) { return 1; } - if (erase(dst_addr, size)) { + if (SPIEraseAreaEx(dst_addr, size)) { return 2; } @@ -153,17 +120,25 @@ void main() int res = 9; struct eboot_command cmd; - eboot_command_read(&cmd); + if (eboot_command_read(&cmd)) { + cmd.action = ACTION_LOAD_APP; + cmd.args[0] = 0; + ets_putc('e'); + } else { + ets_putc('@'); + } + eboot_command_clear(); if (cmd.action == ACTION_COPY_RAW) { res = copy_raw(cmd.args[0], cmd.args[1], cmd.args[2]); if (res == 0) { cmd.action = ACTION_LOAD_APP; + cmd.args[0] = cmd.args[1]; } } if (cmd.action == ACTION_LOAD_APP) { - res = load_app_from_flash_raw(0); + res = load_app_from_flash_raw(cmd.args[0]); } if (res) { diff --git a/bootloaders/eboot/eboot.elf b/bootloaders/eboot/eboot.elf index 0637a05253c2b3f61f91954695e5fd4b116cadc6..97e25c14616a9f6e768711b46c6cafa6f62df21e 100755 GIT binary patch literal 11233 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 diff --git a/bootloaders/eboot/eboot_command.c b/bootloaders/eboot/eboot_command.c index 1e9cbed2c..648039e48 100644 --- a/bootloaders/eboot/eboot_command.c +++ b/bootloaders/eboot/eboot_command.c @@ -28,7 +28,7 @@ uint32_t eboot_command_calculate_crc32(const struct eboot_command* cmd) offsetof(struct eboot_command, crc32)); } -void eboot_command_read(struct eboot_command* cmd) +int eboot_command_read(struct eboot_command* cmd) { const uint32_t dw_count = sizeof(struct eboot_command) / sizeof(uint32_t); uint32_t* dst = (uint32_t *) cmd; @@ -39,9 +39,27 @@ void eboot_command_read(struct eboot_command* cmd) uint32_t crc32 = eboot_command_calculate_crc32(cmd); if (cmd->magic & EBOOT_MAGIC_MASK != EBOOT_MAGIC || cmd->crc32 != crc32) { - - cmd->action = ACTION_LOAD_APP; - cmd->args[0] = 0; + return 1; + } + + return 0; +} + +void eboot_command_write(struct eboot_command* cmd) +{ + cmd->magic = EBOOT_MAGIC; + cmd->crc32 = eboot_command_calculate_crc32(cmd); + + const uint32_t dw_count = sizeof(struct eboot_command) / sizeof(uint32_t); + const uint32_t* src = (const uint32_t *) cmd; + for (uint32_t i = 0; i < dw_count; ++i) { + RTC_MEM[i] = src[i]; } } +void eboot_command_clear() +{ + RTC_MEM[offsetof(struct eboot_command, magic) / sizeof(uint32_t)] = 0; + RTC_MEM[offsetof(struct eboot_command, crc32) / sizeof(uint32_t)] = 0; +} + diff --git a/bootloaders/eboot/eboot_command.h b/bootloaders/eboot/eboot_command.h index aa0fc11bb..cf40c135d 100644 --- a/bootloaders/eboot/eboot_command.h +++ b/bootloaders/eboot/eboot_command.h @@ -23,7 +23,8 @@ struct eboot_command { }; -void eboot_command_read(struct eboot_command* cmd); - +int eboot_command_read(struct eboot_command* cmd); +void eboot_command_write(struct eboot_command* cmd); +void eboot_command_clear(); #endif //EBOOT_COMMAND_H diff --git a/bootloaders/eboot/flash.c b/bootloaders/eboot/flash.c new file mode 100644 index 000000000..6f95a472d --- /dev/null +++ b/bootloaders/eboot/flash.c @@ -0,0 +1,42 @@ +#include +#include +#include +#include "flash.h" + + +int SPIEraseAreaEx(const uint32_t start, const uint32_t size) +{ + if (start & (FLASH_SECTOR_SIZE - 1) != 0) { + return 1; + } + + const uint32_t sectors_per_block = FLASH_BLOCK_SIZE / FLASH_SECTOR_SIZE; + uint32_t current_sector = start / FLASH_SECTOR_SIZE; + uint32_t sector_count = (size + FLASH_SECTOR_SIZE - 1) / FLASH_SECTOR_SIZE; + const uint32_t end = current_sector + sector_count; + + for (; current_sector < end && (current_sector & (sectors_per_block-1)); + ++current_sector, --sector_count) { + if (SPIEraseSector(current_sector)) { + return 2; + } + } + + for (;current_sector + sectors_per_block <= end; + current_sector += sectors_per_block, + sector_count -= sectors_per_block) { + if (SPIEraseBlock(current_sector / sectors_per_block)) { + return 3; + } + } + + for (; current_sector < end; + ++current_sector, --sector_count) { + if (SPIEraseSector(current_sector)) { + return 4; + } + } + + return 0; +} + diff --git a/bootloaders/eboot/eboot.h b/bootloaders/eboot/flash.h similarity index 90% rename from bootloaders/eboot/eboot.h rename to bootloaders/eboot/flash.h index 973c616a8..ea8b65c1f 100644 --- a/bootloaders/eboot/eboot.h +++ b/bootloaders/eboot/flash.h @@ -5,15 +5,14 @@ * 3-clause BSD license to be found in the LICENSE file. */ -#ifndef EBOOT_H -#define EBOOT_H - +#ifndef FLASH_H +#define FLASH_H int SPIEraseBlock(uint32_t block); int SPIEraseSector(uint32_t sector); int SPIRead(uint32_t addr, void *dest, size_t size); int SPIWrite(uint32_t addr, void *src, size_t size); - +int SPIEraseAreaEx(const uint32_t start, const uint32_t size); #define FLASH_SECTOR_SIZE 0x1000 #define FLASH_BLOCK_SIZE 0x10000 @@ -41,4 +40,4 @@ typedef struct { -#endif //EBOOT_H +#endif //FLASH_H From becc1d32eddd572465692b0b683145c37609e8a2 Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Fri, 5 Jun 2015 08:19:47 +0300 Subject: [PATCH 15/18] rename EspClass::eraseESPconfig to eraseConfig --- cores/esp8266/Esp.cpp | 2 +- cores/esp8266/Esp.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/cores/esp8266/Esp.cpp b/cores/esp8266/Esp.cpp index 946a8b375..419cb889a 100644 --- a/cores/esp8266/Esp.cpp +++ b/cores/esp8266/Esp.cpp @@ -295,7 +295,7 @@ struct rst_info * EspClass::getResetInfoPtr(void) { return &resetInfo; } -bool EspClass::eraseESPconfig(void) { +bool EspClass::eraseConfig(void) { bool ret = true; size_t cfgAddr = (ESP.getFlashChipSize() - 0x4000); size_t cfgSize = (8*1024); diff --git a/cores/esp8266/Esp.h b/cores/esp8266/Esp.h index 9411dc5f0..ecb80da07 100644 --- a/cores/esp8266/Esp.h +++ b/cores/esp8266/Esp.h @@ -101,7 +101,7 @@ class EspClass { String getResetInfo(void); struct rst_info * getResetInfoPtr(void); - bool eraseESPconfig(void); + bool eraseConfig(void); inline uint32_t getCycleCount(void); }; From d24fa4636cc2607f06155c4adf1d6b3aafd6e49b Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Fri, 5 Jun 2015 08:29:15 +0300 Subject: [PATCH 16/18] Add some headers --- bootloaders/eboot/eboot_command.h | 7 +++++++ bootloaders/eboot/flash.c | 7 +++++++ 2 files changed, 14 insertions(+) diff --git a/bootloaders/eboot/eboot_command.h b/bootloaders/eboot/eboot_command.h index cf40c135d..ba9c889a2 100644 --- a/bootloaders/eboot/eboot_command.h +++ b/bootloaders/eboot/eboot_command.h @@ -1,3 +1,10 @@ +/* Copyright (c) 2015 Ivan Grokhotkov. All rights reserved. + * This file is part of eboot bootloader. + * + * Redistribution and use is permitted according to the conditions of the + * 3-clause BSD license to be found in the LICENSE file. + */ + #ifndef EBOOT_COMMAND_H #define EBOOT_COMMAND_H diff --git a/bootloaders/eboot/flash.c b/bootloaders/eboot/flash.c index 6f95a472d..f90e25b34 100644 --- a/bootloaders/eboot/flash.c +++ b/bootloaders/eboot/flash.c @@ -1,3 +1,10 @@ +/* Copyright (c) 2015 Ivan Grokhotkov. All rights reserved. + * This file is part of eboot bootloader. + * + * Redistribution and use is permitted according to the conditions of the + * 3-clause BSD license to be found in the LICENSE file. + */ + #include #include #include From 26eede862f1e13ab9f9ba81aafb3162865edb02e Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Fri, 5 Jun 2015 13:48:00 +0300 Subject: [PATCH 17/18] Add function to update sketch from Stream --- cores/esp8266/Esp.cpp | 125 +++++++++++++++++++++ cores/esp8266/Esp.h | 48 ++++---- cores/esp8266/core_esp8266_eboot_command.c | 88 +++++++++++++++ cores/esp8266/core_esp8266_flash_utils.c | 64 +++++++++++ cores/esp8266/eboot_command.h | 36 ++++++ cores/esp8266/flash_utils.h | 63 +++++++++++ 6 files changed, 402 insertions(+), 22 deletions(-) create mode 100644 cores/esp8266/core_esp8266_eboot_command.c create mode 100644 cores/esp8266/core_esp8266_flash_utils.c create mode 100644 cores/esp8266/eboot_command.h create mode 100644 cores/esp8266/flash_utils.h diff --git a/cores/esp8266/Esp.cpp b/cores/esp8266/Esp.cpp index 419cb889a..73367683a 100644 --- a/cores/esp8266/Esp.cpp +++ b/cores/esp8266/Esp.cpp @@ -19,6 +19,9 @@ */ #include "Arduino.h" +#include "flash_utils.h" +#include "eboot_command.h" +#include extern "C" { #include "user_interface.h" @@ -26,6 +29,9 @@ extern "C" { extern struct rst_info resetInfo; } + +// #define DEBUG_SERIAL Serial + //extern "C" void ets_wdt_init(uint32_t val); extern "C" void ets_wdt_enable(void); extern "C" void ets_wdt_disable(void); @@ -315,4 +321,123 @@ bool EspClass::eraseConfig(void) { return ret; } +uint32_t EspClass::getSketchSize() { + static uint32_t result = 0; + if (result) + return result; + + image_header_t image_header; + uint32_t pos = APP_START_OFFSET; + if (spi_flash_read(pos, (uint32_t*) &image_header, sizeof(image_header))) { + return 0; + } + pos += sizeof(image_header); +#ifdef DEBUG_SERIAL + DEBUG_SERIAL.printf("num_segments=%u\r\n", image_header.num_segments); +#endif + for (uint32_t section_index = 0; + section_index < image_header.num_segments; + ++section_index) + { + section_header_t section_header = {0}; + if (spi_flash_read(pos, (uint32_t*) §ion_header, sizeof(section_header))) { + return 0; + } + pos += sizeof(section_header); + pos += section_header.size; +#ifdef DEBUG_SERIAL + DEBUG_SERIAL.printf("section=%u size=%u pos=%u\r\n", section_index, section_header.size, pos); +#endif + } + result = pos; + return result; +} + +extern "C" uint32_t _SPIFFS_start; + +uint32_t EspClass::getFreeSketchSpace() { + + uint32_t usedSize = getSketchSize(); + // round one sector up + uint32_t freeSpaceStart = (usedSize + FLASH_SECTOR_SIZE - 1) & (~(FLASH_SECTOR_SIZE - 1)); + uint32_t freeSpaceEnd = (uint32_t)&_SPIFFS_start - 0x40200000; + +#ifdef DEBUG_SERIAL + DEBUG_SERIAL.printf("usedSize=%u freeSpaceStart=%u freeSpaceEnd=%u\r\n", usedSize, freeSpaceStart, freeSpaceEnd); +#endif + return freeSpaceEnd - freeSpaceStart; +} + +bool EspClass::updateSketch(Stream& in, uint32_t size) { + + if (size > getFreeSketchSpace()) + return false; + + uint32_t usedSize = getSketchSize(); + uint32_t freeSpaceStart = (usedSize + FLASH_SECTOR_SIZE - 1) & (~(FLASH_SECTOR_SIZE - 1)); + uint32_t roundedSize = (size + FLASH_SECTOR_SIZE - 1) & (~(FLASH_SECTOR_SIZE - 1)); + +#ifdef DEBUG_SERIAL + DEBUG_SERIAL.printf("erase @0x%x size=0x%x\r\n", freeSpaceStart, roundedSize); +#endif + + noInterrupts(); + int rc = SPIEraseAreaEx(freeSpaceStart, roundedSize); + interrupts(); + if (rc) + return false; + +#ifdef DEBUG_SERIAL + DEBUG_SERIAL.println("erase done"); +#endif + + uint32_t addr = freeSpaceStart; + uint32_t left = size; + + const uint32_t bufferSize = FLASH_SECTOR_SIZE; + std::unique_ptr buffer(new uint8_t[bufferSize]); + +#ifdef DEBUG_SERIAL + DEBUG_SERIAL.println("writing"); +#endif + while (left > 0) { + size_t willRead = (left < bufferSize) ? left : bufferSize; + size_t rd = in.readBytes(buffer.get(), willRead); + if (rd != willRead) { +#ifdef DEBUG_SERIAL + DEBUG_SERIAL.println("stream read failed"); +#endif + return false; + } + + noInterrupts(); + rc = SPIWrite(addr, buffer.get(), willRead); + interrupts(); + if (rc) { +#ifdef DEBUG_SERIAL + DEBUG_SERIAL.println("write failed"); +#endif + return false; + } + + addr += willRead; + left -= willRead; +#ifdef DEBUG_SERIAL + DEBUG_SERIAL.print("."); +#endif + } + +#ifdef DEBUG_SERIAL + DEBUG_SERIAL.println("\r\nrestarting"); +#endif + eboot_command ebcmd; + ebcmd.action = ACTION_COPY_RAW; + ebcmd.args[0] = freeSpaceStart; + ebcmd.args[1] = 0x00000; + ebcmd.args[2] = size; + eboot_command_write(&ebcmd); + + ESP.restart(); + return true; // never happens +} diff --git a/cores/esp8266/Esp.h b/cores/esp8266/Esp.h index ecb80da07..2b58b79d1 100644 --- a/cores/esp8266/Esp.h +++ b/cores/esp8266/Esp.h @@ -69,44 +69,48 @@ class EspClass { // note: setting the timeout value is not implemented at the moment void wdtEnable(WDTO_t timeout_ms = WDTO_0MS); - void wdtDisable(void); - void wdtFeed(void); + void wdtDisable(); + void wdtFeed(); void deepSleep(uint32_t time_us, WakeMode mode = WAKE_RF_DEFAULT); - void reset(void); - void restart(void); + void reset(); + void restart(); - uint16_t getVcc(void); - uint32_t getFreeHeap(void); + uint16_t getVcc(); + uint32_t getFreeHeap(); - uint32_t getChipId(void); + uint32_t getChipId(); - const char * getSdkVersion(void); + const char * getSdkVersion(); - uint8_t getBootVersion(void); - uint8_t getBootMode(void); + uint8_t getBootVersion(); + uint8_t getBootMode(); - uint8_t getCpuFreqMHz(void); + uint8_t getCpuFreqMHz(); - uint32_t getFlashChipId(void); + uint32_t getFlashChipId(); //gets the actual chip size based on the flash id - uint32_t getFlashChipRealSize(void); + uint32_t getFlashChipRealSize(); //gets the size of the flash as set by the compiler - uint32_t getFlashChipSize(void); - uint32_t getFlashChipSpeed(void); - FlashMode_t getFlashChipMode(void); - uint32_t getFlashChipSizeByChipId(void); + uint32_t getFlashChipSize(); + uint32_t getFlashChipSpeed(); + FlashMode_t getFlashChipMode(); + uint32_t getFlashChipSizeByChipId(); - String getResetInfo(void); - struct rst_info * getResetInfoPtr(void); + uint32_t getSketchSize(); + uint32_t getFreeSketchSpace(); + bool updateSketch(Stream& in, uint32_t size); - bool eraseConfig(void); + String getResetInfo(); + struct rst_info * getResetInfoPtr(); - inline uint32_t getCycleCount(void); + bool eraseConfig(); + + inline uint32_t getCycleCount(); }; -uint32_t EspClass::getCycleCount(void) +uint32_t EspClass::getCycleCount() { uint32_t ccount; __asm__ __volatile__("rsr %0,ccount":"=a" (ccount)); diff --git a/cores/esp8266/core_esp8266_eboot_command.c b/cores/esp8266/core_esp8266_eboot_command.c new file mode 100644 index 000000000..60c92bf18 --- /dev/null +++ b/cores/esp8266/core_esp8266_eboot_command.c @@ -0,0 +1,88 @@ +/* + core_esp8266_eboot_command.c - interface to the eboot bootloader + + Copyright (c) 2015 Ivan Grokhotkov. All rights reserved. + This file is part of the esp8266 core for Arduino environment. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include "eboot_command.h" + +uint32_t crc_update(uint32_t crc, const uint8_t *data, size_t length) +{ + uint32_t i; + bool bit; + uint8_t c; + + while (length--) { + c = *data++; + for (i = 0x80; i > 0; i >>= 1) { + bit = crc & 0x80000000; + if (c & i) { + bit = !bit; + } + crc <<= 1; + if (bit) { + crc ^= 0x04c11db7; + } + } + } + return crc; +} + +uint32_t eboot_command_calculate_crc32(const struct eboot_command* cmd) +{ + return crc_update(0xffffffff, (const uint8_t*) cmd, + offsetof(struct eboot_command, crc32)); +} + +int eboot_command_read(struct eboot_command* cmd) +{ + const uint32_t dw_count = sizeof(struct eboot_command) / sizeof(uint32_t); + uint32_t* dst = (uint32_t *) cmd; + for (uint32_t i = 0; i < dw_count; ++i) { + dst[i] = RTC_MEM[i]; + } + + uint32_t crc32 = eboot_command_calculate_crc32(cmd); + if (cmd->magic & EBOOT_MAGIC_MASK != EBOOT_MAGIC || + cmd->crc32 != crc32) { + return 1; + } + + return 0; +} + +void eboot_command_write(struct eboot_command* cmd) +{ + cmd->magic = EBOOT_MAGIC; + cmd->crc32 = eboot_command_calculate_crc32(cmd); + + const uint32_t dw_count = sizeof(struct eboot_command) / sizeof(uint32_t); + const uint32_t* src = (const uint32_t *) cmd; + for (uint32_t i = 0; i < dw_count; ++i) { + RTC_MEM[i] = src[i]; + } +} + +void eboot_command_clear() +{ + RTC_MEM[offsetof(struct eboot_command, magic) / sizeof(uint32_t)] = 0; + RTC_MEM[offsetof(struct eboot_command, crc32) / sizeof(uint32_t)] = 0; +} + diff --git a/cores/esp8266/core_esp8266_flash_utils.c b/cores/esp8266/core_esp8266_flash_utils.c new file mode 100644 index 000000000..6f8a34f41 --- /dev/null +++ b/cores/esp8266/core_esp8266_flash_utils.c @@ -0,0 +1,64 @@ +/* + core_esp8266_flash_utils.c - flash and binary image helpers + + Copyright (c) 2015 Ivan Grokhotkov. All rights reserved. + This file is part of the esp8266 core for Arduino environment. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + + +#include +#include +#include +#include "flash_utils.h" + + +int SPIEraseAreaEx(const uint32_t start, const uint32_t size) +{ + if (start & (FLASH_SECTOR_SIZE - 1) != 0) { + return 1; + } + + const uint32_t sectors_per_block = FLASH_BLOCK_SIZE / FLASH_SECTOR_SIZE; + uint32_t current_sector = start / FLASH_SECTOR_SIZE; + uint32_t sector_count = (size + FLASH_SECTOR_SIZE - 1) / FLASH_SECTOR_SIZE; + const uint32_t end = current_sector + sector_count; + + for (; current_sector < end && (current_sector & (sectors_per_block-1)); + ++current_sector, --sector_count) { + if (SPIEraseSector(current_sector)) { + return 2; + } + } + + for (;current_sector + sectors_per_block <= end; + current_sector += sectors_per_block, + sector_count -= sectors_per_block) { + if (SPIEraseBlock(current_sector / sectors_per_block)) { + return 3; + } + } + + for (; current_sector < end; + ++current_sector, --sector_count) { + if (SPIEraseSector(current_sector)) { + return 4; + } + } + + return 0; +} + diff --git a/cores/esp8266/eboot_command.h b/cores/esp8266/eboot_command.h new file mode 100644 index 000000000..3d854afba --- /dev/null +++ b/cores/esp8266/eboot_command.h @@ -0,0 +1,36 @@ +#ifndef EBOOT_COMMAND_H +#define EBOOT_COMMAND_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define RTC_MEM ((volatile uint32_t*)0x60001200) + +enum action_t { + ACTION_COPY_RAW = 0x00000001, + ACTION_LOAD_APP = 0xffffffff +}; + +#define EBOOT_MAGIC 0xeb001000 +#define EBOOT_MAGIC_MASK 0xfffff000 + +struct eboot_command { + uint32_t magic; + enum action_t action; + uint32_t args[29]; + uint32_t crc32; +}; + + +int eboot_command_read(struct eboot_command* cmd); +void eboot_command_write(struct eboot_command* cmd); +void eboot_command_clear(); + +#ifdef __cplusplus +} +#endif + +#endif //EBOOT_COMMAND_H diff --git a/cores/esp8266/flash_utils.h b/cores/esp8266/flash_utils.h new file mode 100644 index 000000000..4e5f2120b --- /dev/null +++ b/cores/esp8266/flash_utils.h @@ -0,0 +1,63 @@ +/* + flash_utils.h - Flash access function and data structures + Copyright (c) 2015 Ivan Grokhotkov. All right reserved. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + + +#ifndef FLASH_UTILS_H +#define FLASH_UTILS_H + +#ifdef __cplusplus +extern "C" { +#endif + +int SPIEraseBlock(uint32_t block); +int SPIEraseSector(uint32_t sector); +int SPIRead(uint32_t addr, void *dest, size_t size); +int SPIWrite(uint32_t addr, void *src, size_t size); +int SPIEraseAreaEx(const uint32_t start, const uint32_t size); + +#define FLASH_SECTOR_SIZE 0x1000 +#define FLASH_BLOCK_SIZE 0x10000 +#define APP_START_OFFSET 0x1000 + +typedef struct { + unsigned char magic; + unsigned char num_segments; + + /* SPI Flash Interface (0 = QIO, 1 = QOUT, 2 = DIO, 0x3 = DOUT) */ + unsigned char flash_mode; + + /* High four bits: 0 = 512K, 1 = 256K, 2 = 1M, 3 = 2M, 4 = 4M, + Low four bits: 0 = 40MHz, 1= 26MHz, 2 = 20MHz, 0xf = 80MHz */ + unsigned char flash_size_freq; + + uint32_t entry; +} image_header_t; + + +typedef struct { + uint32_t address; + uint32_t size; +} section_header_t; + +#ifdef __cplusplus +} +#endif + + +#endif //FLASH_UTILS_H From 7f66a3a415df673177e4c67f154f8ee244249c48 Mon Sep 17 00:00:00 2001 From: Dario Di Maio Date: Thu, 4 Jun 2015 16:51:52 +0200 Subject: [PATCH 18/18] Remove unnecessary ICACHE_FLASH_ATTR --- libraries/ESP8266WiFi/src/WiFiClient.cpp | 48 ++++++++++++------------ 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/libraries/ESP8266WiFi/src/WiFiClient.cpp b/libraries/ESP8266WiFi/src/WiFiClient.cpp index 056d5bb65..727e64fc1 100644 --- a/libraries/ESP8266WiFi/src/WiFiClient.cpp +++ b/libraries/ESP8266WiFi/src/WiFiClient.cpp @@ -42,30 +42,30 @@ extern "C" uint16_t WiFiClient::_localPort = 0; -ICACHE_FLASH_ATTR WiFiClient::WiFiClient() +WiFiClient::WiFiClient() : _client(0) { } -ICACHE_FLASH_ATTR WiFiClient::WiFiClient(ClientContext* client) : _client(client) +WiFiClient::WiFiClient(ClientContext* client) : _client(client) { _client->ref(); } -ICACHE_FLASH_ATTR WiFiClient::~WiFiClient() +WiFiClient::~WiFiClient() { if (_client) _client->unref(); } -ICACHE_FLASH_ATTR WiFiClient::WiFiClient(const WiFiClient& other) +WiFiClient::WiFiClient(const WiFiClient& other) { _client = other._client; if (_client) _client->ref(); } -WiFiClient& ICACHE_FLASH_ATTR WiFiClient::operator=(const WiFiClient& other) +WiFiClient& WiFiClient::operator=(const WiFiClient& other) { if (_client) _client->unref(); @@ -76,7 +76,7 @@ WiFiClient& ICACHE_FLASH_ATTR WiFiClient::operator=(const WiFiClient& other) } -int ICACHE_FLASH_ATTR WiFiClient::connect(const char* host, uint16_t port) +int WiFiClient::connect(const char* host, uint16_t port) { IPAddress remote_addr; if (WiFi.hostByName(host, remote_addr)) @@ -86,7 +86,7 @@ int ICACHE_FLASH_ATTR WiFiClient::connect(const char* host, uint16_t port) return 0; } -int ICACHE_FLASH_ATTR WiFiClient::connect(IPAddress ip, uint16_t port) +int WiFiClient::connect(IPAddress ip, uint16_t port) { if (_client) stop(); @@ -114,7 +114,7 @@ int ICACHE_FLASH_ATTR WiFiClient::connect(IPAddress ip, uint16_t port) return 0; } -int8_t ICACHE_FLASH_ATTR WiFiClient::_connected(void* pcb, int8_t err) +int8_t WiFiClient::_connected(void* pcb, int8_t err) { tcp_pcb* tpcb = reinterpret_cast(pcb); _client = new ClientContext(tpcb, 0, 0); @@ -123,31 +123,31 @@ int8_t ICACHE_FLASH_ATTR WiFiClient::_connected(void* pcb, int8_t err) return ERR_OK; } -void ICACHE_FLASH_ATTR WiFiClient::_err(int8_t err) +void WiFiClient::_err(int8_t err) { DEBUGV(":err %d\r\n", err); esp_schedule(); } -void ICACHE_FLASH_ATTR WiFiClient::setNoDelay(bool nodelay) { +void WiFiClient::setNoDelay(bool nodelay) { if (!_client) return; _client->setNoDelay(nodelay); } -bool ICACHE_FLASH_ATTR WiFiClient::getNoDelay() { +bool WiFiClient::getNoDelay() { if (!_client) return false; return _client->getNoDelay(); } -size_t ICACHE_FLASH_ATTR WiFiClient::write(uint8_t b) +size_t WiFiClient::write(uint8_t b) { return write(&b, 1); } -size_t ICACHE_FLASH_ATTR WiFiClient::write(const uint8_t *buf, size_t size) +size_t WiFiClient::write(const uint8_t *buf, size_t size) { if (!_client || !size) { @@ -159,7 +159,7 @@ size_t ICACHE_FLASH_ATTR WiFiClient::write(const uint8_t *buf, size_t size) extern "C" uint32_t esp_micros_at_task_start(); -int ICACHE_FLASH_ATTR WiFiClient::available() +int WiFiClient::available() { static uint32_t lastPollTime = 0; if (!_client) @@ -174,7 +174,7 @@ int ICACHE_FLASH_ATTR WiFiClient::available() return result; } -int ICACHE_FLASH_ATTR WiFiClient::read() +int WiFiClient::read() { if (!available()) return -1; @@ -183,12 +183,12 @@ int ICACHE_FLASH_ATTR WiFiClient::read() } -int ICACHE_FLASH_ATTR WiFiClient::read(uint8_t* buf, size_t size) +int WiFiClient::read(uint8_t* buf, size_t size) { return (int) _client->read(reinterpret_cast(buf), size); } -int ICACHE_FLASH_ATTR WiFiClient::peek() +int WiFiClient::peek() { if (!available()) return -1; @@ -196,13 +196,13 @@ int ICACHE_FLASH_ATTR WiFiClient::peek() return _client->peek(); } -void ICACHE_FLASH_ATTR WiFiClient::flush() +void WiFiClient::flush() { if (_client) _client->flush(); } -void ICACHE_FLASH_ATTR WiFiClient::stop() +void WiFiClient::stop() { if (!_client) return; @@ -211,7 +211,7 @@ void ICACHE_FLASH_ATTR WiFiClient::stop() _client = 0; } -uint8_t ICACHE_FLASH_ATTR WiFiClient::connected() +uint8_t WiFiClient::connected() { if (!_client) return 0; @@ -219,14 +219,14 @@ uint8_t ICACHE_FLASH_ATTR WiFiClient::connected() return _client->state() == ESTABLISHED || available(); } -uint8_t ICACHE_FLASH_ATTR WiFiClient::status() +uint8_t WiFiClient::status() { if (!_client) return CLOSED; return _client->state(); } -ICACHE_FLASH_ATTR WiFiClient::operator bool() + WiFiClient::operator bool() { return _client != 0; } @@ -247,12 +247,12 @@ uint16_t WiFiClient::remotePort() return _client->getRemotePort(); } -int8_t ICACHE_FLASH_ATTR WiFiClient::_s_connected(void* arg, void* tpcb, int8_t err) +int8_t WiFiClient::_s_connected(void* arg, void* tpcb, int8_t err) { return reinterpret_cast(arg)->_connected(tpcb, err); } -void ICACHE_FLASH_ATTR WiFiClient::_s_err(void* arg, int8_t err) +void WiFiClient::_s_err(void* arg, int8_t err) { reinterpret_cast(arg)->_err(err); }