stm32 ADC interrupt - stm32f4discovery

I'm studying ADC programming on STM32 F407 Discovery and starting with the simplest case - single conversion. (connected to ADC1)
I'm using StdPeriph In normal case when I don't using interrupt and do it in while(1) in main() everything is working but when I want to trigger Analog to Digital Converter by interrput value of measurement is set to 0
void ADC_Config(){
//purposly ommited
}
void InitializeTimer_OnehundredthSecond(){
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_TimeBaseStructure.TIM_Period =99;
TIM_TimeBaseStructure.TIM_Prescaler = 8399;
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure);
TIM_Cmd(TIM4, ENABLE);
}
void TIM4_NVIC_Config(){
NVIC_InitTypeDef NVIC_InitStructure;
// numer przerwania
NVIC_InitStructure.NVIC_IRQChannel = TIM4_IRQn;
// priorytet główny
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x00;
// subpriorytet
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x00;
// uruchom dany kanał
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
// zapisz wypełnioną strukturę do rejestrów
NVIC_Init(&NVIC_InitStructure);
// wyczyszczenie przerwania od timera 4 (wystąpiło przy konfiguracji timera)
TIM_ClearITPendingBit(TIM4, TIM_IT_Update);
// zezwolenie na przerwania od przepełnienia dla 4
TIM_ITConfig(TIM4, TIM_IT_Update, ENABLE);
}
int j=0;
int volatile ADC_Result=0;
void TIM4_IRQHandler(void)
{
if(TIM_GetITStatus(TIM4, TIM_IT_Update) != RESET)
{
ADC_SoftwareStartConv(ADC1);
TIM_ClearITPendingBit(TIM4, TIM_IT_Update);
}
}
void ADC1_1_IRQHandler(){
while(ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC) == RESET);
ADC_Result = ADC_GetConversionValue(ADC1);
}
int main(){
ADC_Config();
InitializeTimer_OnehundredthSecond();
TIM4_NVIC_Config();
TIM4_IRQHandler();
ADC1_1_IRQHandler();
while(1){
}
}

I think your ADC interrupt handler is never called.
If you look at your startup file (startup_stm32f407xx.s), you can see that the interrupt handler is:
DCD ADC_IRQHandler ; ADC1, ADC2 and ADC3s
In your code, you have:
void ADC1_1_IRQHandler()
which is never called. So your variable stays at 0.
So rename ADC1_1_IRQHandler into ADC_IRQHandler and that should work.
If this does not save your issue, please share the code for ADC_Config.

Here is working code. I've already solved that problem. Invoking IRQ like I did in main is a bad idea.:/
void InitializeTimer_OnehundredthSecond(){
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_TimeBaseStructure.TIM_Period =99;
TIM_TimeBaseStructure.TIM_Prescaler = 8399;
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure);
}
void TIM4_NVIC_Config(){
NVIC_InitTypeDef NVIC_InitStructure;
// numer przerwania
NVIC_InitStructure.NVIC_IRQChannel = TIM4_IRQn;
// priorytet główny
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x00;
// subpriorytet
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x00;
// uruchom dany kanał
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
// zapisz wypełnioną strukturę do rejestrów
NVIC_Init(&NVIC_InitStructure);
// wyczyszczenie przerwania od timera 4 (wystąpiło przy konfiguracji timera)
TIM_ClearITPendingBit(TIM4, TIM_IT_Update);
// zezwolenie na przerwania od przepełnienia dla 4
TIM_ITConfig(TIM4, TIM_IT_Update, ENABLE);
}
int j=0;
int volatile ADC_Result=0;
void TIM4_IRQHandler(void)
{
if(TIM_GetITStatus(TIM4, TIM_IT_Update) != RESET)
{
ADC_SoftwareStartConv(ADC1);
TIM_ClearITPendingBit(TIM4, TIM_IT_Update);
}
}
void ADC1_1_NVIC_Config(){
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel = ADC_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x00;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x00;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
ADC_ClearITPendingBit(ADC1,ADC_IT_EOC);
ADC_ITConfig(ADC1, ADC_IT_EOC, ENABLE);
}
void ADC_IRQHandler(){
if(ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC) != RESET){
ADC_Result = ADC_GetConversionValue(ADC1);
//ADC_ClearITPendingBit(ADC1,ADC_FLAG_EOC);//<--clear automatically
}
}
int main(){
ADC_Config();
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
ADC1_1_NVIC_Config();
InitializeTimer_OnehundredthSecond();
TIM4_NVIC_Config();
TIM_Cmd(TIM4, ENABLE);
while(1){
}
}

Related

Attempt at STL Container

