tag:blogger.com,1999:blog-78228836832442441822024-03-05T10:36:06.927+02:00low techmuxhttp://www.blogger.com/profile/07901500843676691342noreply@blogger.comBlogger35125tag:blogger.com,1999:blog-7822883683244244182.post-52601274481846559692015-06-14T22:45:00.000+02:002015-06-14T22:45:06.372+02:00AMS00x BLE Module<div dir="ltr" style="text-align: left;" trbidi="on">
I found this little guy while looking for parts on Mouser the other day:<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiZNeVm7WCmft3NbL2aaBQdhh5m7ugK9JhMZbglvnAmNHn7xvnF0Y-wqEGNtfaTpSyNHg1Hv6YrvyaPuvFOHO7bCUDKj2z3TesENUqSnsyHGyyTmrI8A-T-FkypTq6uQQCLyTh2jxqEjIQ/s1600/315_BLTE1.002.WEB.transparent-315-315.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="200" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiZNeVm7WCmft3NbL2aaBQdhh5m7ugK9JhMZbglvnAmNHn7xvnF0Y-wqEGNtfaTpSyNHg1Hv6YrvyaPuvFOHO7bCUDKj2z3TesENUqSnsyHGyyTmrI8A-T-FkypTq6uQQCLyTh2jxqEjIQ/s200/315_BLTE1.002.WEB.transparent-315-315.png" width="200" /></a> </div>
It's a <b>$6.50</b> certified BLE module from ACKme Networks based on a Broadcom <b>ARM
Cortex-M3</b> SoC! The module breaks out the ADC, USART,
SPI, I2C, PWM and GPIOs and ships with a pre-loaded firmware called <b>TruConnect</b> that lets you control the module via the serial port. <br />
<br />
They also have a dev board, with switches, buzzer, RGB LED, accelerometer, switching regulator and an <b>FTDI</b> chip great for quick evaluation but It's a bit expensive and there's a <b>jumper on the backside!</b> I had to buy one anyway because the module was not stocked yet, but I'll be getting the modules next time.<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhr34nUQLLdLYhyphenhyphentVkjiyP4PUs_ppSMkWZILScZ6nI10tgvQ16T4tnH27Lk3kHr_vpvZyVNlIv2__KAUV7jJ7I9FUENi6KEvP58U7A_nipix9NHdx3k-Z_mODVR6DTMMddD6Y9jS7mwjxA/s1600/WAHOO_SPL.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhr34nUQLLdLYhyphenhyphentVkjiyP4PUs_ppSMkWZILScZ6nI10tgvQ16T4tnH27Lk3kHr_vpvZyVNlIv2__KAUV7jJ7I9FUENi6KEvP58U7A_nipix9NHdx3k-Z_mODVR6DTMMddD6Y9jS7mwjxA/s320/WAHOO_SPL.jpg" width="320" /></a></div>
ACKme also released an <b>iOS</b> and <b>Android</b> apps for quick testing, the iOS app has more features, it lets you read the ADC and switches, use the serial interfaces and upgrade the firmware <b>
OTA</b>. However, I don't have an iOS device so I just used the Android app to connect to the module and blink the LED:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhTvnjaUHmUwTJToz9dsSN9hjGiFfxj0bhIXGJmrtdlUfWRiVC48zY55OITR6whvzTMx4-IpeiAEwip8V-tOnfg3XCAa_21U2WIhIQ9ufGRX-My2zns028Y8hyYywFAVwnEQo1bHMu9THM/s1600/CHDcny9XEAEfo-L.jpg%253Alarge.jpe" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="222" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhTvnjaUHmUwTJToz9dsSN9hjGiFfxj0bhIXGJmrtdlUfWRiVC48zY55OITR6whvzTMx4-IpeiAEwip8V-tOnfg3XCAa_21U2WIhIQ9ufGRX-My2zns028Y8hyYywFAVwnEQo1bHMu9THM/s320/CHDcny9XEAEfo-L.jpg%253Alarge.jpe" width="320" /></a></div>
<br />
I made a quick <b>breakout</b> board for future modules, you can order it directly from <a href="https://oshpark.com/shared_projects/hPHlWf7I">OSHPark</a> or checkout the <a href="https://github.com/iabdalkader/ams00x">repo</a> if you don't need a dev board. Note: This breakout is Not tested!<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjObDGhOV3m7snTQC_hyphenhyphenp-gxFk7VpKYuRL96k6Ylgy2ISWF2QCJGyPZfcE09ARaw2fUroi5YrP2erswTcQnXhEfTcPp-XKRnWlYFy_tYzslJ5_JKILsl8XcF9cQiBppczKFcs7v2HgR3js/s1600/Screenshot-1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="287" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjObDGhOV3m7snTQC_hyphenhyphenp-gxFk7VpKYuRL96k6Ylgy2ISWF2QCJGyPZfcE09ARaw2fUroi5YrP2erswTcQnXhEfTcPp-XKRnWlYFy_tYzslJ5_JKILsl8XcF9cQiBppczKFcs7v2HgR3js/s320/Screenshot-1.png" width="320" /></a></div>
<br /></div>
iabdalkaderhttp://www.blogger.com/profile/07526150314777847403noreply@blogger.com2tag:blogger.com,1999:blog-7822883683244244182.post-27795890444630979662015-03-14T01:37:00.000+02:002015-03-14T01:40:17.487+02:00THP 2014/2015, OpenMV, Kickstarter and Pi Day!<div dir="ltr" style="text-align: left;" trbidi="on">
It's been a while since I last wrote about anything, been very busy with THP, Kickstarter, new projects and day dreaming (more on that later), also I've been documenting OpenMV mostly on <a href="http://hackaday.io/">Hackaday.io</a><br />
<br />
However, today is a very special day, it's <b>Pi Day</b> of course, but it’s not just any Pi Day, today at 9:26:53 will describe Pi up to 10 digits, yay! Something that happens once in a lifetime, and if that's not enough, today marks exactly 5 years since my very first blog post and it also happens to be my birthday ;D <br />
<br />
Not being able to resist this historic day, I had to write something, so here's a long overdue post in which I'll try to document my experience with all
this stuff, and share with you some of the lessons I've learned along
the way.<br />
<br />
<b>THP 2014</b> <br />
Last year I submitted OpenMV for THP, I clearly remember saying to myself "Well, here goes nothing" and then I clicked submit, and bang it went viral! I received lots of comments, feedback, orders, even a few job offers! <br />
Shortly after that, OpenMV became the second most "Skulled", viewed and commented project on hackaday.io (and still is, so far). Even though I did not make it to the finals at the end of it, but overall, I think joining the contest was one of the best things I ever did.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj0FrloICcFl1SMK7V8zzw81YIxgKCkJlCMcU4QVPZe5uHrp6gfKcEHKRrCqLu8OtObqAuoW7LkK6YetISkc5qG_uVfX0ZFNw0YGOs2GMkB1aRZWvqdVsb_8_xfvpv-DjgRtz-AV4f4QqA/s1600/Screenshot.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj0FrloICcFl1SMK7V8zzw81YIxgKCkJlCMcU4QVPZe5uHrp6gfKcEHKRrCqLu8OtObqAuoW7LkK6YetISkc5qG_uVfX0ZFNw0YGOs2GMkB1aRZWvqdVsb_8_xfvpv-DjgRtz-AV4f4QqA/s1600/Screenshot.png" height="240" width="400" /></a></div>
<br />
<i>Hint: Just put your project out there, you have nothing to lose, try to document a lot, and if you're lucky, lots of awesome people will give you feedback and support.</i><br />
<br />
<b>Prototyping</b><br />
Having received lots of request for cameras, with the help of my friend <a href="http://www.bot-thoughts.com/">Michael Shimniok</a> we (well, mostly just him :D) went ahead and made a small prototyping run, just to see how things go before doing anything serious:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg86zTUCswCSFkdFxReIQ6OiE64CJN4GZfgbADyhDTSTN38yUYU4YVxXbEmtODxdJ0RUVyyU_mJ-GxozQ59_7dkJo3DRePCO-EoUE2mabz-IfW29AEfkyUOk0j3lkYtzqMBltzclicpmM4/s1600/5481281411087540949.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg86zTUCswCSFkdFxReIQ6OiE64CJN4GZfgbADyhDTSTN38yUYU4YVxXbEmtODxdJ0RUVyyU_mJ-GxozQ59_7dkJo3DRePCO-EoUE2mabz-IfW29AEfkyUOk0j3lkYtzqMBltzclicpmM4/s1600/5481281411087540949.jpg" height="300" width="400" /></a></div>
<br />
This was the original OpenMV cam in the photo, we only made about 20 units of these, the biggest issue was Windows support, which had me recently sit down and rewrite the whole debugging interface to use CDC and, sadly, ditch libusb all together (it's a shame because I enjoy coding with libusb) I might document this issue here one day.<br />
<br />
<i>Hint: plan and *test* cross-platform support as early as possible, before anything else, if you want that eventually (in my defense I didn't want to support Windows at all when I started)</i><br />
<br />
20 cameras were sold on Tindie, and we had more than 100 backorders, at this point, we decided to move forward and seriously consider mass production (by "mass" I was thinking 500-1000 units)<br />
<br />
<b>Production</b><br />
Making a product is no picnic, everyone knows that, you have to consider many factors when doing more than a few prototypes, from parts sourcing, programming and testing to order fulfillment and support, then there's always some product-specific issues that might catch you off guard, something as simple as focusing the lens!<br />
<br />
At this point small costs start to creep in and If you're not careful enough or don't know what you're doing,
something is bound to go wrong, and you might end up loosing money
instead making profit.<br />
<br />
One option is to outsource the whole thing to someone, and that's exactly what we did to minimize risks as much as we could, we've been in contact with <a href="http://macrofab.net/">MacroFab</a> and decided to go with them, they'll be taking care of everything, I have to say I'm still impressed with the idea of a whole production backend as a service :)<br />
<br />
On my end of things, other than working on the software, I went through a few designs trying to find that perfect balance
between features, cost and "manufacturbility".<br />
<br />
Some of the things that I've encountered may (or may not) surprise you, I found out that a cheaper connector or sensor might end up costing a lot more to assemble and test, so unless you plan on assembling 1000s of something yourself, think very carefully which parts you want to use, and consider the costs of assembling and testing those parts.<br />
<br />
I finally settled on the
latest hardware seen on the Kickstarter and then designed a small programming/testing jig, which I'll keep working on and improve further, if needed, in the following days. <br />
<br />
<i><i>Hint</i>: </i><i>think very carefully which parts you want to use, and consider the costs of assembling and testing those parts.</i><br />
<i><br /></i>
<b>Kickstarter</b><br />
This brings us to funding and the Kickstarter, although we've been planning this for a while but it obviously was not enough, I think we did great and all (900 backers/208% funded) but we could have done much better (with some more planning and time) but that's okay for a start :) <br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhL0rr2g4pHVURO0U7-l2jvUFo-kTPrIHBathEvPaMtMurC08okoRtAWi9a1Jh4d_3gFXu_w3byFsoDpREb9Pcch8DilznAtS76-WpY_lEnamj6dexIZIMjLZCcFbi2HdhcdvEMKGvQ5Xs/s1600/Untitled.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhL0rr2g4pHVURO0U7-l2jvUFo-kTPrIHBathEvPaMtMurC08okoRtAWi9a1Jh4d_3gFXu_w3byFsoDpREb9Pcch8DilznAtS76-WpY_lEnamj6dexIZIMjLZCcFbi2HdhcdvEMKGvQ5Xs/s1600/Untitled.png" height="245" width="400" /></a></div>
<br />
If I learned anything from this KS, is that one should plan on every little detail before starting, this the best advice I can give anyone who wants to do this, plan and then plan some more, this includes reward tiers, stretch goals, content, logos, even updates timing and <b>post-KS sales</b>! <br />
<br />
<i><i>Hint: Be prepared for</i> post-</i><i><i>KS</i> sales, have a website up and running, ready to receive back orders as soon as the KS ends (A lesson </i><i><i>painfully </i>learned as we still can't accept backorders yet :( ) </i><br />
<br />
<b>THP 2015</b><br />
Moving on to THP 2015, which just launched a few days ago, I've been eager to participate this year too, if for no other reason than the excitement of it :) sadly, I'm not sure I'll have the time this year and so far I don't have any worthy ideas (well maybe I have one or two<i> </i>tucked away<span class="st"><i></i></span> ;))<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjG9hgrIE10-zNKxTmUEQSGpARvhsy0XzL6_a2xv8XLSKLSgpuaMlBDDK8oO1RzNUna5RbWgwUHcJ46_n1yNmhLUdLVTx9FQadzptzismu9RInbq5ZeX3Q6SQEvkmuvZc8L5kHs5s3vQgM/s1600/had-banner-prize-full.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjG9hgrIE10-zNKxTmUEQSGpARvhsy0XzL6_a2xv8XLSKLSgpuaMlBDDK8oO1RzNUna5RbWgwUHcJ46_n1yNmhLUdLVTx9FQadzptzismu9RInbq5ZeX3Q6SQEvkmuvZc8L5kHs5s3vQgM/s1600/had-banner-prize-full.jpg" height="215" width="400" /></a></div>
<br />
This year's theme is about solving important world problems, some folks like this theme, personally I believe the world is doomed and I can hardly solve my own problems :) but I am still interested, also there's something new this year "The Best Product Prize" a grant of sorts to bring your product to the market, which sounds great.<br />
<br />
If you have an idea go ahead and sign up, you do have a chance (not to save the world of course) but you'll get exposure for your project and maybe you'll win some cash too ;)</div>
iabdalkaderhttp://www.blogger.com/profile/07526150314777847403noreply@blogger.com8tag:blogger.com,1999:blog-7822883683244244182.post-64416588155940686862014-07-09T01:47:00.001+02:002014-07-09T01:47:14.640+02:00Using the STM32 DCMI with JPEG Sensors<div dir="ltr" style="text-align: left;" trbidi="on">
If you've been looking for this, chances are you saw Frank's <a href="http://blog.frankvh.com/2011/08/19/stm32f2xx-digital-camera-interface-dcmi/">post</a> on the subject, while it contains very useful information and he mentions reading JPEG, he didn't explain his approach in details, so here's my soultion.<br />
<br />
First, let me reiterate the issue with JPEG and the STM32, as you already know JPEG images are compressed, so you don't know the exact image size beforehand, you expect to read it after a complete transfer<i>, however, </i>the STM32 DMA data count register (NDTR) counts down, and therein lies the problem, the counter reaches zero after a complete transfer (or gets reloaded in case of a circular mode) either way, you can't find the transfer size after a DMA transfer is complete.<br />
<br />
So here's my solution to this problem, first set the DMA stream to transfer the maximum frame size you expect or the absolute max for a DMA transfer (2^16 bits), afterwards, start the DCMI, it will generate a FRAME_IT when a whole frame has been read (VSYNC is asserted high/low depending on the polarity) however, the DMA will never stop, so at this point you should <b>abort the DMA transfer</b>, this will leave the remainder of the transfer size you requested earlier in the NDTR register (it's guaranteed to be there because the transfer was interrupted) now subtract that from the initial transfer size and you have the frame size.<br />
<br />
Here's an example code, which uses the STM32Cube (HAL):<br />
<br />
<pre class="brush:cpp">uint32_t addr;
uint16_t length;
addr = (uint32_t) image->pixels;
length = MAX_XFER_SIZE;
/* Start the DCMI */
HAL_DCMI_Start_DMA(&DCMIHandle,
DCMI_MODE_SNAPSHOT, addr, length);
/* Wait for frame */
while ((DCMI->CR & DCMI_CR_CAPTURE) != 0) {
}
/* The frame is finished, but DMA still waiting
for data because we set max frame size
so we need to abort the DMA transfer here */
HAL_DMA_Abort(&DMAHandle);
/* Read the number of data items transferred */
image->size = (MAX_XFER_SIZE - DMAHandle.Instance->NDTR)*4;
</pre>
One issue remains, what if it overflows ? well that would mean you're really cutting it close, but anyway (I haven't tested this) but you should be able read the overflow flag in the DCMI port, or check the JPEG markers.
</div>
muxhttp://www.blogger.com/profile/07901500843676691342noreply@blogger.com5tag:blogger.com,1999:blog-7822883683244244182.post-37830938249172610912014-06-03T00:17:00.000+03:002014-06-03T00:17:05.933+03:00OV9650 Breakout<div dir="ltr" style="text-align: left;" trbidi="on">
<div style="text-align: justify;">
I made this breakout for the OV9650 a while ago, and I've been waiting to test it before sharing, I finally had the chance to do so, I used an FPGA this time for testing, and here's the result:</div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhl38KqJCHT1spbZdHb3tyR66NjJ7erN5vg2RMa3aMfn7fwRcVVd0vXUt3-LnGs3kzNnMMsspTsOZXR4KCVmpX-oMooO7HdJ5EkGQnLPzISpF0B8rbfqjdp5_VMS8qUgJ__ID0Yg1otIWs/s1600/DSC03733.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhl38KqJCHT1spbZdHb3tyR66NjJ7erN5vg2RMa3aMfn7fwRcVVd0vXUt3-LnGs3kzNnMMsspTsOZXR4KCVmpX-oMooO7HdJ5EkGQnLPzISpF0B8rbfqjdp5_VMS8qUgJ__ID0Yg1otIWs/s1600/DSC03733.JPG" height="300" width="400" /></a></div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div style="text-align: justify;">
The breakout has two SOT23 LDOs for the sensor's core, digital and analog supplies and requires a single external 3.3v supply, note that most sensors have internal regulators for the core supply, so technically you only need one, anyway, those LDOs should be fairly easy to source, their exact voltages depend on the sensor used. The board is compatible with a few other Omnivision sensors, such as the OV9655, OV7660, OV2640 etc... however, make sure it has the same pinout...</div>
<div style="text-align: justify;">
<br /></div>
Here's the breakout and Eagle library:<br />
<a href="https://github.com/iabdalkader/OV965x">https://github.com/iabdalkader/OV965x</a><br />
<br />
Alternatively, you could order the PCB directly from OSHPark:<br />
<a href="http://oshpark.com/shared_projects/FQwlpPpi">http://oshpark.com/shared_projects/FQwlpPpi</a></div>
muxhttp://www.blogger.com/profile/07901500843676691342noreply@blogger.com2tag:blogger.com,1999:blog-7822883683244244182.post-26471137296587227982014-04-26T22:16:00.003+02:002014-04-26T22:16:41.288+02:00Running ZPU Softcore on Lattice ICE40<div dir="ltr" style="text-align: left;" trbidi="on">
So I got my hands on a new FPGA development board, a Lattice ICE40HX8K eval kit, this is a really basic low-cost board/breakout with a few LEDS, EEPROM and a dual FTDI2232H UART/FIFO, that you can use for programming the EEPROM/FPGA...What I really love about this board, other than the low cost and many I/Os, is that the second FTDI port is configured as a serial port and connected to the FPGA, so basically you get a free USB<->USART bridge which you can use to talk to the FPGA with the same USB cable used for programming (see Linux notes) that's basically all I need as I'm already familiar with FPGAs...<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhajxbFHRkHjx3H3G3xHSHg8H9QHL-5BHlvMT7bRQTySxZ0r-qDN7644vBjb9TB4zmruQgbWoG58xJsXy8wh0qPe8TGA0RMqXNgpUrTZWtzdvNNG9fXOt68aATLiO90919nDz0UzIYw7Qw/s1600/ICE40HX8K-B-EVN.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhajxbFHRkHjx3H3G3xHSHg8H9QHL-5BHlvMT7bRQTySxZ0r-qDN7644vBjb9TB4zmruQgbWoG58xJsXy8wh0qPe8TGA0RMqXNgpUrTZWtzdvNNG9fXOt68aATLiO90919nDz0UzIYw7Qw/s1600/ICE40HX8K-B-EVN.jpg" height="391" width="400" /></a></div>
I wanted to evaluate those FPGAs for a new project I'm working on, which will most likely require a minimal SoC with a wishbone bus... My first thoughts was to use my<a href="http://sigalrm.blogspot.com/2012/05/mips1-isa-implementation.html" target="_blank"> uMIPS core</a>, but it doesn't support the wishbone bus (I might fix that later) so I decided to give the <a href="http://opensource.zylin.com/zpu.htm" target="_blank">ZPU</a> core a shot, which was definitely worth the time it took to get it working on the Lattice FPGA.<br />
<br />
In an effort to save someone else's time, I created this github <a href="https://github.com/iabdalkader/zpu-lattice" target="_blank">repo</a> for the project<b>,</b> it has the sw, hdl, project files and a tested bitmap file, all you need to do is to program the bitmap (or synthesis the project with iCEcube2 if you want), open /dev/ttyUSB1, set it to 8N1, 9600, parity=none and reset the core (you will need and external switch for that, connect it between H16 and GND), it should print out "Hello World!"...<br />
<br />
<b>ZPU Core:</b><br />
The <a href="http://opensource.zylin.com/zpu.htm" target="_blank">ZPU</a> is small 32-bit stack-based CPU, it comes with a gcc-toolchain, lots of variants and examples... For this project I used the zealot/medium variant which comes with a physical I/O layer (provides a USART, GPIO and a timer) and I'm using a single port RAM, no PLLs (to keep things simple) and all the RAM blocks on the ICE40HX8K (16KBs total) for the program image. There's no wishbone yet, I will work on that next.<br />
<br />
<b>Compiling Stuff:</b><br />
First It's worth mentioning here that I modified the I/O memory map (<b>crt_io.c</b>) since there's only 16KBytes of on-chip ram, I modified it to use bit 15 for the I/O space, the modified crt_io.c is included in the repo and the Makefile will compile and link this modified map for you.<br />
<br />
If you want to compile a new program, you'll need to download the ZPU <a href="http://opensource.zylin.com/zpudownload.html" target="_blank">toolchain</a> first and use the Makefile in zpu/sw it will generate a bunch of files, the one we're interested in is<b> hello.bram</b>, this contains the instructions/data used to initialize the embedded RAM, copy the contents of this file and replace the one in bram.vhdl.<br />
<br />
<b>Linux notes:</b><br />
I didn't have much trouble getting the software running on Linux, but one thing you might want to do to make things nicer, is to use this udev rule to unbind ftdio-sio from the first FTDI port when the board is connected, this will allow the programmer to use the first port as JTAG with the second (USART) port bound to ftdi-sio at the same time, so you can use it as to talk to the FPGA after programming:<br />
<br />
<pre class="brush:bash">BUS=="usb",ACTION=="add",SYSFS{idVendor}=="0403",SYSFS{idProduct}=="6010",MODE=="0660"
,GROUP=="plugdev",SYMLINK+="ftdi-0"
SUBSYSTEM=="usb",DRIVER=="ftdi_sio",ATTRS{idVendor}=="0403",SYSFS{idProduct}=="6010"
,ATTR{bInterfaceNumber}=="00",RUN+="/bin/sh -c 'echo `basename %p` >/sys/bus/usb/drivers/ftdi_sio/unbind'"
</pre>
<br />
The following is the iCEcube report for this design:<br />
<br />
<pre class="brush:plain">Total Logic Cells: 3099/7680
Combinational Logic Cells: 2471 out of 7680 32.1745%
Sequential Logic Cells: 628 out of 7680 8.17708%
Logic Tiles: 473 out of 960 49.2708%
Registers:
Logic Registers: 628 out of 7680 8.17708%
IO Registers: 0 out of 1280 0
Block RAMs: 32 out of 32 100%
Pins:
Input Pins: 3 out of 206 1.45631%
Output Pins: 9 out of 206 4.36893%
InOut Pins: 0 out of 206 0%
Global Buffers: 6 out of 8 75%
PLLs: 0 out of 2 0%<!--EndFragment-->
</pre>
<br /></div>
muxhttp://www.blogger.com/profile/07901500843676691342noreply@blogger.com1tag:blogger.com,1999:blog-7822883683244244182.post-61127661751217906062014-02-08T22:06:00.000+02:002014-02-08T22:06:10.379+02:00OpenMV Update: MicroPython, More I/O, uSD and Lots of Other Things!<div dir="ltr" style="text-align: left;" trbidi="on">
Time for another update, sorry this took me so long, I've been very busy working on OpenMV, the good news is I have lots of new features implemented! There's a new (smaller :D) hardware revision with more I/O (USART/I2C and SPI) and a uSD socket, MicroPython support, an IDE for the camera, and for those of you who have been wondering, I'm working with Michael Shimniok from <a href="http://www.bot-thoughts.com/" target="_blank">Bot-Thoughts</a> on doing a Kickstarter campaign for OpenMV, soon, hopefully, you will be able to get one for a very reasonable price :) so stay tuned!<br />
<br />
Okay, so on the software side, you've probably heard of the <a href="http://www.micropython.org/" target="_blank">MicroPython</a> project, if not make sure to check it out, basically MicroPython is very efficient, lightweight Python VM for microcontrollers, the plan was to script the camera with Lua/eLua but MP has some really neat features already implemented, so long story short, I've decided to script the camera with MP... after lots of work, I managed to get MP running on OpenMV, and wrote some MP bindings to export the subsystems of OpenMV to Python, eventually it will be completely controlled with Python.<br />
<br />
So how this works so far, basically, on reset OpenMV runs a default Python script with the old serial camera interface (receive commands from the serial port, process and return result) but it also shows up as a small USB storage device where you can copy your own Python script(s), reset and it runs that instead of the default script.. In addition to that, you can also "talk" to the camera directly using a Python shell over the com port while watching the framebuffer in realtime :)<br />
<br />
I've also combined all those nice features into a single "IDE" for convenience, written with Python, PyGTK and PyUSB. The IDE has a Python shell, a framebuffer viewer, and it can run scripts or save them to flash:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgJPFGJ5rDmFgr0gjSq-TEDZPU2CTSd8BKfYDkxCuuLdnrSIoN6wg1D8FGDJEYd3AR86GyrafZv-wWH6kJS7Jc-DsbMjN9G25-hkrZqpgQAzsr0LIGDzz0MIS89Nqop_8qWxcUgRmfu8ck/s1600/S247.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgJPFGJ5rDmFgr0gjSq-TEDZPU2CTSd8BKfYDkxCuuLdnrSIoN6wg1D8FGDJEYd3AR86GyrafZv-wWH6kJS7Jc-DsbMjN9G25-hkrZqpgQAzsr0LIGDzz0MIS89Nqop_8qWxcUgRmfu8ck/s1600/S247.png" height="315" width="400" /></a></div>
<br />
Moving on to the hardware, the new revision is 1.0x1.30 inches, it has a tiny uSD socket (which will be available to Python user code) USART, SPI and I2C broken out on the main 2.54mm header and a separate 2mm SWD debugging header.. There's also a switch, which will be used for boot or reset.<br />
Here are some pics of the 3rd (2nd?) revision:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg5MU0XKOZddyDYX_EFwy1d9mbpQModV9z9yxjlWkOXC9qFuNAO1Vsy1y94I8AXDra8nv5kHlLSQ2t3tVnGM_AEH6UhZhyphenhyphenYKffPjcTgX0vTrsRKJOv5YxfC94gPMWBRV6LQbSjT0xwI5Jw/s1600/DSC03686.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg5MU0XKOZddyDYX_EFwy1d9mbpQModV9z9yxjlWkOXC9qFuNAO1Vsy1y94I8AXDra8nv5kHlLSQ2t3tVnGM_AEH6UhZhyphenhyphenYKffPjcTgX0vTrsRKJOv5YxfC94gPMWBRV6LQbSjT0xwI5Jw/s1600/DSC03686.JPG" height="300" width="400" /></a></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi8ycDpGMw7nod0MfTnxX6kr3nLDkWoybjFHMDg2vbS2KzJVbELF73FbgAJcmQcA6hOFWv3IMRnFMaKzdyYrr9-Cjf_WkUgN4a8RqRd0XXUWFifxls6DV4Zi4afQTMKMRP8L9DXfryI0ck/s1600/DSC03694.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi8ycDpGMw7nod0MfTnxX6kr3nLDkWoybjFHMDg2vbS2KzJVbELF73FbgAJcmQcA6hOFWv3IMRnFMaKzdyYrr9-Cjf_WkUgN4a8RqRd0XXUWFifxls6DV4Zi4afQTMKMRP8L9DXfryI0ck/s1600/DSC03694.JPG" height="300" width="400" /></a></div>
<br />
Compared to the old one:<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh-zVdhwnmY37XBzYRru-fJTGdMlyFmpCPniiQGzj0IwZhvxV9IfU8Y5bmRgG7rhx3y5QlQTFplcr6OSRRAj3x92mKACANEiYzDv1IrNDHVjtQontqbZjjHhnXQI9j8Vcyu_lQIDoER77E/s1600/DSC03692.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh-zVdhwnmY37XBzYRru-fJTGdMlyFmpCPniiQGzj0IwZhvxV9IfU8Y5bmRgG7rhx3y5QlQTFplcr6OSRRAj3x92mKACANEiYzDv1IrNDHVjtQontqbZjjHhnXQI9j8Vcyu_lQIDoER77E/s1600/DSC03692.JPG" height="300" width="400" /></a></div>
<br />
<br />
That's it for now, please let me know if you have any comments :) thanks!</div>
muxhttp://www.blogger.com/profile/07901500843676691342noreply@blogger.com18tag:blogger.com,1999:blog-7822883683244244182.post-27074514905657169122014-01-18T18:50:00.002+02:002014-01-18T18:59:51.670+02:00Overclocking the STM32F4<div dir="ltr" style="text-align: left;" trbidi="on">
<div style="text-align: justify;">
I've been doing some tests with the STM32F407 to see how fast it can go, STMicro has released an almost identical one that runs at 180MHz, is it a marketing thing ? will they release a 200MHz version in a few months? who cares, anyway, I was able to run the STM32F407 at 240MHz without any "obvious" problems, in addition to overclocking, the code listed below lets you set some different frequencies, which could be useful for frequency scaling.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
On the STM32F4 the clocks are controlled via the RCC (Reset and Clock Control) block, it's easy enough to change the frequency, the tricky part however, is understanding all the different dividers and getting them right. According to the datasheet, the following are the maximum clock frequencies for the core and peripheral buses:</div>
<pre class="brush:plain">SYSCLK: 168MHz
PLLC48: 48MHz (feeds the USB OTG FS and RNG)
APB1 clock: 42MHz
APB2 clock: 84MHz
</pre>
<div style="text-align: justify;">
Based on that, I used multiples of 42MHz to get the maximum possible frequencies for the peripheral buses (APB1 and APB2) for frequencies lower than 168MHz (this doesn't always result in the maximum USB frequency, which is required to get the full 12Mbps), for frequencies higher than 168MHz, I used 200MHz and 240MHz mainly because they are convenient to my application, you might want to use different frequencies based on yours:</div>
<pre class="brush:c">enum sysclk_freq {
SYSCLK_42_MHZ=0,
SYSCLK_84_MHZ,
SYSCLK_168_MHZ,
SYSCLK_200_MHZ,
SYSCLK_240_MHZ,
};
void rcc_set_frequency(enum sysclk_freq freq)
{
int freqs[] = {42, 84, 168, 200, 240};
/* USB freqs: 42MHz, 42Mhz, 48MHz, 50MHz, 48MHz */
int pll_div[] = {2, 4, 7, 10, 10};
/* PLL_VCO = (HSE_VALUE / PLL_M) * PLL_N */
/* SYSCLK = PLL_VCO / PLL_P */
/* USB OTG FS, SDIO and RNG Clock = PLL_VCO / PLLQ */
uint32_t PLL_P = 2;
uint32_t PLL_N = freqs[freq] * 2;
uint32_t PLL_M = (HSE_VALUE/1000000);
uint32_t PLL_Q = pll_div[freq];
RCC_DeInit();
/* Enable HSE osscilator */
RCC_HSEConfig(RCC_HSE_ON);
if (RCC_WaitForHSEStartUp() == ERROR) {
return;
}
/* Configure PLL clock M, N, P, and Q dividers */
RCC_PLLConfig(RCC_PLLSource_HSE, PLL_M, PLL_N, PLL_P, PLL_Q);
/* Enable PLL clock */
RCC_PLLCmd(ENABLE);
/* Wait until PLL clock is stable */
while ((RCC->CR & RCC_CR_PLLRDY) == 0);
/* Set PLL_CLK as system clock source SYSCLK */
RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);
/* Set AHB clock divider */
RCC_HCLKConfig(RCC_SYSCLK_Div1);
/* Set APBx clock dividers */
switch (freq) {
/* Max freq APB1: 42MHz APB2: 84MHz */
case SYSCLK_42_MHZ:
RCC_PCLK1Config(RCC_HCLK_Div1); /* 42MHz */
RCC_PCLK2Config(RCC_HCLK_Div1); /* 42MHz */
break;
case SYSCLK_84_MHZ:
RCC_PCLK1Config(RCC_HCLK_Div2); /* 42MHz */
RCC_PCLK2Config(RCC_HCLK_Div1); /* 84MHz */
break;
case SYSCLK_168_MHZ:
RCC_PCLK1Config(RCC_HCLK_Div4); /* 42MHz */
RCC_PCLK2Config(RCC_HCLK_Div2); /* 84MHz */
break;
case SYSCLK_200_MHZ:
RCC_PCLK1Config(RCC_HCLK_Div4); /* 50MHz */
RCC_PCLK2Config(RCC_HCLK_Div2); /* 100MHz */
break;
case SYSCLK_240_MHZ:
RCC_PCLK1Config(RCC_HCLK_Div4); /* 60MHz */
RCC_PCLK2Config(RCC_HCLK_Div2); /* 120MHz */
break;
}
/* Update SystemCoreClock variable */
SystemCoreClockUpdate();
}
</pre>
<br />
Note: after calling this function, you will probably need to re-enable all the clocks ...<br />
<br />
<b>Note on Overclocking:</b><br />
<div style="text-align: justify;">
There's no telling if overclocking will always work, it might fail at some temperature, critical path or just randomly, but it is nice to know that you have the option to run (burn?) the micro at higher speeds if needed... One thing I can confirm though, is that it doesn't overheat too much, obviously touching the micro with your finger tip is not an accurate way to determine that, so I took this a step further and made a series of tests using the internal core temperature sensor.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
I ran the micro at different frequencies while collecting samples from the internal temperature sensor, which is connected to one of the ADC's channels, for each frequency I collected a number of samples and then I plotted the average vs the frequencies and here's the result:</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhF9rKyI9OoaPRTjWWkQ81hyEhroGbtsl44py_raXOOdslJqUyDQhJ2MkezXzTSkadOa8m8jFnlIIZPIjgLNRjLqn34FzPUPQNIC44mtPPHC3BHyDuEkUk2Zf2h2YRCpA2iUhPZaYINz-o/s1600/Untitled.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhF9rKyI9OoaPRTjWWkQ81hyEhroGbtsl44py_raXOOdslJqUyDQhJ2MkezXzTSkadOa8m8jFnlIIZPIjgLNRjLqn34FzPUPQNIC44mtPPHC3BHyDuEkUk2Zf2h2YRCpA2iUhPZaYINz-o/s1600/Untitled.png" height="240" width="400" /></a></div>
<div style="text-align: justify;">
One important thing to note here, the internal temperature sensor readings varies from chip to chip up to 45 degrees, which means those are <b>NOT absolute temperature values</b> but should only be used to detect temperature variations. Now, the conclusion, it looks like overclocking the STM32F4 from 168MHz to 240MHz increases the core temperature by ~4 degrees.</div>
</div>
muxhttp://www.blogger.com/profile/07901500843676691342noreply@blogger.com6tag:blogger.com,1999:blog-7822883683244244182.post-73105128766235433102013-12-05T06:20:00.002+02:002013-12-06T03:05:19.621+02:00OpenMV Update: 25FPS Face Detection, USB Support and More<div dir="ltr" style="text-align: left;" trbidi="on">
<div class="separator" style="clear: both; text-align: center;">
</div>
So I've been working on OpenMV for the past week and this is what I have so far:<br />
<br />
<b>USB Support:</b><br />
<div style="text-align: justify;">
The camera now supports USB OTG full speed, I've also written a small userspace tool with libusb/SDL to interface with the camera and view the frame buffer, this makes it really easy to debug the image processing code, and it also lets you change the sensor's registers while watching the results in realtime.</div>
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEixLMOfDA2Q7wVRFUrZYqcOOiUh6DqzYFVKT-w7DlJLkq0UHHcXbO4kzOgohXLuFCGcH-GteYglhWzp3btqBrx9-UzSoa6VhTI6Kiv0sNOzmP4-rlL4iWOnKuBz0tABEoekDSUnijHCHiY/s1600/Untitled.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEixLMOfDA2Q7wVRFUrZYqcOOiUh6DqzYFVKT-w7DlJLkq0UHHcXbO4kzOgohXLuFCGcH-GteYglhWzp3btqBrx9-UzSoa6VhTI6Kiv0sNOzmP4-rlL4iWOnKuBz0tABEoekDSUnijHCHiY/s1600/Untitled.png" height="257" width="320" /></a></div>
<br />
I've mentioned building the STM32F4xx libraries in a previous <a href="http://sigalrm.blogspot.com/2013/11/stm32f4xx-libraries.html" target="_blank">post</a>, you can checkout the repo linked there if you want to build the libraries.<br />
<br />
<b>Face Detection:</b><br />
<div style="text-align: justify;">
Many were very interested in this feature, well I've managed to get the viola-jones face detector working on the camera, and it's working fine.. For those of you familiar with the detector, the haar cascade is exported as a C header which is linked to the binary and loaded into the <a href="http://sigalrm.blogspot.com/2013/12/using-ccm-memory-on-stm32.html" target="_blank">CCM</a> (Core Coupled Memory) a 64KB memory block connected directly to the core. Only one integral image is pre-computed and allocated on the heap, the other one, the squared integral image, which is used for computing the standard deviation, can't fit into memory for the QQVGA resoultion, and so, instead, the standard deviation is computed on the fly for every detection scale using some SIMD instructions to speed it up a bit.</div>
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhht4EMA6bBmYitRp-CAuQ7JgMC5MSajT-fMgiM7a3rmPazW7AkrddpGJak-o0QLngrfdy7uYlUdfuTsTum33jTjng0TGkJtWCrw5w1lAWbwFz5qPWHpvJeURD0MNLZhv1eDUTPz6outBg/s1600/so240.jpeg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhht4EMA6bBmYitRp-CAuQ7JgMC5MSajT-fMgiM7a3rmPazW7AkrddpGJak-o0QLngrfdy7uYlUdfuTsTum33jTjng0TGkJtWCrw5w1lAWbwFz5qPWHpvJeURD0MNLZhv1eDUTPz6outBg/s1600/so240.jpeg" height="186" width="200" /></a></div>
<br />
The memory can hold up to 23 stages, however, using only 12 stages and with a relatively large scale step, the detector is working great, with occasional false detections of course, more stages can be used if greater accuracy is required, but not without some performance penalty...As for the numbers, the camera can process 7-8FPS QQVGA, and for <b>QQCIF (88x72) I get </b><b>25FPS</b><b>! </b><br />
<b><br /></b>
Here's a video of the face detector in action running at <b>25FPS</b>:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<iframe allowfullscreen='allowfullscreen' webkitallowfullscreen='webkitallowfullscreen' mozallowfullscreen='mozallowfullscreen' width='320' height='266' src='https://www.youtube.com/embed/SdQF5JI4kzU?feature=player_embedded' frameborder='0'></iframe></div>
<br />
Here's another video of color tracking running at <b>30FPS</b>:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<iframe allowfullscreen='allowfullscreen' webkitallowfullscreen='webkitallowfullscreen' mozallowfullscreen='mozallowfullscreen' width='320' height='266' src='https://www.youtube.com/embed/T-oMfnEsa1o?feature=player_embedded' frameborder='0'></iframe></div>
<br />
<b>Other Updates:</b><br />
I've been doing some general fixes here and there, mainly to improve the image quality, in addition to that, I've compiled all the libraries and code with optimizations (-O2) and I've seen great improvements in speed, there's also a new pixel format, grayscale, which is basically just the Y channel extracted from the YUV422 to avoid doing that every time a grayscale image is required.<br />
<br />
The QCIF/QQCIF are working now (the sensor can output <b>60FPS</b> when using QQCIF ) and through some other register probing, I've removed a few useless registers and discovered that the sensor has<b> digital zoom</b>, cool!<br />
<br />
There's also simple motion detection code in progress, it's based on frame differencing and using the first frame as the background, more work will be done here as soon as I get around to it. And I will probably try template matching next.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgOdyjHIx73X3uYWBOKT6iNY8eZGVbdqp-5vpZEjjTWS4-3RQf5a1T7PZYuxN6IzxzYQzS1s6-H0UY0pbG6NGE4MoXWnRgSjKruCgyb2xV3KjJhbeDqD0uVVypyGkgsE1pXVZGXWPDeoAw/s1600/openmv.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgOdyjHIx73X3uYWBOKT6iNY8eZGVbdqp-5vpZEjjTWS4-3RQf5a1T7PZYuxN6IzxzYQzS1s6-H0UY0pbG6NGE4MoXWnRgSjKruCgyb2xV3KjJhbeDqD0uVVypyGkgsE1pXVZGXWPDeoAw/s1600/openmv.png" height="320" width="230" /></a></div>
<br />
I've also just finished<b> a new hardware revision</b>, it has a tiny <b>uSD socket</b>, which I imagine can be used for anything from storing haar cascades, snapshots or video to buffering larger frames, the new revision is also a bit smaller. </div>
muxhttp://www.blogger.com/profile/07901500843676691342noreply@blogger.com21tag:blogger.com,1999:blog-7822883683244244182.post-89312683107738562672013-12-02T11:10:00.002+02:002013-12-02T11:11:06.729+02:00Using The CCM Memory on the STM32<div dir="ltr" style="text-align: left;" trbidi="on">
<div style="text-align: justify;">
The STM32 series have non-contiguous memories divided into blocks, for example the STM32F4, has 2 (contiguous) blocks of SRAM connected to the bus matrix with different interconnects, and a Core Coupled Memory (CCM) block which is connected directly to the core.</div>
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgsbvANy_RxQlsqc6p81HLVKHM2iN8BIlsHu17HBP19t7Uj0H45ObaV-Rl8xh4N9xpTErvvxDR8TfsmKlyavDdX5vJynCOBkp_ErWDVbmEttO9S3ffFOtUf_92Ot9zmsGmVlYnd4JrkD3I/s1600/stm32f4+ccm.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgsbvANy_RxQlsqc6p81HLVKHM2iN8BIlsHu17HBP19t7Uj0H45ObaV-Rl8xh4N9xpTErvvxDR8TfsmKlyavDdX5vJynCOBkp_ErWDVbmEttO9S3ffFOtUf_92Ot9zmsGmVlYnd4JrkD3I/s1600/stm32f4+ccm.png" height="256" width="400" /></a></div>
<br />
<div style="text-align: justify;">
This tight coupling of the CCM memory to the core, leads to zero wait states, in other words, the core has exclusive access to this memory block, so for example, while other bus masters are using the main SRAM the core can access the CCM. T<span style="text-align: left;">herefore, the CCM block is commonly used for the stack and other critical OS data, this partitioning, allows the core to continue executing code while for example, a DMA transfer takes </span><span style="text-align: left;">place.</span><span style="text-align: left;"> However, the CCM could also be used as an extra memory block, doing so is easy, and there are a few examples out there that show how, simply defining a section in the linker script will do:</span></div>
<pre class="brush:cpp">.ccm : {
. = ALIGN(4);
_sccm = .;
*(.ccm)
. = ALIGN(4);
_eccm = .;
}>CCM
</pre>
<br />
And a section attribute is used to allocate memory into that section :<br />
<pre class="brush:cpp">const int8_t my_array[13] __attribute__ ((section (".ccm")))= {....};
</pre>
<br />
<div style="text-align: justify;">
However, what if you want to load initialized data into that section ? some look-up tables for example? using that section is not enough, see, the linker script makes the distinction between the Load Memory Address (LMA) where data is stored initially, and the Virtual Memory Address (VMA) where the data should be loaded at runtime, if the LMA is not specified explicitly, it becomes the same as VMA.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
You can see here that GDB loads the .ccm data into the CCM block (LMA=VMA=0x10000000) directly, while all other sections are loaded into the flash region (0x8xxxxxx):</div>
<br />
<pre class="brush:plain">Loading section .ccm, size 0x4ebc lma <b>0x10000000</b>
Loading section .isr_vector, size 0x188 lma 0x8000000
Loading section .text, size 0x9744 lma 0x8000188
Loading section .ARM, size 0x8 lma 0x80098cc
Loading section .init_array, size 0x8 lma 0x80098d4
Loading section .fini_array, size 0x4 lma 0x80098dc
Loading section .data, size 0xa30 lma 0x80098e0
Loading section .jcr, size 0x4 lma 0x800a310
</pre>
<br />
<div style="text-align: justify;">
While this may sound right, it's not, if GDB loads the .ccm section is loaded into SRAM directly, it will disappear after a power cycle! So instead, we want the LMA to be somewhere in the FLASH region (0x8xxxxxxx) and the VMA to be (0x10000000)<span style="text-align: left;">:</span></div>
<pre class="brush:cpp">_eidata = (_sidata + SIZEOF(.data) + SIZEOF(.jcr));
.ccm : AT ( _sidata + SIZEOF(.data) + SIZEOF(.jcr))
{
. = ALIGN(4);
_sccm = .;
*(.ccm)
. = ALIGN(4);
_eccm = .;
}>CCM
</pre>
<div>
<br />
<div style="text-align: justify;">
Note the .jcr is included in by some startup code for something related to Java, without adding the SIZEOF(.jcr) the .ccm will overlap that section, also note the _eidata symbol which will be referenced later in code. Now, when you try to load the elf, GDB prints:</div>
<br /></div>
<pre class="brush:cpp">Loading section .isr_vector, size 0x188 lma 0x8000000
Loading section .text, size 0x9794 lma 0x8000188
Loading section .ARM, size 0x8 lma 0x800991c
Loading section .init_array, size 0x8 lma 0x8009924
Loading section .fini_array, size 0x4 lma 0x800992c
Loading section .data, size 0xa30 lma 0x8009930
Loading section .jcr, size 0x4 lma 0x800a360
Loading section .ccm, size 0x4ebc lma <b>0x800a364</b>
</pre>
<br />
<div>
<div style="text-align: justify;">
Great, now the .ccm data is loaded into the FLASH region, we just need something to load it from FLASH to CCM in runtime, if you look at the startup code, there's an assembly function that copies initialized data from the flash to where it should be loaded in SRAM (the VMA), you need to do the same for the .ccm data, by either modifying the startup code, or perferrably, copying the data with a C function, so here it is:</div>
<pre class="brush:cpp">void load_ccm_section () __attribute__ ((section (".init")));
void load_ccm_section (){
extern char _eidata, _sccm, _eccm;
char *src = &_eidata;
char *dst = &_sccm;
while (dst < &_eccm) {
*dst++ = *src++;
}
}
</pre>
Note that the function is placed into the .init section so it executes before main. Now in runtime, this function will load the data from FLASH into SRAM using the pointer defined in the linker script.</div>
</div>
muxhttp://www.blogger.com/profile/07901500843676691342noreply@blogger.com15tag:blogger.com,1999:blog-7822883683244244182.post-42800468551176779412013-11-28T14:17:00.002+02:002013-11-28T14:24:03.754+02:00STM32F4xx Libraries<div dir="ltr" style="text-align: left;" trbidi="on">
<div class="separator" style="clear: both; text-align: left;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjcihaGYJaYVjVLHbR2S2VFY3uQLZlcNgjF7EdQafZ8Xcuv1tfr1zsYKCSXezPHr8H9s-BtTYYHzlDoIGpiQkxJ7PgknpzqZcjBH5CR5GIiRCVrb7bMObJ8HOWBBSWzwfdUY064LbPziRY/s1600/STM32+F4+Series.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjcihaGYJaYVjVLHbR2S2VFY3uQLZlcNgjF7EdQafZ8Xcuv1tfr1zsYKCSXezPHr8H9s-BtTYYHzlDoIGpiQkxJ7PgknpzqZcjBH5CR5GIiRCVrb7bMObJ8HOWBBSWzwfdUY064LbPziRY/s1600/STM32+F4+Series.jpg" height="193" width="200" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<br />
<div style="text-align: justify;">
I wrote a <a href="http://sigalrm.blogspot.com/2012/09/stm32f4-discovery-quick-start-guide.html" target="_blank">tutorial</a> before on how to setup a toolchain and build the <b>STM32F4xx</b> standard peripheral drivers into one convenient library, since then, a few people have asked me about the library, so to make life easier, I downloaded the latest StdPeriph/CMSIS, in addition to a few other libraries that I might need later, and shared everything in one repository, which currently has the following libraries:<br />
<div style="text-align: left;">
<pre class="brush:plain">Cortex-M CMSIS V3.20
STM32F4xx CMSIS V1.3.0
STM32F4xx StdPeriph V1.3.0
STM32_USB_Device V1.1.0
STM32_USB_OTG V2.1.0
</pre>
</div>
</div>
<div style="text-align: justify;">
In addition to those, the repository also includes a simple USB device library (<b>stm32f4xx/USB_Generic</b>) which abstracts all the horrible details of the USB libraries into a very simple generic USB device implementation with just two Bulk endpoints...</div>
<br />
<div style="text-align: justify;">
To use this library you just pass a struct with two callback functions and the library will call those functions whenever data is received or requested, it's as simple as that, note that it's configured for OTG FS only, it could still be useful if you just want to get USB working and don't have time to go through all the examples.</div>
<br />
Finally, repository also includes some examples, a Blinky, a <b>USB_Generic </b>example and some user-space code with libusb.<br />
<br />
<b>Building The Libraries:</b><br />
<div style="text-align: justify;">
To build the libraries and examples just type make in the top directory, the top Makefile will pass along all the flags and variables, here are some options you can pass on the command line:</div>
<br />
<pre class="brush:bash">make DEBUG=0
</pre>
This will build everything with <b>-O2</b> and no debugging symbols (not recommended)<br />
<br />
<pre class="brush:bash">make DEBUG=1 CFLAGS="-DOSC=xx"
</pre>
<div style="text-align: justify;">
This will build the library with debugging enabled, no optimization and using the given crystal frequency in MHz (for example -DOSC=16)</div>
<div style="text-align: justify;">
<br /></div>
Repository:<br />
<pre class="brush:plain">https://github.com/iabdalkader/stm32f4xx.git</pre>
</div>
muxhttp://www.blogger.com/profile/07901500843676691342noreply@blogger.com4tag:blogger.com,1999:blog-7822883683244244182.post-19640779573525675682013-11-17T19:39:00.000+02:002013-11-18T05:05:08.027+02:00FT231X Breakout<div dir="ltr" style="text-align: left;" trbidi="on">
<div style="text-align: justify;">
This is a breakout board for FTDI's latest USB-to-Serial bridge, the FT231X. This one comes in a smaller package (SSOP20) and it's cheaper than its predecessor the FT232R/L, it also offers a charging detection feature, which I'm not really interested in, but anyway see this <a href="http://www.ba0sh1.com/ft230x-charger-detection-investigation/" target="_blank">post</a> for more details.</div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh5GH7Mk5k7fGSRaUFkrbPQp6lD55Cqi5X4UXzwrSHHfB0XqeP6ZOcUqmyo8MMOLi-sJ6noY1qLYI14-VVVzDHGjr4PymDvNr_mTgfnjTsRipnYyHtcacBjoXiyjCd-L1aplcfYbawzXig/s1600/DSC03658.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="257" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh5GH7Mk5k7fGSRaUFkrbPQp6lD55Cqi5X4UXzwrSHHfB0XqeP6ZOcUqmyo8MMOLi-sJ6noY1qLYI14-VVVzDHGjr4PymDvNr_mTgfnjTsRipnYyHtcacBjoXiyjCd-L1aplcfYbawzXig/s320/DSC03658.JPG" width="320" /></a></div>
<br />
<div style="text-align: justify;">
I've seen a couple of good breakout boards out there, but this one has a few advantages over the others, it has a solder jumper to switch VCCIO between 3.3V and 5.0V, a 500mA PTC fuse for over-current protection and it's pin compatible with the Arduino mini programming header.</div>
<br />
Repo:<br />
<pre class="brush:plain">https://github.com/iabdalkader/ft231x-breakout.git
</pre>
<br /></div>
muxhttp://www.blogger.com/profile/07901500843676691342noreply@blogger.com0tag:blogger.com,1999:blog-7822883683244244182.post-59333549374119661072013-11-10T16:22:00.002+02:002013-11-13T13:13:05.826+02:00Color Tracking With OpenMV<div dir="ltr" style="text-align: left;" trbidi="on"><div style="text-align: justify;">So I finally had some free time to work on OpenMV, for those of you who haven't been following this project, OpenMV is an open-source tiny machine vision module based on an STM32F4 ARM Cortex-M4 micro and an OV9650 sensor. I started this project mainly because I find the existing cameras are either too limited for their price or too expensive if they do some image processing, so one of my main goals was to make this as cheap as possible, the total cost of this module so far is around $20 for a single board, and could go as low as $15 for 500 pieces.</div><div class="separator" style="clear: both; text-align: center;"></div><div class="separator" style="clear: both; text-align: center;"></div><div style="text-align: justify;"><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiKZ2w1tkCAOzQ-UJy7S1p6wog9moihwPcSD5ZQNFwRW6JEzDL13nMBEOe9aMp51TcZzibMsh4Xi5GHbk5Fq-pL1hmyK5GSBIOdkQKgc4VPJKuPA5OiXDpr8lUUNUy0XILj7EYw5XAk5VU/s1600/DSC03632.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="240" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiKZ2w1tkCAOzQ-UJy7S1p6wog9moihwPcSD5ZQNFwRW6JEzDL13nMBEOe9aMp51TcZzibMsh4Xi5GHbk5Fq-pL1hmyK5GSBIOdkQKgc4VPJKuPA5OiXDpr8lUUNUy0XILj7EYw5XAk5VU/s320/DSC03632.JPG" width="320" /></a></div><br />
</div><div style="text-align: justify;">I wrote a simple color tracking algorithm for the camera, which I tested using an Arduino, the Arduino sends out a few commands via the serial port to the camera telling it to capture and process a frame, it then receives back the coordinates of the object and controls the servos accordingly. I was able to process around 15FPS, which is not bad given the current naive implementation. This is a video of the camera tracking a ball:<br />
<br />
</div><div class="separator" style="clear: both; text-align: center;"><object class="BLOGGER-youtube-video" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0" data-thumbnail-src="http://img.youtube.com/vi/63_mOyZeNng/0.jpg" height="266" width="320"><param name="movie" value="http://youtube.googleapis.com/v/63_mOyZeNng&source=uds" /><param name="bgcolor" value="#FFFFFF" /><param name="allowFullScreen" value="true" /><embed width="320" height="266" src="http://youtube.googleapis.com/v/63_mOyZeNng&source=uds" type="application/x-shockwave-flash" allowfullscreen="true"></embed></object></div><div class="separator" style="clear: both; text-align: center;">
</div><div style="text-align: justify;">You can find the code and schematics here in a single repository, keep in mind that I'm still working on it, and I'm also considering a new revision to fix some minor issues and add an SPI flash for storage. If you have any suggestions/feedback please feel free to leave a comment. </div><pre class="brush:plain">hg clone https://code.google.com/p/openmv-camera/
</pre>Update:
I've created a new repo on github, this has the most recent version:
<pre class="brush:plain">git clone https://github.com/iabdalkader/openmv.git
</pre></div>muxhttp://www.blogger.com/profile/07901500843676691342noreply@blogger.com31tag:blogger.com,1999:blog-7822883683244244182.post-65102575046762544772013-10-17T15:00:00.000+02:002013-10-18T01:50:24.091+02:00OpenMV Update<div dir="ltr" style="text-align: left;" trbidi="on">
Another quick update on my project <a href="http://sigalrm.blogspot.com/2013/09/openmv-camera-module.html" target="_blank">OpenMV</a>. I've finally managed to get the sensor working in QQVGA/RGB565 mode:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjSkhE9nMAeqqdPhLtjJHmCqpnxuzOUhh0R-br7JxQUTpwaP8vjRqBBBLz4ZG90MGwSh3ul_GyRa1CQ1uGGY4vcjT3bf8ECYveLGobsnuqemYsJsri79fYANaloZd-hdocPpVV5gY2MfW4/s1600/IMAG0168.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="265" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjSkhE9nMAeqqdPhLtjJHmCqpnxuzOUhh0R-br7JxQUTpwaP8vjRqBBBLz4ZG90MGwSh3ul_GyRa1CQ1uGGY4vcjT3bf8ECYveLGobsnuqemYsJsri79fYANaloZd-hdocPpVV5gY2MfW4/s400/IMAG0168.jpg" width="400" /></a></div>
<br />
I'm using the discovery board as a debugger and a smart LCD to display the frames via USART. I've also implemented a simple color tracking algorithm, as a proof of concept:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiRPZq9oeXTRsWSyH32anMtITI4-4uH-VwBk9fUFURmeduCxePYd5IK1MVOKCTHF80IcVjqPe2tCOhYmlM2hQt9LU29foqdTn_JmrU5RRGhi91R68XiYxJosfZmSb9RQzhhzd5sr0cy_Oo/s1600/IMAG0173.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="266" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiRPZq9oeXTRsWSyH32anMtITI4-4uH-VwBk9fUFURmeduCxePYd5IK1MVOKCTHF80IcVjqPe2tCOhYmlM2hQt9LU29foqdTn_JmrU5RRGhi91R68XiYxJosfZmSb9RQzhhzd5sr0cy_Oo/s400/IMAG0173.jpg" width="400" /></a></div>
<br />
I'm currently cleaning up the code, and I will share it with the schematics next time.. Thanks for all your support :)<br />
<br /></div>
muxhttp://www.blogger.com/profile/07901500843676691342noreply@blogger.com1tag:blogger.com,1999:blog-7822883683244244182.post-14971161411482128452013-09-16T00:32:00.000+02:002013-09-16T00:32:24.326+02:00OpenMV Camera Module<div dir="ltr" style="text-align: left;" trbidi="on">
This a quick update on my <a href="http://sigalrm.blogspot.com/2013/07/in-search-of-better-serial-camera-module.html" target="_blank">camera project </a>(OpenMV)... I've finally received the long overdue PCBs today and assembled one:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjIqnJkTAqnJHVV1SYJ24h9jCB_my2Nw62ZfoXZ4neD3s9NLCho9PfXQgs4TzKIKR5uQHRwMp0bIHpgjnlTCi4bsBj67I5MEGXzWY-un0HsSo3N6HKBtar-mZIy9nXMzqN3fG1mayPi0ZU/s1600/openmv.jpeg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjIqnJkTAqnJHVV1SYJ24h9jCB_my2Nw62ZfoXZ4neD3s9NLCho9PfXQgs4TzKIKR5uQHRwMp0bIHpgjnlTCi4bsBj67I5MEGXzWY-un0HsSo3N6HKBtar-mZIy9nXMzqN3fG1mayPi0ZU/s400/openmv.jpeg" width="303" /></a></div>
<br />
I haven't written any code yet, but I've managed to get it into DFU mode and upload a blinky, it seems to be working fine so far, no smoke :) I will post another update or a video as soon as I get something cool running.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiVqOY3QSYatYVfbNBEql93bJq9JVfEHUAZ-OvrFb-eUvngRTzzK_dgf91IujZkTa3XZclmowJSDdD11U2RV-40XdzKjnXCT0mHkTAjJcwi5_ulh421x5wFY8QrTJWMEuBP2Dwd45ddJjo/s1600/DSC03631.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiVqOY3QSYatYVfbNBEql93bJq9JVfEHUAZ-OvrFb-eUvngRTzzK_dgf91IujZkTa3XZclmowJSDdD11U2RV-40XdzKjnXCT0mHkTAjJcwi5_ulh421x5wFY8QrTJWMEuBP2Dwd45ddJjo/s400/DSC03631.JPG" width="400" /></a></div>
<br /></div>
muxhttp://www.blogger.com/profile/07901500843676691342noreply@blogger.com15tag:blogger.com,1999:blog-7822883683244244182.post-55581223499185599142013-07-19T01:29:00.000+02:002013-07-19T01:29:01.743+02:00NHD-C12832 Breakout<div dir="ltr" style="text-align: left;" trbidi="on">
<div style="text-align: justify;">
This is a breakout board for NewHaven's NHD-C12832 graphic display, a 128 x 32 pixels display with an SPI interface. I like this display mainly because it's cheap (about $11) I think it was the cheapest one I could find with this resolution, and it also looks great. However, it has an unusual package (tight pitch pins and four holes, two for the backlight and two for the screen) so I had to spend some time working on the footprint and PCB, but the end result was good.<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgHcPm9yXfVFR1zArJkMnhfk8YuzrJmYOzA0pliPmJBaswZNZ7UOfstYf_4FdPesARCjIPcsOr5eXz37ieWkMMCcylA0ThU-OG6F_ygwXD3hjwcyeX6XM-ZW9YE5QCNr96Iy6UGqRg0hO8/s1600/DSC03583.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgHcPm9yXfVFR1zArJkMnhfk8YuzrJmYOzA0pliPmJBaswZNZ7UOfstYf_4FdPesARCjIPcsOr5eXz37ieWkMMCcylA0ThU-OG6F_ygwXD3hjwcyeX6XM-ZW9YE5QCNr96Iy6UGqRg0hO8/s400/DSC03583.JPG" width="400" /></a></div>
<br />
<div style="text-align: justify;">
I placed all components on the backside of the PCB to keep it as small as possible, the board has a 3.3v 150mA LDO regulator (the display operates from 2.6v to 3.3v) and a level shifter (74VHC541) to convert the logic signals to the operating voltage, so it's compatible with 5.0v logic and can be powered from 3.3v up to the maximum rating of the voltage regulator. The backlight is connected to the regulator via a MOSFET (it draws 45mA maximum) which can be controlled with PWM. The display has an SPI interface and draws about 0.45mA maximum.</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjhyeccP7z4Q22WgrFYBxY7_QgeUpJrqYEhHf7A7q9SmnvRGhEqALBtvx16UY0KrWfYWHULV2lLIiiJWX5s9wk7xxrzGM8AAi-rOwhCsDYZ3QDQqdfkhLfJ-0R6M7Y58p-voTJKN6NsP3w/s1600/DSC03580.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjhyeccP7z4Q22WgrFYBxY7_QgeUpJrqYEhHf7A7q9SmnvRGhEqALBtvx16UY0KrWfYWHULV2lLIiiJWX5s9wk7xxrzGM8AAi-rOwhCsDYZ3QDQqdfkhLfJ-0R6M7Y58p-voTJKN6NsP3w/s400/DSC03580.JPG" width="400" /></a></div>
<div style="text-align: justify;">
The display controller is supported by <a href="http://code.google.com/p/u8glib/" target="_blank">u8glib</a>, so I wrote small Arduino sketch to test drawing a bitmap, to generate the bitmap, I used gimp to convert the image to black and white (1-bit) and then exported it to hex (save as .xbm) and then included that as a header in the sketch...<br />
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhHFFNioeglnNJxVuGWc1sATMx-_yDphtsDKUqcMtq6zR4yy64ekk0-R_cd5mPAKYABqGGnmIzPR7UBxntFo0FLo4m8hJLrcm3w3hsVt7JLbfOzm-K11fFhcAJV7LZvA4Tdg_TT_AwThIY/s1600/DSC03611.JPG" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" height="480" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhHFFNioeglnNJxVuGWc1sATMx-_yDphtsDKUqcMtq6zR4yy64ekk0-R_cd5mPAKYABqGGnmIzPR7UBxntFo0FLo4m8hJLrcm3w3hsVt7JLbfOzm-K11fFhcAJV7LZvA4Tdg_TT_AwThIY/s640/DSC03611.JPG" width="640" /></a></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<br />
<b>Sources:</b><br />
The repository includes the Eagle files and the Arduino sketch.<br />
<br />
<pre class="brush:plain">hg clone https://code.google.com/p/nhd-c12832-breakout
</pre>
</div>
</div>
muxhttp://www.blogger.com/profile/07901500843676691342noreply@blogger.com5tag:blogger.com,1999:blog-7822883683244244182.post-73671985270780039022013-07-09T22:08:00.000+02:002013-09-15T23:18:27.023+02:00In Search of a Better Serial Camera Module<div dir="ltr" style="text-align: left;" trbidi="on">
<div style="text-align: justify;">
So I've been looking everywhere for a cheap serial camera to use in my projects, preferably with some basic image processing, like object or motion detection etc.. The cheapest one I could find that barely meets my needs is sold on <a href="http://www.adafruit.com/products/397" target="_blank">adafruit</a> for $35, it has a 640x480 pixels sensor and can do some motion detection but nothing more. Then there is the more expensive modules which cost around $40 that do nothing at all and finally there's the <a href="https://www.sparkfun.com/products/10032" target="_blank">CMUcam</a>, which has some really nice features, but way too big and expensive (costs $100) for my needs...</div>
<br />
So I decided to make my own serial camera, keeping in mind the basic set of features that I want:<br />
<ul style="text-align: left;">
<li>Low cost</li>
<li>Small form</li>
<li>Basic image processing</li>
<li>Open source (duh!)</li>
</ul>
<div style="text-align: justify;">
First, I had to choose an image sensor to use, I was inclined to use the <a href="http://sigalrm.blogspot.com/2011/03/tcm8230md-breakout.html" target="_blank">TCM8230MD</a>, which I'm familiar with, however, the sensor alone costs $10 and I can't seem to find it any where else other than sparkfun. So, I've decided to try the Omnivision sensors, the cheapest one I could find is the OV9650 (1280x1024 pixels) sold on ebay for $2... The nice thing about this sensors is that it connects to the board with an FPC cable (that flexible yellow cable), which means it's possible to replace it later with another one (assuming it has the same pinout) and it also has a higher resolution than the TCM8230MD. The downside with this particular sensor is that it doesn't have JPEG compression, but I could live with RGB/RAW output, after all I plan to use it mainly for image processing, or I could try to implement the JPEG compression on the micro.</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhjbh7p-0YKzbkNOvdFp0PcSNZRVO7IFcFARpx9fQANVbA8G2fZM3QdNp2ojZstG0wYTkQZfOH7rCCjKdEvOFaUxFfzAUWpCuBv2WBED-PyYNFOJB3n7rwOug2IZPXI7wVy6WIH4BFrFCA/s1600/images.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhjbh7p-0YKzbkNOvdFp0PcSNZRVO7IFcFARpx9fQANVbA8G2fZM3QdNp2ojZstG0wYTkQZfOH7rCCjKdEvOFaUxFfzAUWpCuBv2WBED-PyYNFOJB3n7rwOug2IZPXI7wVy6WIH4BFrFCA/s320/images.jpg" width="245" /></a></div>
<br />
<div style="text-align: justify;">
Moving on to the microcontroller, a powerful micro is needed to interface with this sensor, preferably with a DCMI hardware interface, I implemented a DCMI before in software with an LPC1768/TCM8230MD and it could barely keep up, so I decided to go with something faster. </div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
F<span style="text-align: justify;">ortunately</span><span style="text-align: justify;">, I had a couple of STM32F4 micros laying around, which seemed perfect for the job since it runs at 168MHz, has a hardware DCMI (should make it a lot easier to interface the camera) and as an added bonus, it has a floating point unit and vector processing (SIMD), making it perfect for image processing... Unfortunately, the DCMI only comes with the LQFP-100 package, so I couldn't use a smaller one. </span></div>
<br />
I started working on the PCB, first, I made a footprint for the sensor and its connector, which seems to fit nicely:<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgsFViSeg8PF9vUp4RKV1QMu0trZmPbjZ8SYdbO59GZViyQvNqIhcvvoYT1aWPcB1k2IfFzZylq3MlIrHmLEUemnqcPLhSvYh2rvadtQ-QRBzYXv4xR9CXzJ64pylDPlBg-CsZpUYuIwzs/s1600/DSC03486.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="265" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgsFViSeg8PF9vUp4RKV1QMu0trZmPbjZ8SYdbO59GZViyQvNqIhcvvoYT1aWPcB1k2IfFzZylq3MlIrHmLEUemnqcPLhSvYh2rvadtQ-QRBzYXv4xR9CXzJ64pylDPlBg-CsZpUYuIwzs/s320/DSC03486.JPG" width="320" /></a></div>
<div style="text-align: justify;">
And then I moved to the layout, however, shortly after that, I realized that it's impossible to fit the sensor and micro (let alone the debugging header and interface) on a 2 layer PCB, which is what I had in mind initially to reduce the costs. So a 4 layer PCB seemed inevitable If I wanted to make it as small as possible, there's also some inherit benefits to the extra layers such as better power planes and decoupling, easier routing etc... Anyway, the first version of the PCB (25x37mm) costs around $5</div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi4i_SyPc6qN9GGJI_AgAM7DXeNW8BtT6kRV-TY-JINUnyl3393FJBfL0-2F5kvVKqHNlzxBqeuqnGb6IIxeZHAaF32sH4o-KeLil3AXevRlOAlLBSUiDRwQqD4PFzovHjnUoZkoCyXta8/s1600/openmv-1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi4i_SyPc6qN9GGJI_AgAM7DXeNW8BtT6kRV-TY-JINUnyl3393FJBfL0-2F5kvVKqHNlzxBqeuqnGb6IIxeZHAaF32sH4o-KeLil3AXevRlOAlLBSUiDRwQqD4PFzovHjnUoZkoCyXta8/s320/openmv-1.png" width="232" /></a></div>
<br />
The board has a triple output LDO 3.3v/2.5v/1.5v (the one I had at hand came in a QFN package) and a micro USB connector, which can be used to power the board or update the firmware with DFU. The SWD pins are broken out for debugging (I'm currently working on a JTAG debugger too) I also throw in an RGB led (not sure if it's too close to the sensor to be visible or not)<br />
<br />
<div style="text-align: justify;">
The STM32F4 micro costs $11.79 per one, and $7.31 per 500, this adds up to around $20 for one piece and could go as low as $15 for 500 pieces, it's much higher than I expected, but It should make up for it with some cool image processing, and still almost $15 cheaper than the adafruit camera :)</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
I still haven't received the PCBs yet, will post an update when I do and when I get it working I will release all the sources. I'm also giving away one for free, leave a comment if you're interested :)</div>
</div>
muxhttp://www.blogger.com/profile/07901500843676691342noreply@blogger.com39tag:blogger.com,1999:blog-7822883683244244182.post-52597593676454344592013-05-05T18:08:00.001+02:002013-05-05T18:08:13.028+02:00Running OLinuXino-MAXI on Battery<div dir="ltr" style="text-align: left;" trbidi="on">
<br />
<div style="text-align: justify;">
Finally I've had some time to play with my new <a href="https://www.olimex.com/dev/imx233-olinuxino-maxi.html" target="_blank">Olimex iMX233-OLinuXino-MAXI</a> board, the board is similar to the <a href="http://www.raspberrypi.org/">Raspberry pi</a>, almost the same size and cost, however, this one has an ARM iMX233 running at 454Mhz, less RAM and no GPU. </div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
I played with the board for a while then I decided to test it using batteries, I found out that the USB/Ethernet physical is disabled when running on batteries ! After some digging around in the <a href="https://www.olimex.com/Products/OLinuXino/iMX233/iMX233-OLinuXino-MAXI/resources/iMX233-OLINUXINO-MAXI.pdf" target="_blank">datasheet</a>, there seems to be a way around this, by swapping two jumpers (<b>3.3V_E</b> and <b>3.3VIO_E</b>) located near the reset button that control which DC-DC converter is used, the two possible configurations for those jumpers are:</div>
<ol style="text-align: left;">
<li> External DC-DC: <b>3.3V_E</b> closed (soldered), <b>3.3VIO_E</b> open (unsoldered/cut)</li>
<li> On-chip DC-DC: <b>3.3V_E</b> open (unsoldered/cut), <b>3.3VIO_E</b> closed (soldered)</li>
</ol>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgaEyshw1wNOwYIHefIuFzHkY-mWbhVcyfZOP88fopptqjV_afxioooja1v0Naah0Cux-Z_oyla8rLiMWoEiWjpB2JfPUadtPIGjICBkMEW2Iu2h5ZqzkQ6d6jX4jk5fSiNrOxV4ZCjJxY/s1600/IMAG0230.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="277" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgaEyshw1wNOwYIHefIuFzHkY-mWbhVcyfZOP88fopptqjV_afxioooja1v0Naah0Cux-Z_oyla8rLiMWoEiWjpB2JfPUadtPIGjICBkMEW2Iu2h5ZqzkQ6d6jX4jk5fSiNrOxV4ZCjJxY/s400/IMAG0230.jpg" width="400" /></a></div>
<br />
<div style="text-align: justify;">
Note that the datasheet mentions that the maximum current that can safely be drawn from the on-chip convertor is 200ma and you need to make sure that you don't draw more than that, I'm not sure how exactly, but you should probably use one USB device at a time and either the USB or LAN. </div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
It also mentions that the internal DC-DC makes the chip heat a little bit, so you may want to place a small heat sink on the processor.</div>
</div>
muxhttp://www.blogger.com/profile/07901500843676691342noreply@blogger.com0tag:blogger.com,1999:blog-7822883683244244182.post-79785575128495512542012-09-24T19:41:00.000+02:002012-09-24T19:45:30.575+02:00Routing Differential Signals<div dir="ltr" style="text-align: left;" trbidi="on">
<div dir="ltr" style="text-align: left;" trbidi="on">
<div style="text-align: justify;">
<a href="http://en.wikipedia.org/wiki/Differential_signaling" target="_blank">Differential Signalling</a> uses a pair of complementary signals to cary data, that is each wire is carrying the opposite signal, those signals are subtracted at the receiving end and the result is either 0 for noise or 1 for a valid signal. This technique is used with high speed signals to reduce crosstalk and EMI, examples of differential signalling include the twisted pairs inside Ethernet cables, HDMI and USB.</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="http://upload.wikimedia.org/wikipedia/en/1/1c/Differential_Signaling.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="210" src="http://upload.wikimedia.org/wikipedia/en/1/1c/Differential_Signaling.png" width="400" /></a></div>
<div style="text-align: justify;">
When routing differential signals, each pair should have the exact same length, because the signals are subtracted from each other so they need to arrive at the exact same time, otherwise it's useless, the same requirement applies to other high-speed non-deferential signals such as the signals of this DRAM, note the wiggly tracks on the PCB which are used to make the tracks of equal length:</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiclSmJ-tFfmd06woIQK5t7dy7K7Tad1vMW3QrHdiYtis33vIAQwFFq0a6BIJkZfC-rNX09xcI4D1EjPSueYhLCVaXfCrBrzTCl4djHV8n20px2uJdqSVPEfUGPcKCDBt-cKf5YToFGUls/s1600/2012-09-24-182244.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="234" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiclSmJ-tFfmd06woIQK5t7dy7K7Tad1vMW3QrHdiYtis33vIAQwFFq0a6BIJkZfC-rNX09xcI4D1EjPSueYhLCVaXfCrBrzTCl4djHV8n20px2uJdqSVPEfUGPcKCDBt-cKf5YToFGUls/s320/2012-09-24-182244.jpg" width="320" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<br />
<div style="text-align: justify;">
Eagle 6 has some facilities to help with differential routing, if you use an older version you could still do it manually. For Eagle 6, first give both signals the same name with one ending with _N and the other with _P, so for example USB_N and USB_P, now when you start routing either one of the signals they both will be routed together as you can see: </div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjlLAth4CdD09WSjHnD7wpIQ8QJMCSf6eWX6iaQC8XTa70h4k0hyhim6z8ACU7G-EL2sdAWViIE-RaGdYxEVu3RnZUUVcFhclC7v-QVAPJRTDP9_Wue5Maql6l1AE94kbvoGgySm634kfM/s1600/Screenshot-2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="192" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjlLAth4CdD09WSjHnD7wpIQ8QJMCSf6eWX6iaQC8XTa70h4k0hyhim6z8ACU7G-EL2sdAWViIE-RaGdYxEVu3RnZUUVcFhclC7v-QVAPJRTDP9_Wue5Maql6l1AE94kbvoGgySm634kfM/s320/Screenshot-2.png" width="320" /></a></div>
<br />
<div style="text-align: justify;">
If you can't route both signals together, if there's not enough space, then one will be shorter than the other, and that's when you will need the wiggly traces, or formally the Meander function. After you finish routing the signals as usual, run the meander function with the length you wish to add to the shorter trace, then click on the trace and move the mouse it will start adding wiggles to the trace:</div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiVDAtLpUvbV8NwWF1TgW37vrxuIrrcaVxYHiIVm5zVwH4N1mxXWmLd61z44_7mtI1HycJHoZD5Dx39wuxxpSK0daA3KthwpTyVrbAMY_hlbKidDH1B_P42qfru61Vc4RMiaSBcyoqoso0/s1600/Screenshot-5.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="175" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiVDAtLpUvbV8NwWF1TgW37vrxuIrrcaVxYHiIVm5zVwH4N1mxXWmLd61z44_7mtI1HycJHoZD5Dx39wuxxpSK0daA3KthwpTyVrbAMY_hlbKidDH1B_P42qfru61Vc4RMiaSBcyoqoso0/s320/Screenshot-5.png" width="320" /></a></div>
<br />
You can also use the length.ulp to find out the difference between the tracks before using the meander function:<br />
<pre class="brush:plain">run length USB*</pre>
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhlzTFnq3A5p5ZS4gtud8py6MUPoSrrR_t3vI6T-lc1qn_NUQNocXGe_YcVq_-dtsrLljOz17OeUjJIbVV04nVUsJDZvrefu6qxfYNoGqEHKBCUDl9P6GXaelMm0AFZJ-CQ9xAbGb1YEBQ/s1600/snapshot15.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="170" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhlzTFnq3A5p5ZS4gtud8py6MUPoSrrR_t3vI6T-lc1qn_NUQNocXGe_YcVq_-dtsrLljOz17OeUjJIbVV04nVUsJDZvrefu6qxfYNoGqEHKBCUDl9P6GXaelMm0AFZJ-CQ9xAbGb1YEBQ/s320/snapshot15.png" width="320" /></a></div>
</div>
muxhttp://www.blogger.com/profile/07901500843676691342noreply@blogger.com0tag:blogger.com,1999:blog-7822883683244244182.post-41537254598672771142012-09-01T21:26:00.002+02:002013-07-10T17:00:42.838+02:00STM32F4 Discovery Quick Start Guide<div dir="ltr" style="text-align: left;" trbidi="on">
I finally got my hands on an STM32F4 Discovery board, those are super cheap STM32F407 ARM Cortex-M4 boards from ST. The Cortex-M4 is perfect for DSP applications as it has SIMD and an FPU and it also runs at 168Mhz. As for the board, it seems okay given its price, I really hate the headers though and it only has a few components namely, an audio DAC, a chip microphone, an accelerometer and a few LEDs.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiaQ2apwadXss4KxsVoKFuVdDHzfEg9XIbGQmdzV6SNEpVpdp-IrQHA2JIdUgvA3CLqtyXxOOqY0NrlY-fEc6Pz2oSI9REshUYNPNpnfnDhVlmJa7wkfyvVs2-oqrg-LdySZFNTogLg1WM/s1600/stm32f4_discovery.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="212" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiaQ2apwadXss4KxsVoKFuVdDHzfEg9XIbGQmdzV6SNEpVpdp-IrQHA2JIdUgvA3CLqtyXxOOqY0NrlY-fEc6Pz2oSI9REshUYNPNpnfnDhVlmJa7wkfyvVs2-oqrg-LdySZFNTogLg1WM/s320/stm32f4_discovery.jpg" width="320" /></a></div>
<br />
There's also an STLINK debugger on board, which means you don't need anything else to program and debug the chip. This is a quick tutorial on how to setup a toolchain and the necessary software.<br />
<b><br />
</b> <b>Setting up a toolchain</b><br />
First thing you need to do is build or install a toolchain, I couldn't get myself to use any of the toolchains/IDEs that work with the board, as they are all propriety and they all have some sort of limitations on the free editions.<br />
<br />
There's always the CodeSourcry toolchain, while it works fine, however, it was not built with hard-float enabled only soft and softfp, which means you have a choice between slow FP and really slow FP emulation. I also tried the <a href="https://github.com/esden/summon-arm-toolchain">summon-arm-toolchain</a>, but it seems to have the same problem no hard-float...<br />
<br />
I then accidentally stumbled upon a <a href="https://launchpad.net/gcc-arm-embedded">gcc toolchain</a> which seems to be maintained by ARM and it supports soft, softfp and hard-float, I think I will be using this toolchain for every ARM Cortex I have from now on, anyway, now that you have a working toolchain you can start compiling programs but you still need drivers.<br />
<br />
<b>Building the drivers library:</b><br />
ST provides a package that includes drivers for all the peripherals, a DSP library, API documentation and lots of examples, if you look at the examples you will see that you have to copy all the *.c files you need to your project directory along with the linker script, system initialization and startup code, personally, I like to build a monolithic library and just link with that, so you can skip this step if you want:<br />
<br />
First download and extract the <a href="http://www.st.com/internet/mcu/product/252140.jsp#FIRMWARE">STM32F4 DSP and standard peripherals Library</a> then copy the startup and initialization code to the src directory: <br />
<pre class="brush:bash">$ cp Libraries/CMSIS/Device/ST/STM32F4xx/Source/Templates/system_stm32f4xx.c Libraries/STM32F4xx_StdPeriph_Driver/src/
$ cp Libraries/CMSIS/Device/ST/STM32F4xx/Source/Templates/TrueSTUDIO/startup_stm32f4xx.s Libraries/STM32F4xx_StdPeriph_Driver/src/
</pre>
Before you build the library, note that most of the drivers use a macro called <b>assert_param</b>, this macro is defined in <b>stm32fxx_conf.h</b> when you build a project you can enable/disable assertions, but since we're compiling this into a library the macro has to be seen at compile time, otherwise the compiler will just assume it's an external symbol and you'll get undefined references later, so you need to add this macro to the <b>stm32f4xx</b> header<br />
<pre class="brush:cpp">#Libraries/CMSIS/Device/ST/STM32F4xx/Include/stm32f4xx.h
#ifdef USE_FULL_ASSERT
#define assert_param(expr) ((expr) ? (void)0 : assert_failed((uint8_t *)__FILE__, __LINE__))
void assert_failed(uint8_t* file, uint32_t line);
#else
#define assert_param(expr) ((void)0)
#endif /* USE_FULL_ASSERT */
</pre>
if you <b>#define USE_FULL_ASSERT</b> it will enable assertions or you can compile two libraries one for normal use and the other for debugging.<br />
<br />
Finally, copy this Makefile into the src directory and compile the library, I'm assuming here that you have the new toolchain in the path:<br />
<pre class="brush:bash">#Libraries/STM32F4xx_StdPeriph_Driver/src/Makefile
LIB = libcm4.a
SRCS = $(wildcard *.c)
LIB_OBJS= $(SRCS:.c=.o)
AFLAGS = -mcpu=cortex-m4 -mthumb -mthumb-interwork -mlittle-endian -mfloat-abi=hard -mfpu=fpv4-sp-d16
CFLAGS = -mcpu=cortex-m4 -mthumb -mthumb-interwork -mlittle-endian -mfloat-abi=hard -mfpu=fpv4-sp-d16 -O2 \
-I../inc -I../../CMSIS/Include/ -I../../CMSIS/Device/ST/STM32F4xx/Include/
CC = arm-none-eabi-gcc
AS = arm-none-eabi-as
LD = arm-none-eabi-ld
AR = arm-none-eabi-ar
all:: $(LIB)
$(LIB): $(LIB_OBJS)
$(AR) -r $(LIB) $(LIB_OBJS)
echo $(LIB_OBJ)
clean:
$(RM) *.o *.a
.c.o :
$(CC) $(CFLAGS) -c $<
.s.o :
$(AS) $(AFLAGS) $< -o $@
</pre>
When it's done, copy all the headers (including the CMSIS headers) and the library to somewhere like /opt or /usr/local. There's just one last piece of the puzzle missing, the<b> linker script</b>, you can find one in the many templates included with the library or use the one <a href="https://github.com/jeremyherbert/stm32-templates">here</a>, it also includes a Makefile template.<br />
<br />
<b>Blinky... Well not exactly!</b><br />
To keep this simple, this example just lights up one of the LEDs on the board <b><br />
</b><br />
<pre class="brush:cpp">#include "stm32f4xx_rcc.h"
#include "stm32f4xx_gpio.h"
GPIO_InitTypeDef GPIO_InitStructure;
int main(void)
{
/* GPIOG Periph clock enable */
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE);
/* Configure PD12 in output mode */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(GPIOD, &GPIO_InitStructure);
/* Set PD12 high */
GPIO_SetBits(GPIOD, GPIO_Pin_12);
/* Do nothing */
while (1) {
}
}</pre>
<b>Programming and debugging</b><br />
There's no "official" stlink utility for Linux, so I used this one instead:<br />
<pre class="brush:bash">$ git clone https://github.com/texane/stlink.git
$ cd stlink
$ ./autogen.sh
$ ./configure
$ make
</pre>
This will build two binaries, the st-util a gdb server, and st-flash which is supposed to let you write the binary to flash but it doesn't really work! anyway, the project includes a udev rules, you should use that instead of sudo each time:<br />
<pre class="brush:bash">$ cp 49-stlinkv2.rules /etc/udev/rules.d/
$ udevadm control --reload-rules
</pre>
<br />
Now just run st-util and in another terminal run gdb:<br />
<pre class="brush:bash">$ arm-none-eabi-gdb blinky.elf
$ tar ext :4242
$ load
$ continue
</pre>
<br />
<b>Notes</b><br />
Take care not to remap the USB pins used by the STLINK debugger, if you do so the debugger won't be able to talk to the chip and you could actually <b>brick the board</b> :) if you do find yourself in this situation, pull the BOOT0 pin high, there's a VDD pin right next to it so just place a jumper on those pins, when you do that, the board will run the bootloader instead and you can erase the entire flash.<br />
<br />
The library is configured for a 25MHz oscillator and the Discovery board has an 8MHz oscillator, you will need to change two values to fix that, the HSE_VALUE in <b>stm32f4xx.h</b> set that to (8000000) and the PLL_M in <b>system_stm32f4xx.c</b> to (8).</div>
muxhttp://www.blogger.com/profile/07901500843676691342noreply@blogger.com6tag:blogger.com,1999:blog-7822883683244244182.post-74861562565141745012012-07-11T16:13:00.000+02:002012-07-11T20:34:19.108+02:00Portable SDR with Olinuxino for Tracking Wildlife<div dir="ltr" style="text-align: left;" trbidi="on">
<div style="text-align: left;">
I was working on a project for a biologist friend of mine, that involved tracking RF tag implants on wildlife, using an SDR DVB-T dongle. He wanted a portable solution to be placed near the sprainting places of <a href="http://en.wikipedia.org/wiki/Otter">Otters</a>(<i>Lutra lutra)</i>, the main subject of the study, where they regularly come to deposit scent marks<span style="font-family: inherit; font-size: x-small;">.</span></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjiwVYFIDRNZJY7mQT3yRfqTJLC5Dg-mA-IfEn6OEpO4ctYw4XLTtJtIccg0MLg_WiifyjiXlqwvFyqse1vnRo-PDzhmUpxBodza_vOmz-l6l23zru2BWBX7SewoOjOrscv8P7GCs_H8hg/s1600/Image00001.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="211" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjiwVYFIDRNZJY7mQT3yRfqTJLC5Dg-mA-IfEn6OEpO4ctYw4XLTtJtIccg0MLg_WiifyjiXlqwvFyqse1vnRo-PDzhmUpxBodza_vOmz-l6l23zru2BWBX7SewoOjOrscv8P7GCs_H8hg/s320/Image00001.jpg" width="320" /></a></div>
<br />
An RF tag is implanted on the animal which sends pulses on a frequency unique for each tag, this way we're able to tell them apart, this is what a cheap RF tag looks like, this one has a frequency of 148.354Mhz<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh3_22mHO9pSBabSwXJ8u_neh39nXiheOh2bXiZ97ants0ue0jkLA9e4dloowJ4R-AiXFzxin8kXYlu3jDO0HrpQeCEfhIvxcZbizeIdLBNMgXXwztRmoLX3RRfBbenQxT7s2RaOLGb944/s1600/IMAG0002.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="217" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh3_22mHO9pSBabSwXJ8u_neh39nXiheOh2bXiZ97ants0ue0jkLA9e4dloowJ4R-AiXFzxin8kXYlu3jDO0HrpQeCEfhIvxcZbizeIdLBNMgXXwztRmoLX3RRfBbenQxT7s2RaOLGb944/s320/IMAG0002.jpg" width="320" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
</div>
Software defined radio (SDR) became a bit more accessible recently,
when a kernel hacker discovered that DVB-T dongles based on the RTL2832U
chip can be used as a cheap SDR,
since the chip allows transferring the raw samples to the host. Since the project was on a tight budget that seemed like a perfect solution...<br />
<br />
The <a href="http://sdr.osmocom.org/trac/wiki/rtl-sdr%20">osmocom</a> project provides a user space driver for the dongle, I started with <a href="https://github.com/roger-/pyrtlsdr">pyrtlsdr</a>, a Python binding for librtlsdr, and pylab for signal processing of the samples collected by the SDR, to compute and plot the <a href="http://en.wikipedia.org/wiki/Spectral_density">PSD</a>, that last spike corresponds to the signal of the RF tag above:<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhzg6EKjMtSAO2SAuTISs9ollbbNiqf7E-nkHrb74Ga3R3AOlKWI81rI9zWBdpYqLvboqqCXYyq10y_A9-toq1RihVFPM0CzfrbpSpWFR7T7FIFZRB4WRExrT3ZIxAEFaZwUUvIYe0JGkc/s1600/sdr.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="301" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhzg6EKjMtSAO2SAuTISs9ollbbNiqf7E-nkHrb74Ga3R3AOlKWI81rI9zWBdpYqLvboqqCXYyq10y_A9-toq1RihVFPM0CzfrbpSpWFR7T7FIFZRB4WRExrT3ZIxAEFaZwUUvIYe0JGkc/s400/sdr.png" width="400" /></a></div>
<br />
Finally, I ported everything to an <a href="https://www.olimex.com/dev/imx233-olinuxino-maxi.html">olinuxino</a> ARM-based board running Linux, a script runs on boot and logs the detected frequencies to file on SD card for later processing, the board still hasn't been tested in the field yet, I'm still working out some issues with the power management.<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhEmWn1CxSBRdNW2ozWdjCk1oCNry2t33j2KULRVktCg7h-tAvIfzomUZYK2Vj3FQVT8y5-GtO3ojvxGd21wu_Vxazp5BWoK1iaQG0vONlZMm3GK9ZH-PbjMnnYl81epI85DsA2OQgbyJs/s1600/IMAG0128.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="272" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhEmWn1CxSBRdNW2ozWdjCk1oCNry2t33j2KULRVktCg7h-tAvIfzomUZYK2Vj3FQVT8y5-GtO3ojvxGd21wu_Vxazp5BWoK1iaQG0vONlZMm3GK9ZH-PbjMnnYl81epI85DsA2OQgbyJs/s400/IMAG0128.jpg" width="400" /></a></div>
</div>muxhttp://www.blogger.com/profile/07901500843676691342noreply@blogger.com2tag:blogger.com,1999:blog-7822883683244244182.post-39018073697823569542012-05-03T00:55:00.000+02:002013-07-16T01:12:42.227+02:00MIPS1 ISA Implementation with Verilog<div dir="ltr" style="text-align: left;" trbidi="on">uMIPS is a 32-bit pipelined processor implementing the MIPS1 ISA, written in synthesizable Verilog and tested on a DE0 CycloneIII FPGA board. A great deal of the ISA is implemented, enough to run small C programs compiled with the gcc toolchain.<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgkgsjdQML61O_sCfaFxCmED5-kuDQFiZKVG2_uQzyCOETt6nubHzIhjfhgfeYi69CsqMQzRosvqORxcyF8TPdTD7wdma4NZ3CpdqWhR9-WaLKvXU4wBktu3YwOmtEO-PVf9oYiKSy4i8c/s1600/umips.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="221" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgkgsjdQML61O_sCfaFxCmED5-kuDQFiZKVG2_uQzyCOETt6nubHzIhjfhgfeYi69CsqMQzRosvqORxcyF8TPdTD7wdma4NZ3CpdqWhR9-WaLKvXU4wBktu3YwOmtEO-PVf9oYiKSy4i8c/s400/umips.png" width="400" /></a></div><br />
The design is based on a classic five-stage pipeline, fetch, decode, execute, memory and write-back stages, each one is represented by an architectural state register, it's worth mentioning that it's enough to save and restore those registers for a context switch if needed. Separate data and instruction memories are used, each one is initialized with a memory hex file generated by the toolchain. <br />
<br />
The design includes a hazard unit that solves control and data hazards by forwarding or stalling the pipeline whenever is necessary and some registers are memory mapped to high addresses to control the LED strip on the board and the 2x16 LCD screen. <br />
<br />
<b>Testing</b><br />
I tested the processor successfully by running a program that computes the factorial of a number and the LCD driver.<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgR3m2gAxbF-UJcauUgJnXQ5RT23tIL6vgv8JttSogFXYf4gkc9ds0Frw25EFkuv1B6mqKm68ZaZCk6f66KAs_pB3mIuL4YW4nP-TRBe2HJJDqJ8W9NueeqFj36BbjA_6Gc_PyZXhTAXg8/s1600/DSC03014.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgR3m2gAxbF-UJcauUgJnXQ5RT23tIL6vgv8JttSogFXYf4gkc9ds0Frw25EFkuv1B6mqKm68ZaZCk6f66KAs_pB3mIuL4YW4nP-TRBe2HJJDqJ8W9NueeqFj36BbjA_6Gc_PyZXhTAXg8/s400/DSC03014.JPG" width="400" /></a></div><br />
<br />
<b>Todo</b><br />
<ul style="text-align: left;"><li>Dynamic branch prediction.</li>
<li>Load programs from Flash and link to libc.</li>
<li>Exceptions/Interrupts coprocessor.</li>
<li>The instruction memory does not get inferred properly.</li>
</ul><br />
<b> </b><br />
<b>Sources</b><br />
<pre class="brush:plain">hg clone https://code.google.com/p/umips/
</pre><b><br />
</b><br />
<b>References</b><br />
<b><a href="http://www.amazon.com/Digital-Design-Computer-Architecture-Harris/dp/0123704979">David Harris, Sarah Harris. "Digital Design and Computer Architecture"</a></b><br />
<b><a href="http://www.amazon.com/Computer-Organization-Design-Revised-Edition/dp/0123747503/ref=sr_1_1?s=books&ie=UTF8&qid=1335997429&sr=1-1">David A. Patterson, John L. Hennessy. “Computer Organization and Design”, 4th Edition. </a><br />
</b><br />
</div>muxhttp://www.blogger.com/profile/07901500843676691342noreply@blogger.com0tag:blogger.com,1999:blog-7822883683244244182.post-18783212202557619362012-01-25T02:15:00.000+02:002013-07-16T01:30:39.288+02:00nRFCam<div dir="ltr" style="text-align: left;" trbidi="on"><div style="text-align: justify;">The nRFCam is an open-source 2.4GHz wireless camera built using the TCM8230MD camera, an ARM Cortex-m3 LPC176x MCU and a Nordic nRF24l01p chip for the radio link.<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh8jOs3mJOkaH9ka_D5AoeTBtEq2OJgqlPBets6O5nnDeLlOldFkGbychBagfrWW7Cw2DksjhwjfpaVZqrZubIBuv5dHNumgFAuxGiqpj9eHH-0HiTFs8BOMyv0HacZjcza0UDtWlcfxaQ/s1600/Screenshot.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="186" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh8jOs3mJOkaH9ka_D5AoeTBtEq2OJgqlPBets6O5nnDeLlOldFkGbychBagfrWW7Cw2DksjhwjfpaVZqrZubIBuv5dHNumgFAuxGiqpj9eHH-0HiTFs8BOMyv0HacZjcza0UDtWlcfxaQ/s320/Screenshot.png" width="320" /></a></div></div><b>Overview</b><br />
<div style="text-align: justify;">On reset, the Nordic chip is initialized and a PWM channel is configured to generate the clock signal for the EXTCLK, fast GPIO is used for the data bus and the other sync signals. Once the camera is configured, using the I2C interface, it starts sending frames over the 8-bits wide data bus as usual, synchronized by the HSYNC, VSYNC and DCLK signals (for more details on this see the <a href="http://sigalrm.blogspot.com/2011/03/tcm8230md-breakout.html">TCM8230MD-Breakout</a> post). </div><div class="separator" style="clear: both; text-align: center;"></div><br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEglWw4Lj2yxcLnCXVY-YJ4D4S2YTYAj2lJaOYIkRmXwMtVe469y06r3_jq0daieSolqsLV0bMjdvYg-duXmcF89QbHGTNnJ2uQW2QmUW8dcFGxlpD8X7_D-63cuLiZG20zQRS9uARSQ_YI/s1600/nrfcam_bd.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="240" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEglWw4Lj2yxcLnCXVY-YJ4D4S2YTYAj2lJaOYIkRmXwMtVe469y06r3_jq0daieSolqsLV0bMjdvYg-duXmcF89QbHGTNnJ2uQW2QmUW8dcFGxlpD8X7_D-63cuLiZG20zQRS9uARSQ_YI/s400/nrfcam_bd.png" width="400" /></a></div><div style="text-align: justify;"><br />
</div><div style="text-align: justify;">The VSYNC interrupt handler is written entirely in assembly, unfortunately this makes it difficult to port but it's much more optimized. Each scanline is read in a loop and converted from RGB565 to grayscale and then stored in the frame buffer.</div><div style="text-align: justify;"><br />
</div><div style="text-align: justify;">Once we read a complete frame, the frame is compressed using lzf and then sent out over SPI to the nordic radio chip. A simple frame header precedes the frame data, consisting of a start of frame marker (0xAA), to synchronise the frames, followed by the length of the frame and the frame data.</div><br />
<b>Timing</b><br />
<div style="text-align: justify;">The datasheet does not mention how the data bus clock (DCLK) frequency relates to the external clock (EXTCLK) frequency, however, the maximum DCLK frequency can be inferred from the timing characteristics and from the following diagram, given that the minimum setup time T<span style="font-size: xx-small;">SU</span> and hold time T<span style="font-size: xx-small;">HD </span>is 10, if the camera is running at the maximum external clock (EXTCLK) frequency which is 25Mhz, then the maximum DCLK frequency is 1s/20ns = 50MHz. </div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg-R-BYWQb4x8QlOm3i2Y3PLxtjQZQCJbF9V6gzEWTH-HJMQ3RvVsdZcPLMTwa5NNQUfK9X_5_SXKX3NYdkbNaaOufrVedrp1zCsY9teYMEL1ZNtISwcViASInp2ZIGnInAV3Old5Sp8m4/s1600/timing.png" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" height="192" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg-R-BYWQb4x8QlOm3i2Y3PLxtjQZQCJbF9V6gzEWTH-HJMQ3RvVsdZcPLMTwa5NNQUfK9X_5_SXKX3NYdkbNaaOufrVedrp1zCsY9teYMEL1ZNtISwcViASInp2ZIGnInAV3Old5Sp8m4/s640/timing.png" width="640" /></a></div><div style="text-align: justify;"><b></b>If you sample the data at the rising edge of DCLK it means you have only 10ns to read DOUT, if the MCU is running at 100MHz that's one clock cycle to read DOUT, which is not possible, however, since DCLK is a function of EXTCLK lowering EXTCLK lowers DCLK and increase the time window we have to read the data. The NRFCam generates a 6Mhz EXTCLK for the camera, which gives us a few cycles to read the data.</div><br />
<b>Compression</b><br />
<div style="text-align: justify;">The Nordic chip has an on-air datarate of 2Mbps or 250KBps (ignoring any protocol overhead), it means that even with the camera set to output the smallest possible frame 24KB (128x96x2), the maximum we can send is 10 FPS. In other words, there's no point of trying to keep up with a higher frame rate when all you can send is 10FPS.</div><div style="text-align: justify;"><br />
</div><div style="text-align: justify;">The frame is converted from RGB565 to gray scale reducing the frame size by half (12KB), since we don't have enough time between each DCLK edge, the whole scanline is read first and then converted before the next scanline starts (before the next HSYNC edge). </div><div style="text-align: justify;"><br />
</div><div style="text-align: justify;">After the whole frame has been read, the frame is compressed using the lzf compression algorithm, there's no particular reason for selecting lzf other than that it was the easiest to port and configure for a low memory footprint, maybe there's an algorithm that can better exploit the data, anyway, at this point the frame size is reduced to 4KBs-6KBs (depending on the frame).</div><div style="text-align: justify;"><br />
</div><div style="text-align: justify;">On the other side, the frame can be received by any compatible Nordic chip, decompressed and the grayscale level of each pixel is repeated in the RGB components of the new pixel. Note that since the blue component has 6 bit, in an RGB565, you will need to multiply the grayscale value by two, or left shift by one, for the blue component. </div><br />
<b>The Prototype</b><br />
<div style="text-align: justify;">I haven't tested the new board yet, so it's not in the repository. There's however a new breakout, the one used in the prototype, the new breakout is basically the same except that this one is meant to be connected as module, not to the breadboard, and I've removed the crystal oscillator and instead exposed the EXTCLK pin to be controlled by a PWM. This is the prototype in action:<br />
</div><div style="text-align: center;"><iframe allowfullscreen='allowfullscreen' webkitallowfullscreen='webkitallowfullscreen' mozallowfullscreen='mozallowfullscreen' width='320' height='266' src='https://www.youtube.com/embed/9VUUDDDEpvM?feature=player_embedded' frameborder='0'></iframe> </div><b> Eagle files and </b><b>source code</b> <pre class="brush:plain">hg clone https://code.google.com/p/nrfcam/</pre></div>muxhttp://www.blogger.com/profile/07901500843676691342noreply@blogger.com5tag:blogger.com,1999:blog-7822883683244244182.post-33076266506138493852011-10-24T00:08:00.001+02:002013-10-14T21:53:58.538+02:00Cortex-M3 Exception Vector Checksum<div dir="ltr" style="text-align: left;" trbidi="on"><div dir="ltr" style="text-align: left;" trbidi="on"><div style="text-align: justify;">The 7th entry of the Cortex-M3 exception vector is reserved for the 2's complement of the checksum of the exception vector. At run time the bootloader computes the checksum again and adds it to the one stored in the exception vector, if the result equals zero it starts executing the user code.</div><br />
<div style="text-align: justify;">The checksum is usually computed by the software that flashes the binary like FashMagic or openocd, if you're using openocd like me, you may see this message every time you flash a binary:</div><div style="text-align: justify;"><pre class="brush:plain">Warn : Verification will fail since checksum in image (0x00000000) to be
written to flash is different from calculated vector checksum (0xeffc59e6).
Warn : To remove this warning modify build tools on developer PC to inject
correct LPC vector checksum.</pre></div><div style="text-align: justify;">The code will run normally, because openocd computes the checksum for you, but it's just too annoying, so I wrote the following small utility to compute the checksum and inject it into the binary, it's called from the Makefile before running openocd to flash the binary:</div></div><pre class="brush:cpp">#include <stdio.h>
int main(int argc, char **argv)
{
if (argc == 1) {
printf("usage: cm3_checksum <bin>\n");
return 1;
}
FILE *file;
if ((file = fopen(argv[1], "r+")) == NULL) {
return 1;
}
/* The checksum of the exception vector */
unsigned int i, n, checksum=0;
for (i=0; i<7; i++) {
fread(&n, 4, 1, file);
checksum += n;
}
/* The 2's complement of the checksum */
checksum = -checksum;
printf("checksum: 0x%X\n", checksum);
/* write back the checksum to location 7 */
fseek(file, 0x1c, SEEK_SET);
fwrite(&checksum, 4, 1, file);
fclose(file);
return 0;
}
</pre></div>muxhttp://www.blogger.com/profile/07901500843676691342noreply@blogger.com12tag:blogger.com,1999:blog-7822883683244244182.post-71481831653006970972011-07-12T06:46:00.001+02:002013-07-16T01:05:50.722+02:00Delay Slots<div dir="ltr" style="text-align: left;" trbidi="on"><div style="text-align: justify;">Delay slots are an artifact of some early pipelined architectures in which pipeline hazards were not handled explicitly. I was puzzled for while by some unexpected assembly produced by gcc while working on my own implementation of the MIPS ISA, further investigation yielded the following results about the branch delay and the load delay slots, both of them occurred in early MIPS architectures.</div><br />
<b>Load Delay Slot</b><br />
<div style="text-align: justify;">The load word instruction (lw) loads a word from memory to the specified register, because of the pipelined nature of the architecture, the next instruction(s) execute concurrently with the current instruction, if the following instruction uses the lw destination register as one of its source registers then it cannot continue before the lw data is fetched from memory and written back to the destination register, otherwise, it will read invalid data. For example, in the following code snippet, the add instruction uses $s0 as one of its source registers, if it were to read $s0 before it's written by the lw instruction it would read the old value of $s0.</div><pre class="brush:python">main:
lw $s0, 4($0)
add $s2, $s0, $0
</pre><br />
<div style="text-align: justify;">This peculiarity is called a Hazard, specifically a data hazard. Data hazards can be handled by either stalling the pipeline or with register forwarding. The pipeline can be stalled with a nop, which is sometimes called a bubble because it propagates through the whole pipeline causing every stage to be idle. Register Forwarding, on the other hand, forwards the result of an instruction from the current stage to the previous stage (i.e to the next instruction) bypassing the pipeline, the following image shows register forwarding from the first instruction to the second and third, the following instructions can read the register normally:<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhiTqMdKUpGn0l1w2icPCTZF8MSFPBg6iSjFhH1o3Y1g-DdKvftNZHtPXu38g46uirvvkkB-w-y2vKe6RlWQjX8I_FQIMw3v_L1JiF-5lHHAU9ZwCLPENr75OPaDjJcaLoM6qjmvke2_7s/s1600/pipeline.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="208" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhiTqMdKUpGn0l1w2icPCTZF8MSFPBg6iSjFhH1o3Y1g-DdKvftNZHtPXu38g46uirvvkkB-w-y2vKe6RlWQjX8I_FQIMw3v_L1JiF-5lHHAU9ZwCLPENr75OPaDjJcaLoM6qjmvke2_7s/s400/pipeline.png" width="400" /></a></div><div class="separator" style="clear: both; text-align: center;"></div><br />
<div class="separator" style="clear: both; text-align: center;"></div><div class="separator" style="clear: both; text-align: center;"></div></div><div style="text-align: justify;">If the hazard is not handled by the data path, the assembler introduces a delay slot which it later fills with either a nop or by re-ordering the instructions, if it can find something useful to fill in the delay slot with. This is what the disassembled code looks like, the assembler fills the delay slot with a nop:</div><pre class="brush:python">00000000 <main>:
0: 8c100004 lw s0,4(zero)
4: 00000000 nop
8: 02008820 add s1,s0,zero
</pre><div style="text-align: justify;"><br />
If we change the add instruction such that it's not dependant on the lw instruction any more, therefore it can execute in parallel, the assembler removes the nop:</div><pre class="brush:python">00000000 <main>:
0: 8c100004 lw s0,4(zero)
4: 02408820 add s1,s2,zero
</pre><br />
<b>Branch Delay Slot</b><br />
<div style="text-align: justify;">Similarly, due to the parallel execution of the instructions, by the time the branch target gets resolved the following instruction would have been fetched, in other words, the instruction following a branch always executes whether the branch is taken or not.<br />
<br />
This type of hazard is called a control hazard, modern architectures use a branch predictor to avoid flushing the pipeline, it gets flushed only in the case of a branch misprediction. Early MIPS didn't handle this, obviously, and the assembler needed to introduce yet another delay slot and fills it with either a nop or, if possible, by re-ordering the instructions. In the following example, if the branch were to execute without a delay slot it would execute the last addi instruction at each step of the loop which would never finish (because $s0 and $s2 are both incremented)</div><pre class="brush:python">loop:
addi $s0, $0, 1
add $s1, $s0, $0
bne $s0, $s2, loop
addi $s2, $0, 1
</pre><div style="text-align: justify;">Note that the second add instruction does not affect the branch target so its order is irrelevant and can come before or after the branch, the following disassembled code shows how the assembler re-ordered the instructions and used the add instruction to fill the delay slot:</div><pre class="brush:python">00000000 <loop>:
0: 20100001 addi s0,zero,1
4: 1612fffe bne s0,s2,0 <loop>
8: 02008820 add s1,s0,zero
c: 20120001 addi s2,zero,1
</pre><div style="text-align: justify;">If the branch was, otherwise, dependant on the add instruction, its order will not be changed and the assembler will use a nop to fill the delay slot instead. If we modify the and instruction and have it write to $s2 making the branch dependant on the and result it will use a nop:</div><pre class="brush:python">00000000 <loop>:
0: 20100001 addi s0,zero,1
4: 2012ffff addi s2,zero,-1
8: 1612fffd bne s0,s2,0 <loop>
c: 00000000 nop
10: 20120001 addi s2,zero,1
</pre></div>muxhttp://www.blogger.com/profile/07901500843676691342noreply@blogger.com2tag:blogger.com,1999:blog-7822883683244244182.post-68530119529274139882011-04-30T02:12:00.001+02:002013-07-16T01:01:59.052+02:00Pimp My Hexbug!<div dir="ltr" style="text-align: left;" trbidi="on"><div dir="ltr" style="text-align: left;" trbidi="on"><div style="text-align: justify;">What is a Hexbug you ask ? Well, a Hexbug is a line of micro robotic creatures! Sounds fancy doesn't it ? actually it's quite boring, if you ask me, for example, mine just walks around until it hits something and then it turns around and that's basically just about it! </div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEixChYwTVc10HlLEjoispsM3wX3fn09ZBMADd6kD0i7EJeecus-O9fpq6ThxE2vmUVzEJF0qtIOST7A_yqYq_TXueM4oxR6o6HzofBXmnUwZ3YvSH60u0ilbESUNdN0E3o3uikfiyuc0fU/s1600/hexbug.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="254" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEixChYwTVc10HlLEjoispsM3wX3fn09ZBMADd6kD0i7EJeecus-O9fpq6ThxE2vmUVzEJF0qtIOST7A_yqYq_TXueM4oxR6o6HzofBXmnUwZ3YvSH60u0ilbESUNdN0E3o3uikfiyuc0fU/s320/hexbug.jpg" width="320" /></a></div><div style="text-align: justify;">That's why I've decided to reuse the mechanical parts and boost the bug a bit. So I designed a small wireless board to control my Hexbug. This is the modified Hexbug, I call it nrfbug </div><br />
<div class="separator" style="clear: both; text-align: center;"></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjEd2lcc8ksbR-_COyWAHpFbzWl10BcXpeeAvCqLVWEIxY8b4mC4JR-K72y6pt903Xz4swlq2hPUSLmC8Z-HlgSOkaw9RdRgU19nut0udRFFy1noLQKGtBFTUzxHdv6ccEXa_sZmeKBw8o/s1600/DSC02895.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="240" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjEd2lcc8ksbR-_COyWAHpFbzWl10BcXpeeAvCqLVWEIxY8b4mC4JR-K72y6pt903Xz4swlq2hPUSLmC8Z-HlgSOkaw9RdRgU19nut0udRFFy1noLQKGtBFTUzxHdv6ccEXa_sZmeKBw8o/s320/DSC02895.JPG" width="320" /></a></div><br />
Now let's get down to the glorious details...<br />
<br />
<b>Wireless Link</b><br />
<div style="text-align: justify;">For the wireless link I used the nRF24L01+ chip from <a href="http://www.nordicsemi.com/">Nordic</a>. This chip is by far the most amazing VLSI chip that I have ever seen, it certainly deserves it's own post, however briefly, the nRF24L01+ chip is a 2.4Ghz wireless chip that implements a packet-based low level datalink layer protocol (similar to Ethernet) with dynamic payload length, auto-retransmission, auto-ack, CRC, FIFOs, multiple transmitters, multiple receivers (broadcast). Newer chips even has an integrated USB controller, an improved 8051 core and an AES engine! it's just amazing!</div><div style="text-align: justify;"><br />
</div><div style="text-align: justify;">I wrote a library for this chip, originally wrote it for the LPC1768, it's still a work in progress, but it does the job, link in downloads section.</div><br />
<b>Processing</b><br />
<div style="text-align: justify;">For the MCU I used an atmega328 running on the internal RC oscillator at 8Mhz, the board has the SPI interface broken out to the header, it's not really compatible with any programmer, that I know of, I just use avrdude and an FTDI chip to bitbang the ihex file to flash.</div><br />
<b>Motor</b><br />
<div style="text-align: justify;">On board is an H-bridge to control the motor direction, when the current flows in one direction the nrfbug moves both sets of legs, when it moves in the other direction it moves just one causing it to rotate. The bridge has fly-back diodes for protection. The h-bridge is controlled with two GPIO pins on the MCU.<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhx0g9TBRLhUwDRp1Br9B3hntaSwiokqfVJr_nhABViIQtqAZwRx21IdtRxAQJd8iVfKNq44uUvSnON84qLpMqG9xgoSKvXgF139MEP9AjCzfuGvphFYsY4l5HFF5BW_tnUOwjvc3ljbEU/s1600/h-bridge.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhx0g9TBRLhUwDRp1Br9B3hntaSwiokqfVJr_nhABViIQtqAZwRx21IdtRxAQJd8iVfKNq44uUvSnON84qLpMqG9xgoSKvXgF139MEP9AjCzfuGvphFYsY4l5HFF5BW_tnUOwjvc3ljbEU/s1600/h-bridge.png" /></a></div><span id="goog_718408183"></span><span id="goog_718408184"></span></div><b> </b><br />
<b>Sensors</b><br />
<div style="text-align: justify;">While I was at it, I throw in an SMD ambient light sensor. The sensor is quite simple, it's basically just a light-sensitive transistor that is read by the ADC.</div><br />
<b>Control</b><br />
<div style="text-align: justify;">At the other end, I use an mbed to send commands to the bug. Connected to the mbed is another Nordic chip and a joystick connected to the ADC to move the bug around.<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhdAD1YnrG1imNFvCAKmGxflRfjlqzLnLwkMfT4KCXMbQl4YPI5JCAEc4o05UON8nXa1_bvocWljN8vsaCWnzEMIEOEg3HGkCi3EvPKZlJPhe2le5lEotrsB4tuEdIexAmzeir02T6MlLM/s1600/DSC02911.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="240" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhdAD1YnrG1imNFvCAKmGxflRfjlqzLnLwkMfT4KCXMbQl4YPI5JCAEc4o05UON8nXa1_bvocWljN8vsaCWnzEMIEOEg3HGkCi3EvPKZlJPhe2le5lEotrsB4tuEdIexAmzeir02T6MlLM/s320/DSC02911.JPG" width="320" /></a></div></div><div style="text-align: justify;"><b>Board</b></div><div style="text-align: justify;">The nrfbug board was designed using Eagle and fabricated at BatchPCB. The first board had a small problem with the chip antenna having ground pours beneath it, according the datasheet it shouldn't! that's the bless of reading the datasheet after you finish your project :), it only affects the range though (and maybe cause more packets to drop), anyway, I fixed it and waiting for the new revision. The new Eagle files are available in the downloads.</div><div style="text-align: justify;"><br />
</div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEia2wIenBeHzPHc9C3dRf4TolDu1pN63d0NmkdEHiBxl2I0JCnPRa2R1YoOgpfHbe5QW6HyPCnaSPlS4o8elJ5MvEx2P60rbrVD0mqLsn3EKf9yDZtJRPuYzI7583BFA9CGDSEYJ3wuX9E/s1600/board.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="205" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEia2wIenBeHzPHc9C3dRf4TolDu1pN63d0NmkdEHiBxl2I0JCnPRa2R1YoOgpfHbe5QW6HyPCnaSPlS4o8elJ5MvEx2P60rbrVD0mqLsn3EKf9yDZtJRPuYzI7583BFA9CGDSEYJ3wuX9E/s320/board.png" width="320" /></a></div><div style="text-align: justify;"><br />
</div><div style="text-align: justify;"><b>nrfbug</b><br />
Finally, the bug in action</div><div style="text-align: justify;"><div class="separator" style="clear: both; text-align: center;"><iframe allowfullscreen='allowfullscreen' webkitallowfullscreen='webkitallowfullscreen' mozallowfullscreen='mozallowfullscreen' width='320' height='266' src='https://www.youtube.com/embed/5hgU4SWwU4k?feature=player_embedded' frameborder='0'></iframe></div>
</div><div style="text-align: justify;"><b>Downloads</b></div>nRF24L01p avr library
<pre class="brush:plain">hg clone https://code.google.com/p/nrf24l01p</pre>nrfbug Eagle files
<pre class="brush:plain">hg clone https://code.google.com/p/nrfbug</pre></div></div>muxhttp://www.blogger.com/profile/07901500843676691342noreply@blogger.com4