I am attempting to make a version of std::set using a linked list. I think I have implemented it mostly correctly but I am getting a compile error that I cannot decipher. I would appreciate anyone spotting the error in my code, and or explaining how I would go about tracking down an error like this. Meaning an error that goes far into stl functions.
#include <iterator>
#include <cstddef>
template <typename Type>
struct ListNode{
Type info;
ListNode<Type> * next;
ListNode(Type newInfo, ListNode<Type> * newNext) : info(newInfo), next(newNext){
}
ListNode(ListNode<Type>& L): info(L.info), next(L.next){
}
ListNode<Type>& operator=(ListNode<Type>& L){
info = L->info;
next = L->next;
return this;
}
};
template <typename Type>
class SetList{
ListNode<Type> * head;
ListNode<Type> * tail;
public:
typedef ListNode<Type> value_type;
SetList() : head(nullptr), tail(nullptr){
}
SetList(SetList & s){
}
~SetList(){
//ListNode<Type> * cur = head;
//ListNode<Type> * next = cur;
//while(cur){
// next = cur->next;
// delete cur;
// cur = next;
// }
}
struct iterator{
//traits
typedef std::forward_iterator_tag iterator_category;
typedef iterator self_type;
typedef Type value_type;
typedef Type& reference;
typedef Type* pointer;
typedef ptrdiff_t difference_type;
private:
//rename to ihead
ListNode<Type>* ibuf;
public:
iterator(ListNode<value_type>* node) : ibuf(node){}
self_type& operator++(){ibuf = ibuf->next; return *this;}
self_type operator++(int postfix){
self_type cpy = *this;
ibuf = ibuf->next;
return cpy;
}
reference operator*(){return ibuf->info;}
pointer operator->(){return &ibuf->info;}
self_type operator=(const iterator& it){insert(*it);}
bool operator==(const self_type& rhs) const {return ibuf->info == rhs.ibuf->info;}
bool operator !=(const self_type& rhs) const {return ibuf->info != rhs.ibuf->info;}
};
iterator begin(){ return iterator(head);}
iterator end() { return iterator(nullptr);}
// const_iterator begin() { return const_iterator(head);}
// const_iterator end() { return const_iterator(tail);}
Type operator[](int index){
iterator cur(head);
for(int i = 0; i < index; ++i,++cur){
}
return *cur;
}
SetList<Type>& operator=(const SetList<Type>& s){
head = s.head;
tail = s.tail;
return this;
}
iterator find(Type toFind){
ListNode<Type> * cur = head;
while(cur){
if(cur->info == toFind)
return iterator(cur);
}
return this->end();
}
void insert(Type toInsert){
ListNode<Type>* cur = nullptr;
if(head){
cur = new ListNode<Type>(toInsert, head);
head = cur;
}else{
cur = new ListNode<Type>(toInsert, nullptr);
head = cur;
}
}
};
I am calling elsewhere copy on my set, my copy call works with std::set but not my set.
The error I am getting is as follows.
Hope this isn't too much to ask. You don't even have to read my code, even just input on how to track down large errors like this would be much appreciated.
SetList<Type> should have Type as its value_type, not ListNode<Type>.

How to insert text in CCTextFieldTTF?

I used setString but the string is not updated, so I have to write a CCLabel to show the string, which I feel very weird because showing the user input should be part of the textfield.. Do I missed anything?
I read the test_input example, it uses a CCLabel to show the user input, which I think is a really bad design.
You don't need a Label to show user input.
I have edited the default HelloWorld file with added CCTextFieldttf working example.
This is how your HelloWorld.h file should look
class HelloWorld : public cocos2d::CCLayer, public cocos2d::CCTextFieldDelegate
{
public:
virtual bool init();
static cocos2d::CCScene* scene();
void createTF();
cocos2d::CCTextFieldTTF* tf;
virtual bool ccTouchBegan(CCTouch *pTouch, CCEvent *pEvent);
virtual void ccTouchEnded(CCTouch *pTouch, CCEvent *pEvent);
virtual void registerWithTouchDispatcher();
//CCtextFieldttf delegate begin
virtual bool onTextFieldAttachWithIME(CCTextFieldTTF * pSender);
virtual bool onTextFieldDetachWithIME(CCTextFieldTTF * pSender);
virtual bool onTextFieldInsertText(CCTextFieldTTF * pSender, const char * text, int nLen);
virtual bool onTextFieldDeleteBackward(CCTextFieldTTF * pSender, const char * delText, int nLen);
virtual bool onDraw(CCTextFieldTTF * pSender);
//CCtextFieldttf delegate end
CREATE_FUNC(HelloWorld);
};
This is how your HelloWorld.cpp should be for minimum usage of CCTextFieldttf
CCScene* HelloWorld::scene()
{
// 'scene' is an autorelease object
CCScene *scene = CCScene::create();
// 'layer' is an autorelease object
HelloWorld *layer = HelloWorld::create();
// add layer as a child to scene
scene->addChild(layer);
// return the scene
return scene;
}
// on "init" you need to initialize your instance
bool HelloWorld::init()
{
if ( !CCLayer::init() )
{
return false;
}
this->setTouchEnabled(true);
CCSize visibleSize = CCDirector::sharedDirector()->getVisibleSize();
CCPoint origin = CCDirector::sharedDirector()->getVisibleOrigin();
createTF();
CCLabelTTF* pLabel = CCLabelTTF::create("Hello World", "Arial", 24);
// position the label on the center of the screen
pLabel->setPosition(ccp(origin.x + visibleSize.width/2,
origin.y + visibleSize.height - pLabel->getContentSize().height));
this->addChild(pLabel, 1);
return true;
}
void HelloWorld::createTF()
{
tf = CCTextFieldTTF::textFieldWithPlaceHolder("123", CCSizeMake(100, 100), kCCTextAlignmentCenter, "helvetica", 20);
tf->setColorSpaceHolder(ccWHITE);
tf->setPosition(ccp(200,200));
tf->setHorizontalAlignment(kCCTextAlignmentCenter);
tf->setVerticalAlignment(kCCVerticalTextAlignmentCenter);
tf->setDelegate(this);
addChild(tf);
}
void HelloWorld::registerWithTouchDispatcher()
{
CCDirector* pDirector = CCDirector::sharedDirector();
pDirector->getTouchDispatcher()->addTargetedDelegate(this, 0, false);
}
bool HelloWorld::ccTouchBegan(CCTouch *pTouch, CCEvent *pEvent)
{
CCLog("inside touchbegan");
return true;
}
void HelloWorld::ccTouchEnded(CCTouch *pTouch, CCEvent *pEvent)
{
CCLog("inside touchend");
tf->attachWithIME();
}
bool HelloWorld::onTextFieldAttachWithIME(CCTextFieldTTF * pSender)
{
return false;
}
bool HelloWorld::onTextFieldDetachWithIME(CCTextFieldTTF * pSender)
{
return false;
}
bool HelloWorld::onTextFieldInsertText(CCTextFieldTTF * pSender, const char * text, int nLen)
{
return false;
}
bool HelloWorld::onTextFieldDeleteBackward(CCTextFieldTTF * pSender, const char * delText, int nLen)
{
return false;
}
bool HelloWorld::onDraw(CCTextFieldTTF * pSender)
{
return false;
}
The CCTextFieldDelegate methods are implemented to gain more control over what is entered into CCTextFieldTTF. The only thing that CCTextFieldttf lacks is you have to call CCTextFieldTTF's attachWithIME() method yourself like in the above code it is being called in "ccTouchEnded".
in header
class CustomMultiplayerScene : public PZGBaseMenuScene,public CCIMEDelegate
{
public:
void keyboardWillShow(cocos2d::CCIMEKeyboardNotificationInfo &info);
void keyboardWillHide(cocos2d::CCIMEKeyboardNotificationInfo &info);
void ccTouchesBegan(cocos2d::CCSet *pTouches, cocos2d::CCEvent *pEvent);
};
in .cpp
CCTextFieldTTF *textfield = CCTextFieldTTF::textFieldWithPlaceHolder("Enter Name:", CCSize(480,30), kCCTextAlignmentCenter, "Arial", 12);
// textfield->setAnchorPoint(CCPointZero);
textfield->setPosition(ccp(screenSize.width/2,200));
textfield->setTag(100);
this->addChild(textfield,4);
CCLabelTTF *label = CCLabelTTF::create("ID : ", "", 12);
label->setPosition(ccp(screenSize.width/2,100));
label->setTag(200);
this->addChild(label,4);
implement methods in .cpp
void CustomMultiplayerScene::keyboardWillShow(CCIMEKeyboardNotificationInfo &info)
{
CCLOG("keyboardWillShow");
CCTextFieldTTF *textfield = (CCTextFieldTTF *)this->getChildByTag(100);
textfield->setString("");
}
void CustomMultiplayerScene::keyboardWillHide(CCIMEKeyboardNotificationInfo &info)
{
CCLog("keyboardWillHide");
CCTextFieldTTF *textfield = (CCTextFieldTTF *)this->getChildByTag(100);
CCLabelTTF *label = (CCLabelTTF *)this->getChildByTag(200);
label->setString(textfield->getString());
}
void CustomMultiplayerScene::ccTouchesBegan(cocos2d::CCSet *pTouches, cocos2d::CCEvent *pEvent)
{
CCTouch *pTouch = (CCTouch *)pTouches->anyObject();
CCPoint point = pTouch->getLocationInView();
point = CCDirector::sharedDirector()->convertToGL(point);
CCTextFieldTTF *textfield = (CCTextFieldTTF *)this->getChildByTag(100);
CCRect rect = textfield->boundingBox();
if(rect.containsPoint(point)) {
textfield->attachWithIME();
}
}
CCTextFieldTTF * pTextField = CCTextFieldTTF::textFieldWithPlaceHolder("click here for input",
"Thonburi",
20);
addChild(pTextField);

updating old NPAPI plugin for Maya 2014

I need some advice on how to update an external web browser plugin for Maya 2014 on windows 7. The plugin was last updated in 2008 and works perfectly in an older browser like Firefox 3. However, any later browser (Firefox 3.5 to 26) immediately breaks the plugin.
The error I am getting in firebug is:
Error: Error calling method on NPObject! return MWTObject.execute(CommandText)
I am a complete novice at API programming and am in way over my head on this one. I think the error is being caused by NPP_GetValue getting called 2 times and the plugin not being able to hanlde it. The main.cpp is as follows:
//-
// ==========================================================================
// Copyright 1995,2006,2008 Autodesk, Inc. All rights reserved.
//
// Use of this software is subject to the terms of the Autodesk
// license agreement provided at the time of installation or download,
// or which otherwise accompanies this software in either electronic
// or hard copy form.
// ==========================================================================
//+
#include "mcp.h"
#include "PluginObject.h"
NPNetscapeFuncs *browser;
NPNetscapeFuncs NPNFuncs;
NPError NPP_New(NPMIMEType pluginType, NPP instance, uint16 mode, int16 argc, char* argn[], char* argv[], NPSavedData* saved);
NPError NPP_Destroy(NPP instance, NPSavedData** save);
NPError NPP_SetWindow(NPP instance, NPWindow* window);
NPError NPP_NewStream(NPP instance, NPMIMEType type, NPStream* stream, NPBool seekable, uint16* stype);
NPError NPP_DestroyStream(NPP instance, NPStream* stream, NPReason reason);
int32 NPP_WriteReady(NPP instance, NPStream* stream);
int32 NPP_Write(NPP instance, NPStream* stream, int32 offset, int32 len, void* buffer);
void NPP_StreamAsFile(NPP instance, NPStream* stream, const char* fname);
void NPP_Print(NPP instance, NPPrint* platformPrint);
int16 NPP_HandleEvent(NPP instance, void* event);
void NPP_URLNotify(NPP instance, const char* URL, NPReason reason, void* notifyData);
NPError NPP_GetValue(NPP instance, NPPVariable variable, void *value);
NPError NPP_SetValue(NPP instance, NPNVariable variable, void *value);
char *NPP_GetMIMEDescription(void) {
return "application/x-mcp::MCP Plugin";
}
NPError OSCALL NP_Initialize(NPNetscapeFuncs* pFuncs)
{
if(pFuncs == NULL)
return NPERR_INVALID_FUNCTABLE_ERROR;
if(HIBYTE(pFuncs->version) > NP_VERSION_MAJOR)
return NPERR_INCOMPATIBLE_VERSION_ERROR;
if(pFuncs->size < sizeof(NPNetscapeFuncs))
return NPERR_INVALID_FUNCTABLE_ERROR;
NPNFuncs.size = pFuncs->size;
NPNFuncs.version = pFuncs->version;
NPNFuncs.geturlnotify = pFuncs->geturlnotify;
NPNFuncs.geturl = pFuncs->geturl;
NPNFuncs.posturlnotify = pFuncs->posturlnotify;
NPNFuncs.posturl = pFuncs->posturl;
NPNFuncs.requestread = pFuncs->requestread;
NPNFuncs.newstream = pFuncs->newstream;
NPNFuncs.write = pFuncs->write;
NPNFuncs.destroystream = pFuncs->destroystream;
NPNFuncs.status = pFuncs->status;
NPNFuncs.uagent = pFuncs->uagent;
NPNFuncs.memalloc = pFuncs->memalloc;
NPNFuncs.memfree = pFuncs->memfree;
NPNFuncs.memflush = pFuncs->memflush;
NPNFuncs.reloadplugins = pFuncs->reloadplugins;
NPNFuncs.getJavaEnv = pFuncs->getJavaEnv;
NPNFuncs.getJavaPeer = pFuncs->getJavaPeer;
NPNFuncs.getvalue = pFuncs->getvalue;
NPNFuncs.setvalue = pFuncs->setvalue;
NPNFuncs.invalidaterect = pFuncs->invalidaterect;
NPNFuncs.invalidateregion = pFuncs->invalidateregion;
NPNFuncs.forceredraw = pFuncs->forceredraw;
NPNFuncs.getstringidentifier = pFuncs->getstringidentifier;
NPNFuncs.getstringidentifiers = pFuncs->getstringidentifiers;
NPNFuncs.getintidentifier = pFuncs->getintidentifier;
NPNFuncs.identifierisstring = pFuncs->identifierisstring;
NPNFuncs.utf8fromidentifier = pFuncs->utf8fromidentifier;
NPNFuncs.intfromidentifier = pFuncs->intfromidentifier;
NPNFuncs.createobject = pFuncs->createobject;
NPNFuncs.retainobject = pFuncs->retainobject;
NPNFuncs.releaseobject = pFuncs->releaseobject;
NPNFuncs.invoke = pFuncs->invoke;
NPNFuncs.invokeDefault = pFuncs->invokeDefault;
NPNFuncs.evaluate = pFuncs->evaluate;
NPNFuncs.getproperty = pFuncs->getproperty;
NPNFuncs.setproperty = pFuncs->setproperty;
NPNFuncs.removeproperty = pFuncs->removeproperty;
NPNFuncs.hasproperty = pFuncs->hasproperty;
NPNFuncs.hasmethod = pFuncs->hasmethod;
NPNFuncs.releasevariantvalue = pFuncs->releasevariantvalue;
NPNFuncs.setexception = pFuncs->setexception;
browser = &NPNFuncs;
return NPERR_NO_ERROR;
}
NPError OSCALL NP_GetEntryPoints(NPPluginFuncs* pluginFuncs)
{
if(pluginFuncs == NULL)
return NPERR_INVALID_FUNCTABLE_ERROR;
if(pluginFuncs->size < sizeof(NPPluginFuncs))
return NPERR_INVALID_FUNCTABLE_ERROR;
pluginFuncs->version = (NP_VERSION_MAJOR << 8) | NP_VERSION_MINOR;
pluginFuncs->size = sizeof(NPPluginFuncs);
pluginFuncs->newp = NPP_New;
pluginFuncs->destroy = NPP_Destroy;
pluginFuncs->setwindow = NPP_SetWindow;
pluginFuncs->newstream = NPP_NewStream;
pluginFuncs->destroystream = NPP_DestroyStream;
pluginFuncs->asfile = NPP_StreamAsFile;
pluginFuncs->writeready = NPP_WriteReady;
pluginFuncs->write = NPP_Write;
pluginFuncs->print = NPP_Print;
pluginFuncs->event = NPP_HandleEvent;
pluginFuncs->urlnotify = NPP_URLNotify;
pluginFuncs->getvalue = NPP_GetValue;
pluginFuncs->setvalue = NPP_SetValue;
pluginFuncs->javaClass = NULL;
return NPERR_NO_ERROR;
}
NPError OSCALL NP_Shutdown(void)
{
return NPERR_NO_ERROR;
}
NPError NPP_New(NPMIMEType pluginType, NPP instance, uint16 mode, int16 argc, char* argn[], char* argv[], NPSavedData* saved)
{
if (browser->version >= 14)
instance->pdata = browser->createobject (instance, getPluginClass());
return NPERR_NO_ERROR;
}
NPError NPP_Destroy(NPP instance, NPSavedData** save)
{
PluginObject *obj = (PluginObject *)instance->pdata;
return NPERR_NO_ERROR;
}
NPError NPP_SetWindow(NPP instance, NPWindow* window)
{
PluginObject *obj = (PluginObject *)instance->pdata;
// Do nothing if browser didn't support NPN_CreateObject which would have created the PluginObject.
if (obj != NULL) {
obj->window = window;
}
return NPERR_NO_ERROR;
}
NPError NPP_NewStream(NPP instance, NPMIMEType type, NPStream* stream, NPBool seekable, uint16* stype)
{
return NPERR_NO_ERROR;
}
NPError NPP_DestroyStream(NPP instance, NPStream* stream, NPReason reason)
{
return NPERR_NO_ERROR;
}
int32 NPP_WriteReady(NPP instance, NPStream* stream)
{
return 0;
}
int32 NPP_Write(NPP instance, NPStream* stream, int32 offset, int32 len, void* buffer)
{
return 0;
}
void NPP_StreamAsFile(NPP instance, NPStream* stream, const char* fname)
{
}
void NPP_Print(NPP instance, NPPrint* platformPrint)
{
}
int16 NPP_HandleEvent(NPP instance, void* event)
{
return 0;
}
void NPP_URLNotify(NPP instance, const char* url, NPReason reason, void* notifyData)
{
}
NPError NPP_GetValue(NPP instance, NPPVariable variable, void *value)
{
if(instance == NULL)
return NPERR_INVALID_INSTANCE_ERROR;
if (variable == NPPVpluginScriptableNPObject) {
void **v = (void **)value;
PluginObject *obj = (PluginObject *)instance->pdata;
// Increase reference count
obj->referenceCount++;
*v = obj;
return NPERR_NO_ERROR;
}
return NPERR_GENERIC_ERROR;
}
NPError NPP_SetValue(NPP instance, NPNVariable variable, void *value)
{
return NPERR_GENERIC_ERROR;
}
I don't know if this is enough information to even diagnose the problem, but any help would be much appreciated. If anyone wants to look at the full source code for this plugin it is available in your Maya install directory (if you have Maya, of course) in devkit/externalwebbrowser/windows

rootbeer CUDA example code quantified throughput gain

The following is the rootbeer example code for Nvidia CUDA that I ran on a laptop with Ubuntu 12.04 (Precise) with bumblebee and optirun. The laptop features Nvidia Optimus, hence the optirun. The GPU happens to be a Nvidia GeForce GT 540M which the Nvidia website says has 96 cores. I get almost no throughput gain. What is the problem?
package com.random.test;
import java.util.ArrayList;
import java.util.Formatter;
import java.util.List;
import edu.syr.pcpratts.rootbeer.runtime.Kernel;
import edu.syr.pcpratts.rootbeer.runtime.Rootbeer;
public class ArraySumApp {
final static int numberOfJobs = 1024; // 1024 in the original example
final static int sizeOfArray = 512; // 512 in the original example
final static int theAnswer = 130816;
public int[] sumArrays(List<int[]> arrays) {
List<Kernel> jobs = new ArrayList<Kernel>();
int[] ret = new int[arrays.size()];
for (int i = 0; i < arrays.size(); ++i) {
jobs.add(new ArraySum(arrays.get(i), ret, i));
}
Rootbeer rootbeer = new Rootbeer();
rootbeer.runAll(jobs);
return ret;
}
private static long measureOneJob() {
int[] source = new int[ArraySumApp.sizeOfArray];
int[] destination = new int[1];
for (int i = 0; i < ArraySumApp.sizeOfArray; i++)
source[i] = i;
Kernel job = new ArraySum(source, destination, 0);
ElapsedTimer et = new ElapsedTimer();
job.gpuMethod();
long timeInMs = et.stopInMilliseconds();
System.out.println("measureOneJob " + et.stringInMilliseconds());
assert destination[0] == ArraySumApp.theAnswer : "cosmic rays";
return timeInMs;
}
public static void main(String[] args) {
Helper.assertAssertionEnabled();
// measure the time to do one job
ArraySumApp.measureOneJob();
long oneJob = ArraySumApp.measureOneJob();
ArraySumApp app = new ArraySumApp();
List<int[]> arrays = new ArrayList<int[]>();
// you want 1000s of threads to run on the GPU all at once for speedups
for (int i = 0; i < ArraySumApp.numberOfJobs; ++i) {
int[] array = new int[ArraySumApp.sizeOfArray];
for (int j = 0; j < array.length; ++j) {
array[j] = j;
}
arrays.add(array);
}
ElapsedTimer et = new ElapsedTimer();
int[] sums = app.sumArrays(arrays);
long allJobs = et.stopInMilliseconds();
System.out.println("measureAllJobs " + et.stringInMilliseconds());
double gainFactor = ((double) ArraySumApp.numberOfJobs) * oneJob
/ allJobs;
System.out.println(String.format(
"throughput gain factor %.1f\nthroughput gain %.1f\n",
gainFactor, gainFactor - 1.0d));
// check the number of answers is correct
assert sums.length == ArraySumApp.numberOfJobs : "cosmic rays";
// check they all have the answer
for (int i = 0; i < ArraySumApp.numberOfJobs; i++)
assert sums[i] == ArraySumApp.theAnswer : "cosmic rays";
}
}
class ArraySum implements Kernel {
final static int repetitionFactor = 100000;
private int[] source;
private int[] ret;
private int index;
public ArraySum(int[] src, int[] dst, int i) {
source = src;
ret = dst;
index = i;
}
public void gpuMethod() {
for (int repetition = 0; repetition < ArraySum.repetitionFactor; repetition++) {
int sum = 0;
for (int i = 0; i < source.length; ++i) {
sum += source[i];
}
ret[index] = sum;
}
}
}
class Helper {
private Helper() {
}
static void assertAssertionEnabled() {
try {
assert false;
} catch (AssertionError e) {
return;
}
Helper.noteCosmicRays();
}
static void noteCosmicRays() // programmer design or logic error
{
throw new RuntimeException("cosmic rays");
}
}
class ElapsedTimer {
private org.joda.time.DateTime t0;
private long savedStopInMilliseconds;
public ElapsedTimer() {
this.t0 = new org.joda.time.DateTime();
}
public long stopInMilliseconds() {
return stop();
}
public String stringInMilliseconds() // relies on a saved stop
{
Formatter f = new Formatter();
f.format("%d ms", this.savedStopInMilliseconds);
String s = f.toString();
f.close();
return s;
}
public String stopStringInMilliseconds() {
stop();
return stringInMilliseconds();
}
public String stringInSecondsAndMilliseconds() // relies on a saved stop
{
Formatter f = new Formatter();
f.format("%5.3f s", this.savedStopInMilliseconds / 1000.0d);
String s = f.toString();
f.close();
return s;
}
public String stopStringInSecondsAndMilliseconds() {
stop();
return stringInSecondsAndMilliseconds();
}
public long stopInSeconds() {
return (stop() + 500L) / 1000L; // rounding
}
public String stringInSeconds() // relies on a saved stop
{
Formatter f = new Formatter();
long elapsed = (this.savedStopInMilliseconds + 500L) / 1000L; // rounding
f.format("%d s", elapsed);
String s = f.toString();
f.close();
return s;
}
public String stopStringInSeconds() {
stop();
return stringInSeconds();
}
/**
* This is private. Use the stopInMilliseconds method if this is what you
* need.
*/
private long stop() {
org.joda.time.DateTime t1 = new org.joda.time.DateTime();
savedStopInMilliseconds = t1.getMillis() - this.t0.getMillis();
return savedStopInMilliseconds;
}
}
This is the output:
measureOneJob 110 ms
measureOneJob 26 ms
CudaRuntime2 ctor: elapsedTimeMillis: 609
measureAllJobs 24341 ms
throughput gain factor 1.1
throughput gain 0.1
The rootbeer developer said the example code that takes the sum of array elements is not the best example and an alternative example would show throughput gains.
You can see: https://github.com/pcpratts/rootbeer1/tree/develop/gtc2013/Matrix
This is an example for the 2013 NVIDIA GTC conference. I obtained a 20x speedup over a 4-core Java Matrix Multiply that uses transpose.
The example is a tiled Matrix Multiply using shared memory on the GPU. From the NVIDIA literature, using shared memory is one of the most important apsects of getting good speedups. To use shared memory you have each thread in a block load values into a shared array. Then you have to reuse these shared values several times. This saves the time to fetch from global memory.
A fetch from global memory takes about 200-300 clock cycles and a fetch from shared memory takes about 2-3 clock cycles on the Tesla 2.0 archicture.

JCuda. Reusing already used pointer

I have a trouble working with JCUDA. I have a task to make 1D FFT using CUFFT library, but the result should be multiply on 2. So I decided to make 1D FFT with type CUFFT_R2C. Class responsible for this going next:
public class FFTTransformer {
private Pointer inputDataPointer;
private Pointer outputDataPointer;
private int fftType;
private float[] inputData;
private float[] outputData;
private int batchSize = 1;
public FFTTransformer (int type, float[] inputData) {
this.fftType = type;
this.inputData = inputData;
inputDataPointer = new CUdeviceptr();
JCuda.cudaMalloc(inputDataPointer, inputData.length * Sizeof.FLOAT);
JCuda.cudaMemcpy(inputDataPointer, Pointer.to(inputData),
inputData.length * Sizeof.FLOAT, cudaMemcpyKind.cudaMemcpyHostToDevice);
outputDataPointer = new CUdeviceptr();
JCuda.cudaMalloc(outputDataPointer, (inputData.length + 2) * Sizeof.FLOAT);
}
public Pointer getInputDataPointer() {
return inputDataPointer;
}
public Pointer getOutputDataPointer() {
return outputDataPointer;
}
public int getFftType() {
return fftType;
}
public void setFftType(int fftType) {
this.fftType = fftType;
}
public float[] getInputData() {
return inputData;
}
public int getBatchSize() {
return batchSize;
}
public void setBatchSize(int batchSize) {
this.batchSize = batchSize;
}
public float[] getOutputData() {
return outputData;
}
private void R2CTransform() {
cufftHandle plan = new cufftHandle();
JCufft.cufftPlan1d(plan, inputData.length, cufftType.CUFFT_R2C, batchSize);
JCufft.cufftExecR2C(plan, inputDataPointer, outputDataPointer);
JCufft.cufftDestroy(plan);
}
private void C2CTransform(){
cufftHandle plan = new cufftHandle();
JCufft.cufftPlan1d(plan, inputData.length, cufftType.CUFFT_C2C, batchSize);
JCufft.cufftExecC2C(plan, inputDataPointer, outputDataPointer, fftType);
JCufft.cufftDestroy(plan);
}
public void transform(){
if (fftType == JCufft.CUFFT_FORWARD) {
R2CTransform();
} else {
C2CTransform();
}
}
public float[] getFFTResult() {
outputData = new float[inputData.length + 2];
JCuda.cudaMemcpy(Pointer.to(outputData), outputDataPointer,
outputData.length * Sizeof.FLOAT, cudaMemcpyKind.cudaMemcpyDeviceToHost);
return outputData;
}
public void releaseGPUResources(){
JCuda.cudaFree(inputDataPointer);
JCuda.cudaFree(outputDataPointer);
}
public static void main(String... args) {
float[] inputData = new float[65536];
for(int i = 0; i < inputData.length; i++) {
inputData[i] = (float) Math.sin(i);
}
FFTTransformer transformer = new FFTTransformer(JCufft.CUFFT_FORWARD, inputData);
transformer.transform();
float[] result = transformer.getFFTResult();
HilbertSpectrumTicksKernelInvoker.multiplyOn2(transformer.getOutputDataPointer(), inputData.length+2);
transformer.releaseGPUResources();
}
}
Method which responsible for multiplying uses cuda kernel function.
Java method code:
public static void multiplyOn2(Pointer inputDataPointer, int dataSize){
// Enable exceptions and omit all subsequent error checks
JCudaDriver.setExceptionsEnabled(true);
// Create the PTX file by calling the NVCC
String ptxFileName = null;
try {
ptxFileName = FileService.preparePtxFile("resources\\HilbertSpectrumTicksKernel.cu");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// Initialize the driver and create a context for the first device.
cuInit(0);
CUdevice device = new CUdevice();
cuDeviceGet(device, 0);
CUcontext context = new CUcontext();
cuCtxCreate(context, 0, device);
// Load the ptx file.
CUmodule module = new CUmodule();
cuModuleLoad(module, ptxFileName);
// Obtain a function pointer to the "add" function.
CUfunction function = new CUfunction();
cuModuleGetFunction(function, module, "calcSpectrumSamples");
// Set up the kernel parameters: A pointer to an array
// of pointers which point to the actual values.
int N = (dataSize + 1) / 2 + 1;
int pair = (dataSize + 1) % 2 > 0 ? 1 : -1;
Pointer kernelParameters = Pointer.to(Pointer.to(inputDataPointer),
Pointer.to(new int[] { dataSize }),
Pointer.to(new int[] { N }), Pointer.to(new int[] { pair }));
// Call the kernel function.
int blockSizeX = 128;
int gridSizeX = (int) Math.ceil((double) dataSize / blockSizeX);
cuLaunchKernel(function, gridSizeX, 1, 1, // Grid dimension
blockSizeX, 1, 1, // Block dimension
0, null, // Shared memory size and stream
kernelParameters, null // Kernel- and extra parameters
);
cuCtxSynchronize();
// Allocate host output memory and copy the device output
// to the host.
float freq[] = new float[dataSize];
cuMemcpyDtoH(Pointer.to(freq), (CUdeviceptr)inputDataPointer, dataSize
* Sizeof.FLOAT);
And the kernel function is next:
extern "C"
__global__ void calcSpectrumSamples(float* complexData, int dataSize, int N, int pair) {
int i = threadIdx.x + blockIdx.x * blockDim.x;
if(i >= dataSize) return;
complexData[i] = complexData[i] * 2;
}
But when I'm trying to pass the pointer which points to the result of FFT (in device memory) to the multiplyOn2 method, it throws the exception on cuCtxSynchronize() call. Exception:
Exception in thread "main" jcuda.CudaException: CUDA_ERROR_UNKNOWN
at jcuda.driver.JCudaDriver.checkResult(JCudaDriver.java:263)
at jcuda.driver.JCudaDriver.cuCtxSynchronize(JCudaDriver.java:1709)
at com.ifntung.cufft.HilbertSpectrumTicksKernelInvoker.multiplyOn2(HilbertSpectrumTicksKernelInvoker.java:73)
at com.ifntung.cufft.FFTTransformer.main(FFTTransformer.java:123)
I was trying to do the same using Visual Studion C++ and there no problems with this. Could you please help me.
P.S.
I can solve this prolem, but I need to copy data from device memory to host memory and then copy back with creating new pointers every time before calling new cuda functions, which slows my program executing.
Where exactly does the error occurs at which line?
The Cuda error can also be a previous error.
Why do you use Pointer.to(inputDataPointer), you already have that device pointer. Now you pass a pointer to the device pointer to the device?
Pointer kernelParameters = Pointer.to(Pointer.to(inputDataPointer),
I also recommend to use "this" qualifier or any other marking to detect instance variables. I hate and refuse to look through code, especially as nested and long as your example if I cannot see which scope the variable in methods have trying to debug it by just reading it.
I don't wanna ask myself always where the hell comes this variable from.
If a complex code in a question at SO is not formatted properly I don't read it.